def set_config(self, full_config, extra_data):
    
        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])
        
        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']]['model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(full_config, None, self.config['global'], 
            mureilbase.ConfigurableInterface)    
        self.global_config = self.global_calc.get_config()

        # Now check the dispatch_order, to get a list of the generators
        for gen in self.config['dispatch_order']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()
        
        self.dispatch_order = self.config['dispatch_order']
        
        # Set up the data class and get the data
        self.data = mureilbuilder.create_instance(full_config, self.global_config, self.config['data'], 
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config({'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        # Instantiate the generator objects, set their data, determine their param requirements
        param_count = 0
        self.gen_list = {}
        self.gen_params = {}

        for i in range(len(self.dispatch_order)):
            gen_type = self.dispatch_order[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(full_config, self.global_config, 
                self.config[gen_type], singlepassgenerator.SinglePassGeneratorBase)
            self.gen_list[gen_type] = gen

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)

            # Determine how many parameters this generator requires and
            # allocate the slots in the params list
            params_req = gen.get_param_count()
            if (params_req == 0):
                self.gen_params[gen_type] = (0, 0)
            else:
                self.gen_params[gen_type] = (param_count, 
                    param_count + params_req)
            param_count += params_req
        
        self.param_count = param_count
        
        self.is_configured = True
    def test_simple(self):
        demand_config = {
            'data_name': 'demand_data',
            'node_list_name': 'demand_data_hdr',
            'bid_price': {
                2010: 10000,
                2020: 20000
            },
            'scale': {
                2010: 1.0,
                2030: 1.5
            }
        }

        data_config = {
            'ts_csv_list': 'demand_data',
            'demand_data_file': 'short_data.csv'
        }

        run_periods = [2010, 2020, 2030]

        try:
            self.data.set_config(data_config)
            self.demand.set_config(demand_config, run_periods=run_periods)

            mureilbuilder.supply_single_pass_data(self.demand, self.data,
                                                  'demand')

        except mureilexception.MureilException as me:
            print me.msg
            self.assertEqual(False, True)

        exp_names = ['DAT1', 'DAT2', 'DAT3']
        names = self.demand.get_node_names()
        self.assertEqual(names, exp_names)

        exp_data = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
        data = self.demand.get_data(2010)
        self.assertTrue(numpy.allclose(data, exp_data))

        data = self.demand.get_data(2030)
        self.assertTrue(numpy.allclose(data, exp_data * 1.5))

        bid = self.demand.get_bid_prices(2010)
        self.assertTrue(numpy.allclose(bid, [10000, 10000, 10000]))

        bid = self.demand.get_bid_prices(2030)
        self.assertTrue(numpy.allclose(bid, [20000, 20000, 20000]))

        self.assertEqual(self.data.ts_length, 4)
    def test_simple(self):
        demand_config = {
            'data_name': 'demand_data',
            'node_list_name': 'demand_data_hdr',
            'bid_price': {2010: 10000, 2020: 20000},
            'scale': {2010: 1.0, 2030: 1.5}
        }

        data_config = {
            'ts_csv_list' : 'demand_data',
            'demand_data_file' : 'short_data.csv'
        }
        
        run_periods = [2010, 2020, 2030]
        
        try:
            self.data.set_config(data_config)
            self.demand.set_config(demand_config, run_periods=run_periods)

            mureilbuilder.supply_single_pass_data(self.demand, self.data, 'demand')

        except mureilexception.MureilException as me:
            print me.msg
            self.assertEqual(False, True)    

        exp_names = ['DAT1','DAT2','DAT3']
        names = self.demand.get_node_names()
        self.assertEqual(names, exp_names)

        exp_data = numpy.array([[1,2,3],
            [4,5,6],[7,8,9],[10,11,12]])
        data = self.demand.get_data(2010)
        self.assertTrue(numpy.allclose(data, exp_data))

        data = self.demand.get_data(2030)
        self.assertTrue(numpy.allclose(data, exp_data * 1.5))

        bid = self.demand.get_bid_prices(2010)
        self.assertTrue(numpy.allclose(bid, [10000, 10000, 10000]))

        bid = self.demand.get_bid_prices(2030)
        self.assertTrue(numpy.allclose(bid, [20000, 20000, 20000]))
 
        self.assertEqual(self.data.ts_length, 4)
    def set_config(self, full_config, extra_data):

        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])

        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']][
                'model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(
            full_config, None, self.config['global'],
            mureilbase.ConfigurableInterface)
        self.global_config = self.global_calc.get_config()

        # Now check the dispatch_order, to get a list of the generators
        for gen in self.config['dispatch_order']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()

        self.dispatch_order = self.config['dispatch_order']

        # Set up the data class and get the data, and compute the global parameters
        self.data = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['data'],
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config(
            {'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        # Instantiate the transmission model
        if self.config['transmission'] in full_config:
            self.transmission = mureilbuilder.create_instance(
                full_config, self.global_config, self.config['transmission'],
                configurablebase.ConfigurableMultiBase,
                self.config['run_periods'])
            mureilbuilder.supply_single_pass_data(self.transmission, self.data,
                                                  self.config['transmission'])
        else:
            self.transmission = None

        # Instantiate the generator objects, set their data, determine their param requirements
        param_count = 0
        self.gen_list = {}
        self.gen_params = {}

        run_period_len = len(self.config['run_periods'])
        start_values_min = numpy.array([[]]).reshape(run_period_len, 0)
        start_values_max = numpy.array([[]]).reshape(run_period_len, 0)

        for i in range(len(self.dispatch_order)):
            gen_type = self.dispatch_order[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(
                full_config, self.global_config, self.config[gen_type],
                txmultigeneratorbase.TxMultiGeneratorBase,
                self.config['run_periods'])
            self.gen_list[gen_type] = gen

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)

            # Determine how many parameters this generator requires and
            # allocate the slots in the params list
            params_req = gen.get_param_count()
            if (params_req == 0):
                self.gen_params[gen_type] = (0, 0)
            else:
                self.gen_params[gen_type] = (param_count,
                                             param_count + params_req)

                start_values_min, start_values_max = mureilbuilder.add_param_starts(
                    gen.get_param_starts(), params_req, self.global_config,
                    run_period_len, start_values_min, start_values_max)

            param_count += params_req

        start_values_min = start_values_min.reshape(run_period_len *
                                                    param_count)
        start_values_max = start_values_max.reshape(run_period_len *
                                                    param_count)

        self.param_count = param_count
        # Check that run_periods increases by time_period_yrs
        self.run_periods = self.config['run_periods']
        if len(self.run_periods) > 1:
            run_period_diffs = numpy.diff(self.run_periods)
            if (not (min(run_period_diffs)
                     == self.global_config['time_period_yrs'])
                    or not (max(run_period_diffs)
                            == self.global_config['time_period_yrs'])):
                raise mureilexception.ConfigException(
                    'run_periods must be separated by time_period_yrs', {})

        self.period_count = len(self.run_periods)
        self.total_param_count = param_count * self.period_count

        # Check if 'extra_data' has been provided, as a full gene to start at.
        # extra_data needs to be a dict with entry 'start_gene' that is a list
        # of integer values the same length as param_count.
        if extra_data is not None:
            if 'start_gene' in extra_data:
                if not (len(start_values_min) == self.total_param_count):
                    msg = (
                        'extra_data of start_gene passed to txmultimastersimple. '
                        + 'Length expected = {:d}, found = {:d}'.format(
                            self.total_param_count, len(start_values_min)))
                    raise mureilexception.ConfigException(msg, {})

                start_values_min = extra_data['start_gene']
                start_values_max = extra_data['start_gene']

        # Instantiate the genetic algorithm
        mureilbuilder.check_section_exists(full_config,
                                           self.config['algorithm'])
        algorithm_config = full_config[self.config['algorithm']]
        algorithm_config['min_len'] = algorithm_config[
            'max_len'] = self.total_param_count
        algorithm_config['start_values_min'] = start_values_min
        algorithm_config['start_values_max'] = start_values_max
        algorithm_config['gene_test_callback'] = self.gene_test
        self.algorithm = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['algorithm'],
            mureilbase.ConfigurableInterface)

        self.is_configured = True
Beispiel #5
0
    def set_config(self, full_config, extra_data):
    
        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])
        
        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']]['model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(full_config, None, self.config['global'], 
            mureilbase.ConfigurableInterface)    
        self.global_config = self.global_calc.get_config()

        # Now check the list of the generators
        for gen in self.config['generators']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()
        
        self.generators = self.config['generators']
        
        # Set up the data class and get the data, and compute the global parameters
        self.data = mureilbuilder.create_instance(full_config, self.global_config, self.config['data'], 
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config({'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        ## The master here takes 'global' variables, if needed and available, to get at the carbon_price_m,
        ## variable_cost_mult and time_scale_up_mult values, which it then expands to all time periods,
        ## for use later.
        for param_name in ['carbon_price_m', 'variable_cost_mult', 'time_scale_up_mult']:
            if (param_name not in self.config) and (param_name in self.global_config):
                self.config[param_name] = self.global_config[param_name]
        self.config_spec += [('carbon_price_m', float, None), ('variable_cost_mult', float, None),
            ('time_scale_up_mult', float, None)]
        self.check_config()
        self.expand_config(self.config['run_periods'])

        # Now instantiate the demand model
        self.demand = mureilbuilder.create_instance(full_config, self.global_config, 
            self.config['demand'], configurablebase.ConfigurableMultiBase,
            self.config['run_periods'])

        # Supply data to the demand model
        mureilbuilder.supply_single_pass_data(self.demand, self.data, 'demand')

        # And instantiate the transmission model
        self.transmission = mureilbuilder.create_instance(full_config, self.global_config,
            self.config['transmission'], configurablebase.ConfigurableMultiBase,
            self.config['run_periods'])
        
        mureilbuilder.check_subclass(self.transmission, 
            interfacesflowmaster.InterfaceTransmission)

        # Instantiate the generator objects, set their data, determine their param requirements,
        # and separate by dispatch type.
        param_count = 0
        
        # gen_list, gen_params are indexed by position in self.generators
        self.gen_list = [None] * len(self.generators)
        self.gen_params = [None] * len(self.generators)
        
        self.semisch_list = []
        self.instant_list = []
        self.ramp_list = []
        
        run_period_len = len(self.config['run_periods'])
        start_values_min = numpy.array([[]]).reshape(run_period_len, 0)
        start_values_max = numpy.array([[]]).reshape(run_period_len, 0)

        for i in range(len(self.generators)):
            gen_type = self.generators[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(full_config, self.global_config, 
                self.config[gen_type], txmultigeneratorbase.TxMultiGeneratorBase,
                self.config['run_periods'])
                
            self.gen_list[i] = gen

            gen_details = gen.get_details()
            gen_dispatch = gen_details['dispatch']
            
            if (gen_dispatch == 'semischeduled'):
                self.semisch_list.append(i)
                mureilbuilder.check_subclass(gen, interfacesflowmaster.InterfaceSemiScheduledDispatch)
            elif (gen_dispatch == 'instant'):
                self.instant_list.append(i)
                mureilbuilder.check_subclass(gen, interfacesflowmaster.InterfaceInstantDispatch)
            elif (gen_dispatch == 'ramp'):
                self.ramp_list.append(i)
                mureilbuilder.check_subclass(gen, interfacesflowmaster.InterfaceRampDispatch)
                msg = ("Generator " + gen_type + " has dispatch type ramp, which is not yet implemented")
                raise mureilexception.ConfigException(msg, {})            
            else:
                msg = ("Generator " + gen_type + " has dispatch type " + gen_dispatch + 
                    " which is not one of semischeduled, instant or ramp.")
                raise mureilexception.ConfigException(msg, {})
            
            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)
    
            # Determine how many parameters this generator requires and
            # allocate the slots in the params list
            params_req = gen.get_param_count()
            if (params_req == 0):
                self.gen_params[i] = (0, 0)
            else:
                self.gen_params[i] = (param_count, 
                    param_count + params_req)

                start_values_min, start_values_max = mureilbuilder.add_param_starts(
                    gen.get_param_starts(), params_req, self.global_config,
                    run_period_len, start_values_min, start_values_max)
                    
            param_count += params_req

        start_values_min = start_values_min.reshape(run_period_len * param_count)
        start_values_max = start_values_max.reshape(run_period_len * param_count)

        self.param_count = param_count
        # Check that run_periods increases by time_period_yrs
        self.run_periods = self.config['run_periods']
        if len(self.run_periods) > 1:
            run_period_diffs = numpy.diff(self.run_periods)
            if (not (min(run_period_diffs) == self.global_config['time_period_yrs']) or
                not (max(run_period_diffs) == self.global_config['time_period_yrs'])):
                raise mureilexception.ConfigException('run_periods must be separated by time_period_yrs', {})

        self.period_count = len(self.run_periods)
        self.total_param_count = param_count * self.period_count

        # Check if 'extra_data' has been provided, as a full gene to start at.
        # extra_data needs to be a dict with entry 'start_gene' that is a list
        # of integer values the same length as param_count.
        if extra_data is not None:
            if 'start_gene' in extra_data:
                if not (len(start_values_min) == self.total_param_count):
                    msg = ('extra_data of start_gene passed to txmultimasterflow. ' +
                        'Length expected = {:d}, found = {:d}'.format(self.total_param_count, 
                        len(start_values_min)))
                    raise mureilexception.ConfigException(msg, {})

                start_values_min = extra_data['start_gene']
                start_values_max = extra_data['start_gene']
       
        # Instantiate the market solver
        self.market_solver = mureilbuilder.create_instance(full_config, self.global_config, 
            self.config['market_solver'], configurablebase.ConfigurableMultiBase,
            self.config['run_periods'])

        # Instantiate the genetic algorithm
        mureilbuilder.check_section_exists(full_config, self.config['algorithm'])
        algorithm_config = full_config[self.config['algorithm']]
        algorithm_config['min_len'] = algorithm_config['max_len'] = self.total_param_count
        algorithm_config['start_values_min'] = start_values_min
        algorithm_config['start_values_max'] = start_values_max
        algorithm_config['gene_test_callback'] = self.gene_test
        self.algorithm = mureilbuilder.create_instance(full_config, self.global_config,
            self.config['algorithm'], mureilbase.ConfigurableInterface)

        self.is_configured = True
Beispiel #6
0
    def set_config(self, full_config, extra_data):

        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])

        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']][
                'model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(
            full_config, None, self.config['global'],
            mureilbase.ConfigurableInterface)
        self.global_config = self.global_calc.get_config()

        # Now check the dispatch_order, to get a list of the generators
        for gen in self.config['dispatch_order']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()

        self.dispatch_order = self.config['dispatch_order']

        # Set up the data class and get the data, and compute the global parameters
        self.data = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['data'],
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config(
            {'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        # Instantiate the generator objects, set their data, determine their param requirements
        param_count = 0
        self.gen_list = {}
        self.gen_params = {}
        start_values_min = []
        start_values_max = []

        for i in range(len(self.dispatch_order)):
            gen_type = self.dispatch_order[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(
                full_config, self.global_config, self.config[gen_type],
                singlepassgenerator.SinglePassGeneratorBase)
            self.gen_list[gen_type] = gen

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)

            # Determine how many parameters this generator requires and
            # allocate the slots in the params list
            params_req = gen.get_param_count()
            if (params_req == 0):
                self.gen_params[gen_type] = (0, 0)
            else:
                self.gen_params[gen_type] = (param_count,
                                             param_count + params_req)
                (starts_min, starts_max) = gen.get_param_starts()

                if len(starts_min) == 0:
                    start_values_min += (
                        (np.ones(params_req) *
                         self.global_config['min_param_val']).tolist())
                else:
                    start_values_min += starts_min

                if len(starts_max) == 0:
                    start_values_max += (
                        (np.ones(params_req) *
                         self.global_config['max_param_val']).tolist())
                else:
                    start_values_max += starts_max

            param_count += params_req

        self.param_count = param_count

        # Check if 'extra_data' has been provided, as a full gene to start at.
        # extra_data needs to be a dict with entry 'start_gene' that is a list
        # of integer values the same length as param_count.
        if extra_data is not None:
            if 'start_gene' in extra_data:
                if not (len(start_values_min) == param_count):
                    msg = (
                        'extra_data of start_gene passed to simplemureilmaster. '
                        + 'Length expected = {:d}, found = {:d}'.format(
                            param_count, len(start_values_min)))
                    raise mureilexception.ConfigException(msg, {})
                else:
                    start_values_min = extra_data['start_gene']
                    start_values_max = extra_data['start_gene']

        # Instantiate the genetic algorithm
        mureilbuilder.check_section_exists(full_config,
                                           self.config['algorithm'])
        algorithm_config = full_config[self.config['algorithm']]
        algorithm_config['min_len'] = algorithm_config['max_len'] = param_count
        algorithm_config['start_values_min'] = start_values_min
        algorithm_config['start_values_max'] = start_values_max
        algorithm_config['gene_test_callback'] = self.gene_test
        self.algorithm = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['algorithm'],
            mureilbase.ConfigurableInterface)

        self.is_configured = True
    def set_config(self, full_config, extra_data):

        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config["Master"])

        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config["global"])
        if "model" not in full_config[self.config["global"]]:
            full_config[self.config["global"]]["model"] = "tools.globalconfig.GlobalBase"
        self.global_calc = mureilbuilder.create_instance(
            full_config, None, self.config["global"], mureilbase.ConfigurableInterface
        )
        self.global_config = self.global_calc.get_config()

        # Now check the dispatch_order, to get a list of the generators
        for gen in self.config["dispatch_order"]:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()

        self.dispatch_order = self.config["dispatch_order"]

        # Set up the data class and get the data, and compute the global parameters
        self.data = mureilbuilder.create_instance(
            full_config, self.global_config, self.config["data"], mureilbase.DataSinglePassInterface
        )
        self.global_calc.update_config({"data_ts_length": self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        # Instantiate the generator objects, set their data, determine their param requirements
        param_count = 0
        self.gen_list = {}
        self.gen_params = {}
        start_values_min = []
        start_values_max = []

        for i in range(len(self.dispatch_order)):
            gen_type = self.dispatch_order[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(
                full_config, self.global_config, self.config[gen_type], singlepassgenerator.SinglePassGeneratorBase
            )
            self.gen_list[gen_type] = gen

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)

            # Determine how many parameters this generator requires and
            # allocate the slots in the params list
            params_req = gen.get_param_count()
            if params_req == 0:
                self.gen_params[gen_type] = (0, 0)
            else:
                self.gen_params[gen_type] = (param_count, param_count + params_req)
                (starts_min, starts_max) = gen.get_param_starts()

                if len(starts_min) == 0:
                    start_values_min += (np.ones(params_req) * self.global_config["min_param_val"]).tolist()
                else:
                    start_values_min += starts_min

                if len(starts_max) == 0:
                    start_values_max += (np.ones(params_req) * self.global_config["max_param_val"]).tolist()
                else:
                    start_values_max += starts_max

            param_count += params_req

        self.param_count = param_count

        # Check if 'extra_data' has been provided, as a full gene to start at.
        # extra_data needs to be a dict with entry 'start_gene' that is a list
        # of integer values the same length as param_count.
        if extra_data is not None:
            if "start_gene" in extra_data:
                if not (len(start_values_min) == param_count):
                    msg = (
                        "extra_data of start_gene passed to simplemureilmaster. "
                        + "Length expected = {:d}, found = {:d}".format(param_count, len(start_values_min))
                    )
                    raise mureilexception.ConfigException(msg, {})
                else:
                    start_values_min = extra_data["start_gene"]
                    start_values_max = extra_data["start_gene"]

        # Instantiate the genetic algorithm
        mureilbuilder.check_section_exists(full_config, self.config["algorithm"])
        algorithm_config = full_config[self.config["algorithm"]]
        algorithm_config["min_len"] = algorithm_config["max_len"] = param_count
        algorithm_config["start_values_min"] = start_values_min
        algorithm_config["start_values_max"] = start_values_max
        algorithm_config["gene_test_callback"] = self.gene_test
        self.algorithm = mureilbuilder.create_instance(
            full_config, self.global_config, self.config["algorithm"], mureilbase.ConfigurableInterface
        )

        self.is_configured = True
Beispiel #8
0
    def set_config(self, full_config, extra_data):

        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])

        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']][
                'model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(
            full_config, None, self.config['global'],
            mureilbase.ConfigurableInterface)
        self.global_config = self.global_calc.get_config()

        # Now check the list of the generators
        for gen in self.config['generators']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()

        self.generators = self.config['generators']

        # Set up the data class and get the data, and compute the global parameters
        self.data = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['data'],
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config(
            {'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        ## The master here takes 'global' variables, if needed and available, to get at the carbon_price_m,
        ## variable_cost_mult and time_scale_up_mult values, which it then expands to all time periods,
        ## for use later.
        for param_name in [
                'carbon_price_m', 'variable_cost_mult', 'time_scale_up_mult'
        ]:
            if (param_name not in self.config) and (param_name
                                                    in self.global_config):
                self.config[param_name] = self.global_config[param_name]
        self.config_spec += [('carbon_price_m', float, None),
                             ('variable_cost_mult', float, None),
                             ('time_scale_up_mult', float, None)]
        self.check_config()
        self.expand_config(self.config['run_periods'])

        # Now instantiate the demand model
        self.demand = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['demand'],
            configurablebase.ConfigurableMultiBase, self.config['run_periods'])

        # Supply data to the demand model
        mureilbuilder.supply_single_pass_data(self.demand, self.data, 'demand')

        # And instantiate the transmission model
        self.transmission = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['transmission'],
            configurablebase.ConfigurableMultiBase, self.config['run_periods'])

        mureilbuilder.check_subclass(
            self.transmission, interfacesflowmaster.InterfaceTransmission)

        # Instantiate the generator objects, set their data, determine their param requirements,
        # and separate by dispatch type.
        param_count = 0

        # gen_list, gen_params are indexed by position in self.generators
        self.gen_list = [None] * len(self.generators)
        self.gen_params = [None] * len(self.generators)

        self.semisch_list = []
        self.instant_list = []
        self.ramp_list = []

        run_period_len = len(self.config['run_periods'])
        start_values_min = numpy.array([[]]).reshape(run_period_len, 0)
        start_values_max = numpy.array([[]]).reshape(run_period_len, 0)

        for i in range(len(self.generators)):
            gen_type = self.generators[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(
                full_config, self.global_config, self.config[gen_type],
                txmultigeneratorbase.TxMultiGeneratorBase,
                self.config['run_periods'])

            self.gen_list[i] = gen

            gen_details = gen.get_details()
            gen_dispatch = gen_details['dispatch']

            if (gen_dispatch == 'semischeduled'):
                self.semisch_list.append(i)
                mureilbuilder.check_subclass(
                    gen, interfacesflowmaster.InterfaceSemiScheduledDispatch)
            elif (gen_dispatch == 'instant'):
                self.instant_list.append(i)
                mureilbuilder.check_subclass(
                    gen, interfacesflowmaster.InterfaceInstantDispatch)
            elif (gen_dispatch == 'ramp'):
                self.ramp_list.append(i)
                mureilbuilder.check_subclass(
                    gen, interfacesflowmaster.InterfaceRampDispatch)
                msg = ("Generator " + gen_type +
                       " has dispatch type ramp, which is not yet implemented")
                raise mureilexception.ConfigException(msg, {})
            else:
                msg = ("Generator " + gen_type + " has dispatch type " +
                       gen_dispatch +
                       " which is not one of semischeduled, instant or ramp.")
                raise mureilexception.ConfigException(msg, {})

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)

            # Determine how many parameters this generator requires and
            # allocate the slots in the params list
            params_req = gen.get_param_count()
            if (params_req == 0):
                self.gen_params[i] = (0, 0)
            else:
                self.gen_params[i] = (param_count, param_count + params_req)

                start_values_min, start_values_max = mureilbuilder.add_param_starts(
                    gen.get_param_starts(), params_req, self.global_config,
                    run_period_len, start_values_min, start_values_max)

            param_count += params_req

        start_values_min = start_values_min.reshape(run_period_len *
                                                    param_count)
        start_values_max = start_values_max.reshape(run_period_len *
                                                    param_count)

        self.param_count = param_count
        # Check that run_periods increases by time_period_yrs
        self.run_periods = self.config['run_periods']
        if len(self.run_periods) > 1:
            run_period_diffs = numpy.diff(self.run_periods)
            if (not (min(run_period_diffs)
                     == self.global_config['time_period_yrs'])
                    or not (max(run_period_diffs)
                            == self.global_config['time_period_yrs'])):
                raise mureilexception.ConfigException(
                    'run_periods must be separated by time_period_yrs', {})

        self.period_count = len(self.run_periods)
        self.total_param_count = param_count * self.period_count

        # Check if 'extra_data' has been provided, as a full gene to start at.
        # extra_data needs to be a dict with entry 'start_gene' that is a list
        # of integer values the same length as param_count.
        if extra_data is not None:
            if 'start_gene' in extra_data:
                if not (len(start_values_min) == self.total_param_count):
                    msg = (
                        'extra_data of start_gene passed to txmultimasterflow. '
                        + 'Length expected = {:d}, found = {:d}'.format(
                            self.total_param_count, len(start_values_min)))
                    raise mureilexception.ConfigException(msg, {})

                start_values_min = extra_data['start_gene']
                start_values_max = extra_data['start_gene']

        # Instantiate the market solver
        self.market_solver = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['market_solver'],
            configurablebase.ConfigurableMultiBase, self.config['run_periods'])

        # Instantiate the genetic algorithm
        mureilbuilder.check_section_exists(full_config,
                                           self.config['algorithm'])
        algorithm_config = full_config[self.config['algorithm']]
        algorithm_config['min_len'] = algorithm_config[
            'max_len'] = self.total_param_count
        algorithm_config['start_values_min'] = start_values_min
        algorithm_config['start_values_max'] = start_values_max
        algorithm_config['gene_test_callback'] = self.gene_test
        self.algorithm = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['algorithm'],
            mureilbase.ConfigurableInterface)

        self.is_configured = True
    def set_config(self, full_config, extra_data):

        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])

        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']][
                'model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(
            full_config, None, self.config['global'],
            mureilbase.ConfigurableInterface)
        self.global_config = self.global_calc.get_config()

        # Now check the dispatch_order, to get a list of the generators
        for gen in self.config['dispatch_order']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()

        self.dispatch_order = self.config['dispatch_order']

        # Set up the data class and get the data
        self.data = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['data'],
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config(
            {'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        # Instantiate the generator objects, set their data, determine their param requirements
        param_count = 0
        self.gen_list = {}
        self.gen_params = {}

        for i in range(len(self.dispatch_order)):
            gen_type = self.dispatch_order[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(
                full_config, self.global_config, self.config[gen_type],
                singlepassgenerator.SinglePassGeneratorBase)
            self.gen_list[gen_type] = gen

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)

            # Determine how many parameters this generator requires and
            # allocate the slots in the params list
            params_req = gen.get_param_count()
            if (params_req == 0):
                self.gen_params[gen_type] = (0, 0)
            else:
                self.gen_params[gen_type] = (param_count,
                                             param_count + params_req)
            param_count += params_req

        self.param_count = param_count

        self.is_configured = True
    def set_config(self, full_config, extra_data):
    
        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])
        
        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']]['model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(full_config, None, self.config['global'], 
            mureilbase.ConfigurableInterface)    
        self.global_config = self.global_calc.get_config()

        # Now check the dispatch_order, to get a list of the generators
        for gen in self.config['dispatch_order']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()
        
        self.dispatch_order = self.config['dispatch_order']
        
        # Set up the data class and get the data, and compute the global parameters
        self.data = mureilbuilder.create_instance(full_config, self.global_config, self.config['data'], 
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config({'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        # Instantiate the transmission model
        if self.config['transmission'] in full_config:
            self.transmission = mureilbuilder.create_instance(full_config, self.global_config, 
                self.config['transmission'], configurablebase.ConfigurableMultiBase,
                self.config['run_periods'])
            mureilbuilder.supply_single_pass_data(self.transmission,
                self.data, self.config['transmission'])
        else:
            self.transmission = None
        
        # Instantiate the generator objects, set their data, determine their param requirements
        param_count = 0
        self.gen_list = {}
        self.gen_params = {}
        
        run_period_len = len(self.config['run_periods'])
        start_values_min = numpy.array([[]]).reshape(run_period_len, 0)
        start_values_max = numpy.array([[]]).reshape(run_period_len, 0)

        for i in range(len(self.dispatch_order)):
            gen_type = self.dispatch_order[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(full_config, self.global_config, 
                self.config[gen_type], txmultigeneratorbase.TxMultiGeneratorBase,
                self.config['run_periods'])
            self.gen_list[gen_type] = gen

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)
    
            # Determine how many parameters this generator requires and
            # allocate the slots in the params list
            params_req = gen.get_param_count()
            if (params_req == 0):
                self.gen_params[gen_type] = (0, 0)
            else:
                self.gen_params[gen_type] = (param_count, 
                    param_count + params_req)

                start_values_min, start_values_max = mureilbuilder.add_param_starts(
                    gen.get_param_starts(), params_req, self.global_config,
                    run_period_len, start_values_min, start_values_max)

            param_count += params_req

        start_values_min = start_values_min.reshape(run_period_len * param_count)
        start_values_max = start_values_max.reshape(run_period_len * param_count)

        self.param_count = param_count
        # Check that run_periods increases by time_period_yrs
        self.run_periods = self.config['run_periods']
        if len(self.run_periods) > 1:
            run_period_diffs = numpy.diff(self.run_periods)
            if (not (min(run_period_diffs) == self.global_config['time_period_yrs']) or
                not (max(run_period_diffs) == self.global_config['time_period_yrs'])):
                raise mureilexception.ConfigException('run_periods must be separated by time_period_yrs', {})

        self.period_count = len(self.run_periods)
        self.total_param_count = param_count * self.period_count

        # Check if 'extra_data' has been provided, as a full gene to start at.
        # extra_data needs to be a dict with entry 'start_gene' that is a list
        # of integer values the same length as param_count.
        if extra_data is not None:
            if 'start_gene' in extra_data:
                if not (len(start_values_min) == self.total_param_count):
                    msg = ('extra_data of start_gene passed to txmultimastersimple. ' +
                        'Length expected = {:d}, found = {:d}'.format(self.total_param_count, 
                        len(start_values_min)))
                    raise mureilexception.ConfigException(msg, {})

                start_values_min = extra_data['start_gene']
                start_values_max = extra_data['start_gene']
       
        # Instantiate the genetic algorithm
        mureilbuilder.check_section_exists(full_config, self.config['algorithm'])
        algorithm_config = full_config[self.config['algorithm']]
        algorithm_config['min_len'] = algorithm_config['max_len'] = self.total_param_count
        algorithm_config['start_values_min'] = start_values_min
        algorithm_config['start_values_max'] = start_values_max
        algorithm_config['gene_test_callback'] = self.gene_test
        self.algorithm = mureilbuilder.create_instance(full_config, self.global_config,
            self.config['algorithm'], mureilbase.ConfigurableInterface)

        self.is_configured = True
    def set_config(self, full_config, extra_data):

        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])

        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']][
                'model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(
            full_config, None, self.config['global'],
            mureilbase.ConfigurableInterface)
        self.global_config = self.global_calc.get_config()

        # Now check the dispatch_order, to get a list of the generators
        for gen in self.config['dispatch_order']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()

        self.dispatch_order = self.config['dispatch_order']

        # Set up the data class and get the data, and compute the global parameters
        self.data = mureilbuilder.create_instance(
            full_config, self.global_config, self.config['data'],
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config(
            {'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        # Instantiate the transmission model
        if self.config['transmission'] in full_config:
            self.transmission = mureilbuilder.create_instance(
                full_config, self.global_config, self.config['transmission'],
                configurablebase.ConfigurableMultiBase,
                self.config['run_periods'])
            mureilbuilder.supply_single_pass_data(self.transmission, self.data,
                                                  self.config['transmission'])
        else:
            self.transmission = None

        # Instantiate the generator objects, set their data
        self.gen_list = {}

        for i in range(len(self.dispatch_order)):
            gen_type = self.dispatch_order[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(
                full_config, self.global_config, self.config[gen_type],
                txmultigeneratorbase.TxMultiGeneratorBase,
                self.config['run_periods'])
            self.gen_list[gen_type] = gen

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)

        # Check that run_periods increases by time_period_yrs
        self.run_periods = self.config['run_periods']
        if len(self.run_periods) > 1:
            run_period_diffs = numpy.diff(self.run_periods)
            if (not (min(run_period_diffs)
                     == self.global_config['time_period_yrs'])
                    or not (max(run_period_diffs)
                            == self.global_config['time_period_yrs'])):
                raise mureilexception.ConfigException(
                    'run_periods must be separated by time_period_yrs', {})

        self.period_count = len(self.run_periods)
        self.is_configured = True
    def set_config(self, full_config, extra_data):
    
        # Master explicitly does not copy in the global variables. It is too confusing
        # to combine those with flags, defaults and values defined in the config files.
        self.load_initial_config(full_config['Master'])
        
        # Get the global variables
        mureilbuilder.check_section_exists(full_config, self.config['global'])
        if 'model' not in full_config[self.config['global']]:
            full_config[self.config['global']]['model'] = 'tools.globalconfig.GlobalBase'
        self.global_calc = mureilbuilder.create_instance(full_config, None, self.config['global'], 
            mureilbase.ConfigurableInterface)    
        self.global_config = self.global_calc.get_config()

        # Now check the dispatch_order, to get a list of the generators
        for gen in self.config['dispatch_order']:
            self.config_spec += [(gen, None, None)]

        self.update_from_config_spec()
        self.check_config()
        
        self.dispatch_order = self.config['dispatch_order']
        
        # Set up the data class and get the data, and compute the global parameters
        self.data = mureilbuilder.create_instance(full_config, self.global_config, self.config['data'], 
            mureilbase.DataSinglePassInterface)
        self.global_calc.update_config({'data_ts_length': self.data.get_ts_length()})
        self.global_calc.post_data_global_calcs()
        self.global_config = self.global_calc.get_config()

        # Instantiate the transmission model
        if self.config['transmission'] in full_config:
            self.transmission = mureilbuilder.create_instance(full_config, self.global_config, 
                self.config['transmission'], configurablebase.ConfigurableMultiBase,
                self.config['run_periods'])
            mureilbuilder.supply_single_pass_data(self.transmission,
                self.data, self.config['transmission'])
        else:
            self.transmission = None
        
        # Instantiate the generator objects, set their data
        self.gen_list = {}
        
        for i in range(len(self.dispatch_order)):
            gen_type = self.dispatch_order[i]

            # Build the generator instances
            gen = mureilbuilder.create_instance(full_config, self.global_config, 
                self.config[gen_type], txmultigeneratorbase.TxMultiGeneratorBase,
                self.config['run_periods'])
            self.gen_list[gen_type] = gen

            # Supply data as requested by the generator
            mureilbuilder.supply_single_pass_data(gen, self.data, gen_type)
    
        # Check that run_periods increases by time_period_yrs
        self.run_periods = self.config['run_periods']
        if len(self.run_periods) > 1:
            run_period_diffs = numpy.diff(self.run_periods)
            if (not (min(run_period_diffs) == self.global_config['time_period_yrs']) or
                not (max(run_period_diffs) == self.global_config['time_period_yrs'])):
                raise mureilexception.ConfigException('run_periods must be separated by time_period_yrs', {})

        self.period_count = len(self.run_periods)
        self.is_configured = True