def calculate(tax_benefit_system, input_data): simulation = SimulationBuilder().build_from_entities(tax_benefit_system, input_data) requested_computations = dpath.util.search(input_data, '*/*/*/*', afilter = lambda t: t is None, yielded = True) computation_results = {} for computation in requested_computations: path = computation[0] entity_plural, entity_id, variable_name, period = path.split('/') variable = tax_benefit_system.get_variable(variable_name) result = simulation.calculate(variable_name, period) population = simulation.get_population(entity_plural) entity_index = population.get_index(entity_id) if variable.value_type == Enum: entity_result = result.decode()[entity_index].name elif variable.value_type == float: entity_result = float(str(result[entity_index])) # To turn the float32 into a regular float without adding confusing extra decimals. There must be a better way. elif variable.value_type == str: entity_result = str(result[entity_index]) else: entity_result = result.tolist()[entity_index] dpath.util.new(computation_results, path, entity_result) dpath.merge(input_data, computation_results) return input_data
def test_clone(): simulation = SimulationBuilder().build_from_entities(tax_benefit_system, { "persons": { "bill": {"salary": {"2017-01": 3000}}, }, "households": { "household": { "parents": ["bill"] } } }) simulation_clone = simulation.clone() assert simulation != simulation_clone for entity_id, entity in simulation.populations.items(): assert entity != simulation_clone.populations[entity_id] assert simulation.persons != simulation_clone.persons salary_holder = simulation.person.get_holder('salary') salary_holder_clone = simulation_clone.person.get_holder('salary') assert salary_holder != salary_holder_clone assert salary_holder_clone.simulation == simulation_clone assert salary_holder_clone.population == simulation_clone.persons
def test_dump(): directory = tempfile.mkdtemp(prefix = "openfisca_") simulation = SimulationBuilder().build_from_entities(tax_benefit_system, couple) calculated_value = simulation.calculate('disposable_income', '2018-01') dump_simulation(simulation, directory) simulation_2 = restore_simulation(directory, tax_benefit_system) # Check entities structure have been restored assert_array_equal(simulation.person.ids, simulation_2.person.ids) assert_array_equal(simulation.person.count, simulation_2.person.count) assert_array_equal(simulation.household.ids, simulation_2.household.ids) assert_array_equal(simulation.household.count, simulation_2.household.count) assert_array_equal(simulation.household.members_position, simulation_2.household.members_position) assert_array_equal(simulation.household.members_entity_id, simulation_2.household.members_entity_id) assert_array_equal(simulation.household.members_role, simulation_2.household.members_role) # Check calculated values are in cache disposable_income_holder = simulation_2.person.get_holder('disposable_income') cached_value = disposable_income_holder.get_array('2018-01') assert cached_value is not None assert_array_equal(cached_value, calculated_value) shutil.rmtree(directory)
def test_get_memory_usage(): test_case = deepcopy(single) test_case["persons"]["Alicia"]["salary"] = {"2017-01": 0} simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_case) simulation.calculate('disposable_income', '2017-01') memory_usage = simulation.person.get_memory_usage(variables = ['salary']) assert(memory_usage['total_nb_bytes'] > 0) assert(len(memory_usage['by_variable']) == 1)
def new_simulation(self, debug = False, opt_out_cache = False, use_baseline = False, trace = False): # Legacy from scenarios, used in reforms tax_benefit_system = self.tax_benefit_system if use_baseline: while True: baseline = tax_benefit_system.baseline if baseline is None: break tax_benefit_system = baseline builder = SimulationBuilder() if self.attributes: variables = self.attributes.get('input_variables') or {} period = self.attributes.get('period') builder.set_default_period(period) simulation = builder.build_from_variables(tax_benefit_system, variables) else: builder.set_default_period(self.period) simulation = builder.build_from_entities(tax_benefit_system, self.dict) simulation.debug = debug simulation.opt_out_cache = opt_out_cache if trace: simulation.trace = trace simulation.tracer = Tracer() return simulation
def parse_test(self): self.name = self.test.get('name', '') if not self.test.get('output'): raise ValueError("Missing key 'output' in test '{}' in file '{}'".format(self.name, self.fspath)) if not TEST_KEYWORDS.issuperset(self.test.keys()): unexpected_keys = set(self.test.keys()).difference(TEST_KEYWORDS) raise ValueError("Unexpected keys {} in test '{}' in file '{}'".format(unexpected_keys, self.name, self.fspath)) self.tax_benefit_system = _get_tax_benefit_system(self.baseline_tax_benefit_system, self.test.get('reforms', []), self.test.get('extensions', [])) try: builder = SimulationBuilder() input = self.test.get('input', {}) period = self.test.get('period') verbose = self.options.get('verbose') builder.set_default_period(period) self.simulation = builder.build_from_dict(self.tax_benefit_system, input) self.simulation.trace = verbose except (VariableNotFound, SituationParsingError): raise except Exception as e: error_message = os.linesep.join([str(e), '', f"Unexpected error raised while parsing '{self.fspath}'"]) raise ValueError(error_message).with_traceback(sys.exc_info()[2]) from e # Keep the stack trace from the root error
def trace(tax_benefit_system, input_data): simulation = SimulationBuilder().build_from_entities(tax_benefit_system, input_data) simulation.trace = True requested_computations = dpath.util.search(input_data, '*/*/*/*', afilter = lambda t: t is None, yielded = True) for computation in requested_computations: path = computation[0] entity_plural, entity_id, variable_name, period = path.split('/') simulation.calculate(variable_name, period) trace = deepcopy(simulation.tracer.trace) for _vector_key, vector_trace in trace.items(): value = vector_trace['value'].tolist() if isinstance(vector_trace['value'], EnumArray): value = [item.name for item in vector_trace['value'].decode()] if isinstance(value[0], bytes): value = [str(item) for item in value] vector_trace['value'] = value return { "trace": trace, "entitiesDescription": simulation.describe_entities(), "requestedCalculations": list(simulation.tracer.requested_calculations) }
def test_calculate_with_trace(): simulation = SimulationBuilder().build_default_simulation(tax_benefit_system) simulation.trace = True simulation.calculate('income_tax', '2017-01') salary_trace = simulation.tracer.trace['salary<2017-01>'] assert salary_trace['parameters'] == {} income_tax_trace = simulation.tracer.trace['income_tax<2017-01>'] assert income_tax_trace['parameters']['taxes.income_tax_rate<2017-01-01>'] == 0.15 # Trace parameters called with indirect access simulation.calculate('housing_tax', '2017') housing_tax_trace = simulation.tracer.trace['housing_tax<2017>'] assert 'taxes.housing_tax<2017-01-01>' not in housing_tax_trace['parameters'] assert housing_tax_trace['parameters']['taxes.housing_tax.rate<2017-01-01>'] == 10 assert housing_tax_trace['parameters']['taxes.housing_tax.minimal_amount<2017-01-01>'] == 200
def _make_simulation(tbs, data): builder = SimulationBuilder() builder.default_period = month return builder.build_from_variables(tbs, data)
def build(self): self.sim_builder = SimulationBuilder() self.sim = self.sim_builder.build_from_entities( openfisca_uk.CountryTaxBenefitSystem(), self.situation_data)
def new_simulation(test_case, period = MONTH): builder = SimulationBuilder() builder.set_default_period(period) return builder.build_from_entities(tax_benefit_system, test_case)
def simulation(reference_period): return SimulationBuilder().build_default_simulation(tax_benefit_system)
def load_dataset(self, entity_dfs: Tuple[pd.DataFrame], verbose: bool = False) -> None: person, benunit, household = entity_dfs self.system = openfisca_uk.CountryTaxBenefitSystem() self.apply_reforms(self.reforms) builder = SimulationBuilder() builder.create_entities(self.system) person.sort_values("P_person_id", inplace=True) benunit.sort_values("B_benunit_id", inplace=True) household.sort_values("H_household_id", inplace=True) person["id"] = person["P_person_id"] benunit["id"] = benunit["B_benunit_id"] household["id"] = household["H_household_id"] person.sort_values("id", inplace=True) person.reset_index(inplace=True, drop=True) benunit.sort_values("id", inplace=True) benunit.reset_index(inplace=True, drop=True) household.sort_values("id", inplace=True) household.reset_index(inplace=True, drop=True) self.relations = { "person": np.array(person["P_person_id"]), "benunit": np.array(benunit["B_benunit_id"]), "household": np.array(household["H_household_id"]), "person-benunit": np.array(person["P_benunit_id"]), "person-household": np.array(person["P_household_id"]), } person_ids = np.array(person["P_person_id"]) benunit_ids = np.array(benunit["B_benunit_id"]) household_ids = np.array(household["H_household_id"]) builder.declare_person_entity("person", person_ids) benunits = builder.declare_entity("benunit", benunit_ids) households = builder.declare_entity("household", household_ids) person_roles = np.array(person["P_role"]) builder.join_with_persons( benunits, person["P_benunit_id"], person_roles) # define person-benunit memberships builder.join_with_persons( households, np.array(person["P_household_id"]), person_roles) # define person-household memberships model = builder.build(self.system) skipped = [] for input_file in [person, benunit, household]: for column in input_file.columns: if column != "P_role": try: def_period = self.system.get_variable( column).definition_period if def_period in ["eternity", "year"]: input_periods = [self.input_year] else: input_periods = period( self.input_year).get_subperiods(def_period) for subperiod in input_periods: model.set_input(column, subperiod, np.array(input_file[column])) except Exception: skipped += [column] if skipped and verbose: print( f"Incomplete initialisation: skipped {len(skipped)} variables:" ) for var in skipped: print(f"{var}") return model
def load_frs(self, *reforms, verbose=False, bonus={}): """ Create and populate a tax-benefit simulation model from OpenFisca. Arguments: reforms: any reforms to apply, in order. data: any data to use instead of the loaded Family Resources Survey. input_period: the period in which to enter all data (at the moment, all data is entered under this period). Returns: A Simulation object. """ system = CountryTaxBenefitSystem() for reform in reforms: system = reform(system) # apply each reform in order builder = SimulationBuilder() builder.create_entities( system) # create the entities (person, benunit, etc.) person_file = pd.read_csv(os.path.join(self.data_dir, "person.csv"), low_memory=False) benunit_file = pd.read_csv(os.path.join(self.data_dir, "benunit.csv"), low_memory=False) household_file = pd.read_csv(os.path.join(self.data_dir, "household.csv"), low_memory=False) person_file.sort_values(by=["person_id"], inplace=True) benunit_file.sort_values(by=["benunit_id"], inplace=True) household_file.sort_values(by=["household_id"], inplace=True) for input_file in [person_file, benunit_file, household_file]: input_file = input_file.sort_index() self.relations = { "person": np.array(person_file["person_id"]), "benunit": np.array(benunit_file["benunit_id"]), "household": np.array(household_file["household_id"]), "person-benunit": np.array(person_file["benunit_id"]), "person-household": np.array(person_file["household_id"]), } person_ids = np.array(person_file["person_id"]) benunit_ids = np.array(benunit_file["benunit_id"]) household_ids = np.array(household_file["household_id"]) builder.declare_person_entity("person", person_ids) benunits = builder.declare_entity("benunit", benunit_ids) households = builder.declare_entity("household", household_ids) person_roles = person_file["role"] builder.join_with_persons( benunits, np.array(person_file["benunit_id"]), person_roles) # define person-benunit memberships builder.join_with_persons(households, np.array(person_file["household_id"]), person_roles) person_file["index"] = np.arange(start=0, stop=len(person_file)) model = builder.build(system) skipped = [] for input_file in [person_file, benunit_file, household_file]: for column in input_file.columns: if column in bonus: input_file[column] += bonus[column] if column != "role": try: def_period = system.get_variable( column).definition_period if def_period in ["eternity", "year"]: input_periods = [self.input_period] else: input_periods = period( self.input_period).get_subperiods(def_period) for subperiod in input_periods: model.set_input(column, subperiod, np.array(input_file[column])) except Exception as e: skipped += [column] if skipped and verbose: print( f"Incomplete initialisation: skipped {len(skipped)} variables:" ) for var in skipped: print(f"{var}") return model
def simulation(): return SimulationBuilder().build_from_entities(tax_benefit_system, single)
'famille_' + str(q): { 'enfants': ['enf_' + str(q)], 'strasbourg_metropole_quotient_familial': { '2021-03': q } } for q in qf }, } from pprint import pprint pprint(TEST_CASE) tax_benefit_system = CountryTaxBenefitSystem() tax_benefit_system.load_extension('openfisca_france_local') simulation_builder = SimulationBuilder() simulation = simulation_builder.build_from_entities(tax_benefit_system, TEST_CASE) tarif_cantine = simulation.calculate( 'strasbourg_metropole_tarification_cantine', '2021-03') print('vecteur des tarifs') print(tarif_cantine) sum_tranches = counts * tarif_cantine * 200 # Pour 200 repas par an print('vecteur des recettes par tranche') print(sum_tranches) print('recettes totales') print(sum(sum_tranches))
def test_get_memory_usage(): simulation = SimulationBuilder().build_from_entities(tax_benefit_system, single) simulation.calculate('disposable_income', '2017-01') memory_usage = simulation.get_memory_usage(variables = ['salary']) assert(memory_usage['total_nb_bytes'] > 0) assert(len(memory_usage['by_variable']) == 1)
def couple(): return SimulationBuilder().build_from_entities(tax_benefit_system, openfisca_country_template.situation_examples.couple)
def test_get_entity_not_found(): simulation = SimulationBuilder().build_default_simulation(tax_benefit_system) assert simulation.get_entity(plural = "no_such_entities") is None
def simulation_builder(): return SimulationBuilder()
def _make_simulation(tbs, period, data): builder = SimulationBuilder() builder.default_period = period return builder.build_from_variables(tbs, data)
import numpy as np import pandas from openfisca_core.simulation_builder import SimulationBuilder from openfisca_country_template import CountryTaxBenefitSystem from income_tax_rate_editable_reform import income_tax_rate_editable_reform tax_benefit_system = CountryTaxBenefitSystem() period = '2020-01' salaries = np.array([1500, 2500, 3500]) # Calculate income tax according to current tax rate simulation_builder = SimulationBuilder() simulation_1 = simulation_builder.build_default_simulation(tax_benefit_system, count=3) simulation_1.set_input('salary', '2020-01', salaries) print("> current income_tax_rate", tax_benefit_system.parameters(period).taxes.income_tax_rate) income_tax = simulation_1.calculate('income_tax', period) print("income_tax", income_tax) # Calculate income tax according to csv tax rates csv_data = pandas.read_csv('./income_tax_rates.csv') for income_tax_rate in csv_data.income_tax_rate: print("> reform income_tax_rate", income_tax_rate) specific_legislation = income_tax_rate_editable_reform(tax_benefit_system, income_tax_rate) simulation_builder = SimulationBuilder()
activite_selg_2018_par_titre = pandas.merge(titres, activites_selg_2018, left_on="id", right_on="titre_id") activite_selg_2018_par_titre['renseignements_selg'].fillna(0, inplace=True) print(activite_selg_2018_par_titre[[ # noqa: T001 'id_x', 'communes', 'renseignements_selg', 'annee' ]]) # SIMULATION : CAS ACTUEL # ----------------------- period = '2019' tax_benefit_system = FranceFiscaliteMiniereTaxBenefitSystem() simulation_builder = SimulationBuilder() simulation_builder.create_entities(tax_benefit_system) simulation_builder.declare_person_entity('societe', titres_ids) simulation = simulation_builder.build(tax_benefit_system) simulation.set_input('quantite_sel_abattage_kt', '2018', activite_selg_2018_par_titre['renseignements_selg']) redevance_communale_des_mines_sel_abattage_kt = simulation.calculate( 'redevance_communale_des_mines_sel_abattage_kt', period) print("redevance_communale_des_mines_sel_abattage_kt ?") # noqa: T001 print(redevance_communale_des_mines_sel_abattage_kt) # noqa: T001 # SIMULATION : ESSAI REFORME # --------------------------
}, }, "benunits": { "b1": { "adults": ["pensioner1", "pensioner2"] } }, "households": { "h1": { "adults": ["pensioner1", "pensioner2"] } }, } system = CountryTaxBenefitSystem() simulation_builder = SimulationBuilder() baseline = simulation_builder.build_from_dict(system, TEST_CASE) reform_system = reform_3(system) reform = simulation_builder.build_from_dict(reform_system, TEST_CASE) variables = [ "household_gross_income", "household_net_income_bhc", "gross_income", "net_income", "income_tax", "NI", "capital_gains_tax", "working_tax_credit", "child_tax_credit", "child_benefit",
import pandas import numpy as numpy from openfisca_core.simulation_builder import SimulationBuilder from openfisca_country_template import CountryTaxBenefitSystem tax_benefit_system = CountryTaxBenefitSystem() # READ DATA data_persons = pandas.read_csv('./data_persons.csv') data_households = pandas.read_csv('./data_households.csv') # SIMULATION BUILDER sb = SimulationBuilder() sb.create_entities(tax_benefit_system) persons_ids = data_persons.person_id sb.declare_person_entity('person', persons_ids) # Instanciate the household entity: households_ids = data_households.household_id household_instance = sb.declare_entity('household', households_ids) # Join households data on persons: persons_households = data_persons.household_id persons_households_roles = data_persons.person_role_in_household sb.join_with_persons(household_instance, persons_households, persons_households_roles)
def test_get_entity_not_found(): simulation = SimulationBuilder().build_default_simulation( tax_benefit_system) assert simulation.get_entity(plural="no_such_entities") is None
def new_simulation(): return SimulationBuilder().build_from_dict(tax_benefit_system, situation)
class IndividualSim: def __init__(self, *reforms, year=2020): self.year = year self.reforms = reforms self.system = openfisca_uk.CountryTaxBenefitSystem() self.entities = {var.key: var for var in self.system.entities} self.apply_reforms(self.reforms) self.situation_data = {"people": {}, "benunits": {}, "households": {}} self.varying = False self.num_points = None def build(self): self.sim_builder = SimulationBuilder() self.system = openfisca_uk.CountryTaxBenefitSystem() self.apply_reforms(self.reforms) self.sim = self.sim_builder.build_from_entities( self.system, self.situation_data) def apply_reforms(self, reforms: list) -> None: """Applies a list of reforms to the tax-benefit system. Args: reforms (list): A list of reforms. Each reform can also be a list of reforms. """ for reform in reforms: if isinstance(reform, tuple) or isinstance(reform, list): self.apply_reforms(reform) else: self.system = reform(self.system) def add_data( self, entity="people", name=None, input_period=None, auto_period=True, **kwargs, ): input_period = input_period or self.year entity_plural = self.entities[entity].plural if name is None: name = (entity + "_" + str(len(self.situation_data[entity_plural]) + 1)) if auto_period: data = {} for var, value in kwargs.items(): try: def_period = self.system.get_variable( var).definition_period if def_period in ["eternity", "year"]: input_periods = [input_period] else: input_periods = period(input_period).get_subperiods( def_period) data[var] = { str(subperiod): value for subperiod in input_periods } except: data[var] = value self.situation_data[entity_plural][name] = data self.build() def add_person(self, **kwargs): self.add_data(entity="person", **kwargs) def add_benunit(self, **kwargs): self.add_data(entity="benunit", name="benunit", **kwargs) def add_household(self, **kwargs): self.add_data(entity="household", name="household", **kwargs) def get_entity(self, name): entity_type = [ entity for entity in self.entities.values() if name in self.situation_data[entity.plural] ][0] return entity_type def get_group(self, entity, name): containing_entity = [ group for group in self.situation_data[entity.plural] if name in self.situation_data[entity.plural][group]["adults"] or name in self.situation_data[entity.plural][group]["children"] ][0] return containing_entity def calc(self, var, period=None, target=None, index=None): period = period or self.year entity = self.sim_builder.get_variable_entity(var) if target is not None: target_entity = self.get_entity(target) if target_entity.key != entity.key: target = self.get_group(entity, target) try: result = self.sim.calculate(var, period) except: try: result = self.sim.calculate_add(var, period) except: result = self.sim.calculate_divide(var, period) if self.varying: result = result.reshape( (self.num_points, len(self.situation_data[entity.plural]))).transpose() members = list(self.situation_data[entity.plural]) if index is not None: index = min(len(members) - 1, index) if target is not None: index = members.index(target) if target is not None or index is not None: return result[index] return result def calc_deriv( self, var, wrt="employment_income", period=None, var_target=None, wrt_target=None, ): period = period or self.year y = self.calc(var, period=period, target=var_target) x = self.calc(wrt, period=period, target=wrt_target) try: y = y.squeeze() except: pass try: x = x.squeeze() except: pass x = x.astype(np.float32) y = y.astype(np.float32) assert (len(y) > 1 and len(x) > 1 ), "Simulation must vary on an axis to calculate derivatives." deriv = (y[1:] - y[:-1]) / (x[1:] - x[:-1]) deriv = np.append(deriv, deriv[-1]) return deriv def calc_mtr( self, target="household_net_income", wrt="employment_income", wrt_target=None, var_target=None, ): return 1 - self.calc_deriv( target, wrt=wrt, wrt_target=wrt_target, var_target=var_target) def reset_vary(self): del self.situation_data["axes"] self.varying = False self.num_points = None def vary(self, var, min=0, max=200000, step=100, index=0, period=None): period = period or self.year if "axes" not in self.situation_data: self.situation_data["axes"] = [[]] count = int((max - min) / step) self.situation_data["axes"][0] += [{ "count": count, "name": var, "min": min, "max": max, "period": period, "index": index, }] self.build() self.varying = True self.num_points = count
from openfisca_core.simulation_builder import SimulationBuilder from openfisca_france import FranceTaxBenefitSystem tbs = FranceTaxBenefitSystem() sb = SimulationBuilder() simulation = sb.build_default_simulation(tbs, count=3) period = '2020-01' print(simulation.calculate('smic_proratise', period))
def simulation(period, data, tbs): # Traduction des roles attribués au format openfisca data["quimenof"] = "enfant" data.loc[data["quifoy"] == 1, "quimenof"] = "conjoint" data.loc[data["quifoy"] == 0, "quimenof"] = "personne_de_reference" data["quifoyof"] = "personne_a_charge" data.loc[data["quifoy"] == 1, "quifoyof"] = "conjoint" data.loc[data["quifoy"] == 0, "quifoyof"] = "declarant_principal" data["quifamof"] = "enfant" data.loc[data["quifam"] == 1, "quifamof"] = "conjoint" data.loc[data["quifam"] == 0, "quifamof"] = "demandeur" sb = SimulationBuilder() sb.create_entities(tbs) sb.declare_person_entity("individu", data.index) # Creates openfisca entities and generates grouped listentities = {"foy": "foyer_fiscal", "men": "menage", "fam": "famille"} instances = {} dictionnaire_datagrouped = {"individu": data} for ent, ofent in listentities.items(): persons_ent = data["id" + ent].values persons_ent_roles = data["qui" + ent + "of"].values ent_ids = data["id" + ent].unique() instances[ofent] = sb.declare_entity(ofent, ent_ids) sb.join_with_persons(instances[ofent], persons_ent, roles=persons_ent_roles) # The following ssumes data defined for an entity are the same for all rows in # the same entity. Or at least that the first non null value found for an # entity will always be the total value for an entity (which is the case for # f4ba). These checks are performed in the checkdata function defined below. dictionnaire_datagrouped[ofent] = ( data.groupby("id" + ent, as_index=False).first().sort_values(by="id" + ent) ) # These variables should not be attributed to any OpenFisca Entity columns_not_OF_variables = set( [ "idmen", "idfoy", "idfam", "noindiv", "level_0", "quifam", "quifoy", "quimen", "idmen_x", "idmen_y", "wprm", "index", "idmen_original", "idfoy_original", "idfam_original", "quifamof", "quifoyof", "quimenof", ] ) simulation = sb.build(tbs) memory_config = MemoryConfig( max_memory_occupation=0.95, # When 95% of the virtual memory is full, switch to disk storage priority_variables=["salary", "age"], # Always store these variables in memory variables_to_drop=non_cached_variables, ) simulation.memory_config = memory_config # Attribution des variables à la bonne entité OpenFisca for colonne in data.columns: if colonne not in columns_not_OF_variables: # try: simulation.set_input( colonne, period, dictionnaire_datagrouped[tbs.get_variable(colonne).entity.key][colonne], ) return simulation, dictionnaire_datagrouped
def new_simulation(test_case, period=MONTH): builder = SimulationBuilder() builder.set_default_period(period) return builder.build_from_entities(tax_benefit_system, test_case)