<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def set_default_config(modules, params=None, yaml=None, filename=None, config=None, validate=True):
 """Set up global configuration for tests and noninteractive tools. `modules` is an iterable of :class:`yakonfig.Configurable` objects, or anything equivalently typed. This function iterates through those objects to produce a default configuration, reads `yaml` as though it were the configuration file, and fills in any values from `params` as though they were command-line arguments. The resulting configuration is set as the global configuration. :param modules: modules or Configurable instances to use :type modules: iterable of :class:`~yakonfig.Configurable` :param dict params: dictionary of command-line argument key to values :param str yaml: global configuration file :param str filename: location of global configuration file :param dict config: global configuration object :param bool validate: check configuration after creating :return: the new global configuration :returntype: dict """

    if params is None:
        params = {}

    # Get the configuration from the file, or from params['config']
    file_config = {}
    if yaml is None and filename is None and config is None:
        if 'config' in params and params['config'] is not None:
            filename = params['config']
    if yaml is not None or filename is not None or config is not None:
        if yaml is not None:
            file_config = yaml_mod.load(StringIO(yaml))
        elif filename is not None:
            with open(filename, 'r') as f:
                file_config = yaml_mod.load(f)
        elif config is not None:
            file_config = config

    # First pass: set up to call replace_config()
    # Assemble the configuration from defaults + file + arguments
    base_config = copy.deepcopy(file_config)
    create_config_tree(base_config, modules)
    fill_in_arguments(base_config, modules, params)
    default_config = assemble_default_config(modules)
    base_config = overlay_config(default_config, base_config)

    # Replace the modules list (accommodate external modules)
    def replace_module(config, m):
        name = getattr(m, 'config_name')
        c = config.get(name, {})
        if hasattr(m, 'replace_config'):
            return getattr(m, 'replace_config')(c, name)
        return m
    modules = [replace_module(base_config, m) for m in modules]

    # Reassemble the configuration again, this time reaching out to
    # the environment
    base_config = file_config
    create_config_tree(base_config, modules)
    fill_in_arguments(base_config, modules, params)
    do_config_discovery(base_config, modules)
    default_config = assemble_default_config(modules)
    base_config = overlay_config(default_config, file_config)
    fill_in_arguments(base_config, modules, params)

    # Validate the configuration
    if validate and len(modules) > 0:
        mod = modules[-1]
        checker = getattr(mod, 'check_config', None)
        if checker is not None:
            with _temporary_config():
                set_global_config(base_config)
                checker(base_config[mod.config_name], mod.config_name)

    # All done, normalize and set the global configuration
    normalize_config(base_config, modules)
    set_global_config(base_config)
    return base_config