def test_evaluate(): ps = ParameterSet( { 'East_River_Creature': { 'formula': '2 * Deep_Thought + 16' }, 'Elders_of_Krikkit': { 'formula': 'sqrt(East_River_Creature)' }, }, {'Deep_Thought': 42}) assert ps.evaluate() == { 'East_River_Creature': 100, 'Elders_of_Krikkit': 10, 'Deep_Thought': 42, }
def test_simple_evaluation(): params = { 'Agrajag': { 'amount': 3.14 }, 'Constant_Mown': { 'amount': 0.001 }, 'Deep_Thought': { 'amount': 42 }, 'East_River_Creature': { 'formula': '2 * Agrajag ** 2' }, 'Eccentrica_Gallumbits': { 'formula': '1 / sqrt(Constant_Mown)' }, 'Elders_of_Krikkit': { 'formula': 'East_River_Creature + Eccentrica_Gallumbits' }, 'Emily_Saunders': { 'formula': 'sin(Deep_Thought) + 7 - Elders_of_Krikkit' }, 'Gag_Halfrunt': { 'formula': 'Deep_Thought + Constant_Mown - log10(abs(Emily_Saunders))' }, 'Gargravarr': { 'formula': ('Agrajag + Constant_Mown + Deep_Thought + ' 'East_River_Creature + Eccentrica_Gallumbits + ' 'Elders_of_Krikkit + Emily_Saunders + Gag_Halfrunt') } } ParameterSet(params).evaluate()
def test_monte_carlo_evaluation_global_params(): params = { 'Deep_Thought': { 'amount': 5, 'uncertainty type': 4, # Uniform 'minimum': 2, 'maximum': 8, }, 'Gargravarr': { 'amount': 10, 'uncertainty type': 4, # Uniform 'minimum': 0, 'maximum': 20, }, 'East_River_Creature': { 'formula': 'Agrajag + Gargravarr' }, 'Elders_of_Krikkit': { 'formula': 'East_River_Creature + Deep_Thought' }, } global_params = { 'Agrajag': np.arange(10) + 100 } result = ParameterSet(params, global_params=global_params).evaluate_monte_carlo(10) assert all(result['East_River_Creature'] > 100) assert all(result['Elders_of_Krikkit'] > result['East_River_Creature'])
def get_global_parameters(cls, data, pm): current, parameters = None, [] for line in data: if not line: # Blank line, end of section current = None elif line[0] in { "Database Input parameters", "Project Input parameters" }: current = "input" elif line[0] in { "Database Calculated parameters", "Project Calculated parameters" }: current = "calculated" elif current is None: continue elif current == 'input': parameters.append(cls.parse_input_parameter(line)) elif current == 'calculated': parameters.append(cls.parse_calculated_parameter(line, pm)) else: raise ValueError("This should never happen") # Extract name and lowercase parameters = {obj.pop('name').lower(): obj for obj in parameters} # Change all formula values to lowercase if referencing global parameters for obj in parameters.values(): if 'formula' in obj: obj['formula'] = replace_with_lowercase( obj['formula'], parameters) ParameterSet(parameters).evaluate_and_set_amount_field() return parameters
def test_call_updates_exchanges(): ds = { 'name': 'Some dataset', 'parameters': { 'Deep_Thought': { 'amount': 42 }, 'East_River_Creature': { 'formula': '2 * Deep_Thought + 16' }, 'Elders_of_Krikkit': { 'formula': 'sqrt(East_River_Creature)' }, }, 'exchanges': [{ 'formula': 'Elders_of_Krikkit' }, { 'amount': 44 }] } ParameterSet(ds['parameters'])(ds['exchanges']) assert ds['parameters']['East_River_Creature'] == { 'amount': 100, 'formula': '2 * Deep_Thought + 16' } assert ds['exchanges'][0] == {'amount': 10, 'formula': 'Elders_of_Krikkit'} assert ds['exchanges'][1] == {'amount': 44}
def recalculate_activity_parameters(self, group: str, global_params: dict = None ) -> Optional[dict]: new_values = self.get_altered_values(group) if global_params is None: global_params = {} data = ActivityParameter.load(group) if not data: return for name, amount in new_values.items(): data[name]["amount"] = amount new_symbols = get_new_symbols(data.values(), set(data)) missing = new_symbols.difference(global_params) if missing: raise MissingName( "The following variables aren't defined:\n{}".format( "|".join(missing))) glo = self._static(global_params, needed=new_symbols) if new_symbols else None ParameterSet(data, glo).evaluate_and_set_amount_field() return self._prune_result_data(data)
def test_missing_fields(): with pytest.raises(ValueError): ps = ParameterSet({'': {}}) with pytest.raises(ValueError): ps = ParameterSet([{ 'amount': 1, 'name': 'Gag_Halfrunt' }, { 'name': 'Emily_Saunders' }]) with pytest.raises(ValueError): ps = ParameterSet([{ 'formula': 'foo', 'name': 'Deep_Thought' }, { 'name': 'Constant_Mown' }])
def test_wrong_shape(): params = { 'Agrajag': {'amount': 3.14}, 'East_River_Creature': { 'formula': '2 * Agrajag * empty((100, 1000))' }, } with pytest.raises(BroadcastingError): ParameterSet(params).evaluate_monte_carlo()
def test_evaluation_values(): params = { 'Deep_Thought': { 'amount': 42 }, 'East_River_Creature': { 'formula': '2 * Deep_Thought + 16' }, 'Elders_of_Krikkit': { 'formula': 'sqrt(East_River_Creature)' }, } ps = ParameterSet(params) assert ps.evaluate() == { 'Deep_Thought': 42, 'Elders_of_Krikkit': 10, 'East_River_Creature': 100 }
def test_capitaliation_error(): with pytest.raises(CapitalizationError): ps = ParameterSet({ 'Elders_of_Krikkit': { 'formula': '2 * Agrajag' }, 'agrajag': { 'amount': 2 }, })
def test_global_params_arrays_allowed(): ps = ParameterSet( { 'East_River_Creature': { 'formula': '2 * Deep_Thought + 16' }, 'Elders_of_Krikkit': { 'formula': 'sqrt(East_River_Creature)' }, }, {'Deep_Thought': np.arange(5)})
def test_nonidentifier(): with pytest.raises(ValueError): ps = ParameterSet( { 'East_River_Creature': { 'formula': '2 * Deep_Thought + 16' }, 'Elders_of_Krikkit': { 'formula': 'sqrt(East_River_Creature)' }, }, {'Deep Thought': 2.4})
def recalculate_project_parameters(self) -> dict: data = self.initial.project() if not data: return {} new_values = self.parameters.data_by_group("project") for name, amount in new_values.items(): data[name]["amount"] = amount ParameterSet(data).evaluate_and_set_amount_field() return StaticParameters.prune_result_data(data)
def recalculate_project_parameters(self) -> Optional[dict]: new_values = self.get_altered_values("project") data = ProjectParameter.load() if not data: return for name, amount in new_values.items(): data[name]["amount"] = amount ParameterSet(data).evaluate_and_set_amount_field() return self._prune_result_data(data)
def test_circular_reference(): with pytest.raises(ParameterError): ps = ParameterSet({ 'Elders_of_Krikkit': { 'formula': '2 * Agrajag' }, 'East_River_Creature': { 'formula': '2 * Elders_of_Krikkit' }, 'Agrajag': { 'formula': '2 * East_River_Creature' }, })
def test_evaluate_update_values(): params = { 'Deep_Thought': { 'amount': 42 }, 'East_River_Creature': { 'formula': '2 * Deep_Thought + 16' }, 'Elders_of_Krikkit': { 'formula': 'sqrt(East_River_Creature)' }, } ParameterSet(params).evaluate_and_set_amount_field() assert params['East_River_Creature']['amount'] == 100 assert params['Elders_of_Krikkit']['amount'] == 10
def test_call_no_exchanges(): ds = { 'parameters': { 'Deep_Thought': { 'amount': 42 }, 'East_River_Creature': { 'formula': '2 * Deep_Thought + 16' }, 'Elders_of_Krikkit': { 'formula': 'sqrt(East_River_Creature)' }, } } ds = ParameterSet(ds['parameters'])(ds) assert 'exchanges' not in ds
def recalculate_activity_parameters(self, group: str, global_params: dict = None) -> dict: data = self.initial.act_by_group(group) if not data: return {} new_values = self.parameters.data_by_group(group) glo = global_params or {} for name, amount in new_values.items(): data[name]["amount"] = amount new_symbols = get_new_symbols(data.values(), set(data)) missing = new_symbols.difference(global_params) if missing: raise MissingName("The following variables aren't defined:\n{}".format("|".join(missing))) glo = Parameters.static(glo, needed=new_symbols) if new_symbols else None ParameterSet(data, glo).evaluate_and_set_amount_field() return StaticParameters.prune_result_data(data)
def test_monte_carlo_evaluation(): params = { 'Agrajag': {'amount': 3.14}, 'Constant_Mown': { 'amount': 0.001, 'uncertainty_type': 3, 'loc': 0.001, 'scale': 0.2, 'minimum': 0, }, 'Deep_Thought': { 'amount': 42, 'uncertainty type': 5, 'minimum': 30, 'maximum': 70, }, 'Gargravarr': { 'amount': 10, 'uncertainty type': 5, 'minimum': 0, 'maximum': 25, }, 'East_River_Creature': { 'formula': '2 * Agrajag ** 2 + Gargravarr' }, 'Eccentrica_Gallumbits': { 'formula': '1 / sqrt(Constant_Mown)' }, 'Elders_of_Krikkit': { 'formula': 'East_River_Creature + Eccentrica_Gallumbits' }, 'Emily_Saunders': {'formula': 'sin(Deep_Thought) + 7 - Elders_of_Krikkit'}, 'Gag_Halfrunt': { 'formula': 'Deep_Thought + Constant_Mown - log10(abs(Emily_Saunders))' }, } result = ParameterSet(deepcopy(params)).evaluate_monte_carlo(1001) for v in result.values(): assert v.shape == (1001,) for key in params: if key == 'Agrajag': continue assert np.unique(result[key]).shape[0] > 100 assert np.allclose(result['Agrajag'].sum(), 1001 * 3.14) result = ParameterSet(params).evaluate_monte_carlo() for v in result.values(): assert v.shape == (1000,)
def read_data_set(cls, data, index, db_name, filepath, gp, pm): metadata, index = cls.read_dataset_metadata(data, index) # `index` is now the `Products` or `Waste Treatment` line ds = { 'simapro metadata': metadata, 'code': metadata.get('Process identifier') or uuid.uuid4().hex, 'exchanges': [], 'parameters': [], 'database': db_name, 'filename': filepath, "type": "process", } while not data[index] or data[index][0] != 'End': if not data[index] or not data[index][0]: index += 1 elif data[index][0] in SIMAPRO_TECHNOSPHERE: category = data[index][0] index += 1 # Advance to data lines while index < len(data) and data[index] and data[index][ 0]: # Stop on blank line ds['exchanges'].append( cls.parse_input_line(data[index], category, pm)) index += 1 elif data[index][0] in SIMAPRO_BIOSPHERE: category = data[index][0] index += 1 # Advance to data lines while index < len(data) and data[index] and data[index][ 0]: # Stop on blank line ds['exchanges'].append( cls.parse_biosphere_flow(data[index], category, pm)) index += 1 elif data[index][0] == "Calculated parameters": index += 1 # Advance to data lines while index < len(data) and data[index] and data[index][ 0]: # Stop on blank line ds['parameters'].append( cls.parse_calculated_parameter(data[index], pm)) index += 1 elif data[index][0] == "Input parameters": index += 1 # Advance to data lines while index < len(data) and data[index] and data[index][ 0]: # Stop on blank line ds['parameters'].append( cls.parse_input_parameter(data[index])) index += 1 elif data[index][0] == "Products": index += 1 # Advance to data lines while index < len(data) and data[index] and data[index][ 0]: # Stop on blank line ds['exchanges'].append( cls.parse_reference_product(data[index], pm)) index += 1 elif data[index][0] == "Waste treatment": index += 1 # Advance to data lines while index < len(data) and data[index] and data[index][ 0]: # Stop on blank line ds['exchanges'].append( cls.parse_waste_treatment(data[index], pm)) index += 1 elif data[index][0] == "Final waste flows": index += 1 # Advance to data lines while index < len(data) and data[index] and data[index][ 0]: # Stop on blank line ds['exchanges'].append( cls.parse_final_waste_flow(data[index], pm)) index += 1 elif data[index][0] in SIMAPRO_END_OF_DATASETS: # Don't care about processing steps below, as no dataset # was extracted raise EndOfDatasets else: index += 1 if index == len(data): break # Extract name and lowercase ds['parameters'] = { obj.pop('name').lower(): obj for obj in ds['parameters'] } # Change all parameter formula values to lowercase if referencing # global or local parameters for obj in ds['parameters'].values(): if 'formula' in obj: obj['formula'] = replace_with_lowercase( obj['formula'], ds['parameters']) obj['formula'] = replace_with_lowercase(obj['formula'], gp) # Change all exchange values to lowercase if referencing # global or local parameters for obj in ds['exchanges']: if 'formula' in obj: obj['formula'] = replace_with_lowercase( obj['formula'], ds['parameters']) obj['formula'] = replace_with_lowercase(obj['formula'], gp) ps = ParameterSet(ds['parameters'], {key: value['amount'] for key, value in gp.items()}) # Changes in-place ps(ds['exchanges']) if not ds['parameters']: del ds['parameters'] return ds, index
def test_not_dict(): with pytest.raises(ValueError): ps = ParameterSet([])
def test_not_dict(): with pytest.raises(ValueError): ps = ParameterSet({'Deep Thought': 42})
def test_space_in_name(): ps = ParameterSet({'Deep_Thought': {'amount': 42}}) with pytest.raises(ValueError): ps = ParameterSet({'Deep Thought': {'amount': 42}})
def test_name_in_existing_symbols(): with pytest.raises(DuplicateName): ps = ParameterSet({'log': {'amount': 1}})
def test_missing_reference(): with pytest.raises(ParameterError): ps = ParameterSet( {'Elders_of_Krikkit': { 'formula': '2 * Ford_Prefect' }})
def test_self_reference(): with pytest.raises(SelfReference): ParameterSet( {'Elders_of_Krikkit': { 'formula': '2 * Elders_of_Krikkit' }})