Model module

The main MESA model for the agent-based simulation of heating system adoption.

This module defines the Prototype_Model class, which handles the entire agent-based simulation. It is responsible for initialising the environment, creating all agents (Houses, Houseowners, Plumbers, Energy Advisors), managing the simulation schedule, collecting data, and running the simulation loop. It also handles dynamic updates to the environment, such as changes in fuel costs or subsidy availability.

Authors:
class Prototype_Model(*args: Any, **kwargs: Any)[source]

Bases: Model

The main MESA model for simulating heating system replacement decisions.

This class sets up and runs the agent-based simulation. It initialises the geographical space (GeoSpace), creates and populates it with agents based on input data (e.g., GeoJSON), and manages their interactions through a scheduler. The model also handles scenario-specific interventions, dynamic environmental changes, and comprehensive data collection.

Attributes:
spacemesa_geo.GeoSpace

The geographical environment where agents are located.

schedulemesa.time.RandomActivationByType

The scheduler that controls the order of agent activation.

scenarioScenario

The scenario object defining interventions and targets for the simulation run.

datacollectormesa.DataCollector

The MESA object responsible for collecting model- and agent-level data.

gridshobnetpy.SHoBNetworkGrid

The social network grid managing interactions between Houseowner agents.

num_plumbersint

The number of Plumber agents in the model.

num_energy_advisorsint

The number of EnergyAdvisor agents in the model.

dropout_counterpd.DataFrame

A DataFrame tracking the reasons why houseowners did not choose certain heating systems.

obstaclesdict

A dictionary for tracking agents at various stages of the decision-making process for target heating systems.

Initializes the simulation model.

This method orchestrates the complete setup of the simulation environment. It involves creating the geographical space, loading and processing building data from a GeoJSON file, and instantiating all agent populations: Houses, Houseowners with specific milieu and economic profiles, Plumbers, and Energy Advisors. It also establishes the social network between houseowners, configures scenario-specific parameters, and prepares a comprehensive data collector for tracking simulation outputs.

Parameters:
Pint

The number of Plumber agents to create.

scenariostr

The name of the scenario class to be used for the simulation.

Eint

The number of Energy Advisor agents to create.

subsidy_to_observestr, optional

A specific subsidy to observe for visualization purposes. Defaults to None.

known_hs_to_observestr, optional

A specific heating system to observe for visualization. Defaults to None.

verbosebool, optional

If True, enables print statements during initialization. Defaults to True.

geojson_pathstr, optional

The file path to the GeoJSON file containing house data.

heating_distribution

Agent creator

step()[source]

Executes a single time step in the simulation.

This method advances the model by one step. It first updates dynamic environmental variables (like fuel costs and subsidy availability), then applies any scenario-specific impacts, activates all scheduled agents to perform their actions, and finally collects all specified data for this step.

run(steps, run_id, config_id)[source]

Runs the simulation for a specified number of steps and saves the results.

This method iterates through the step() method for the given number of steps. After the simulation is complete, it processes the data collected by the DataCollector and saves it to output files (e.g., CSV, Pickle).

Parameters:
stepsint

The total number of steps to run the simulation.

run_idstr or int

A unique identifier for this specific simulation run, used for file naming.

config_idstr or int

An identifier for the configuration used in this run.

update_ownership()[source]

NOTE: Needs to be finalised by generating a social network for the new agent, otherwise it will not have any connections, including spatial neighbours. Then the method should be called at the very beginning of every model step. Also needs testing. Also refactor cognitive resource, it should not be random. —————— Simulates the change of house ownership for each houseowner.

Iterates through all Houseowner agents and, based on a small probability, replaces an existing houseowner with a new one. The new houseowner is generated with a fresh set of socio-demographic and psychological attributes, but inherits the same house. The old agent is removed from the model schedule and space, and the new one is added.

update_availability()[source]

Updates the availability of heating systems based on the current step.

If a heating system’s availability term has expired, it is added to the list of globally infeasible options for all agents.

update_contracts()[source]

Updates the remaining term of fixed-price fuel contracts for houseowners.

update_emissions()[source]

Updates the emissions factors for heating systems based on dynamic data.

If the current step corresponds to a scheduled change in emissions, this method updates the heating_params_table and recalculates the emissions for all installed systems of that type.

update_fuel_costs()[source]

Updates fuel costs for heating systems based on dynamic data.

If the current step corresponds to a scheduled change in fuel price, this method updates the heating_params_table and recalculates the fuel costs for all installed systems not under a fixed-price contract. It may also trigger a Trigger_fuel_price for affected houseowners.

update_subsidies()[source]

Removes temporary subsidies from the model when they expire.

create_information_sources()[source]

Creates and returns a list of all available information source objects.

determine_highest_milieu(row)[source]

Defines the milieu with the highest probability

map_milieus(row)[source]

Maps a milieu group number to its corresponding string label.

Parameters:
rowpd.Series

A row from the GeoJSON DataFrame containing milieu group data.

Returns:
str

The string label for the milieu (e.g., ‘Leading’).

generate_heating_system(oil, gas, heat, elec, pellet)[source]

Generates a random heating system instance based on a given probability distribution.

Parameters:
oil, gas, heat, elec, pelletfloat

The probabilities for each respective heating system type.

Returns:
Heating_system

An instance of a randomly chosen heating system with a generated age.

generate_clipped_age(min_val, max_val, mean, sd)[source]

Generates a system age from a truncated normal distribution.

Returns:
int

The generated age in simulation steps (weeks).

distribute_heating_systems()[source]

Assigns initial heating systems to houses based on milieu-specific distributions.

define_income(milieu: str)[source]

Generates a weekly income for a houseowner from a milieu-specific distribution. This time truncated normal.

Parameters:
milieustr

The milieu type of the houseowner.

Returns:
int

The generated weekly income.

define_risk_tolerance(milieu: str)[source]

Defines a risk tolerance value for a houseowner based on their milieu.

Parameters:
milieustr

The milieu type of the houseowner.

Returns:
float

The agent’s risk tolerance value.

define_cognitive_resource(milieu: str)[source]

Produces milieu-specific cognitive resource values

Parameters:
milieustr

The milieu type of the houseowner.

Returns:
int

The agent’s cognitive resource value.

initial_meetings(agent, share=1.0)[source]

Performs initial knowledge spread to populate social norm-related memory parts of the Houseowner agents

Parameters:
agentHouseowner

The agent to perform meetings.

share: float

The share of predecessor neighbours to meet

calculate_emissions()[source]

Calculates the mean annual emissions across all houses in the model.

calculate_energy_demand()[source]

Calculates the mean annual energy demand across all houses.

calculate_total_expenses()[source]

Calculates the mean Levelized Cost of Heat (LCOH) across all houses.

get_replacements_counter()[source]

Returns a copy of the dictionary counting heating system replacements.

get_changes_counter()[source]

Returns a copy of the dictionary counting changes in heating technology.

get_information_source_calls()[source]

Returns a dictionary summarising the calls to different information sources.

get_dropouts()[source]

Returns a dictionary summarising the reasons agents dropped certain HS options.

get_heating_distribution()[source]

Returns a copy of the dictionary tracking the distribution of installed heating systems.

get_triggers_by_type()[source]

Returns a copy of the dictionary tracking the triggers.

get_subsidised_hs()[source]

Returns a number indicating the amount of houses with a subsidised heating system.

get_subsidies()[source]

Returns the the volume of subsidies covered during a run

get_loans()[source]

Returns the the volume of loans taken during a run

get_cognitive_resource()[source]

Returns the the volume cognitive resource spent

get_obstacles()[source]

Returns counted obstacles for each heating system in a new dictionary

get_stage_flows()[source]

Returns stage flows as a nested dictionary

get_evaluation_quartiles()[source]

Computes quartiles of differences for each evaluation stored in evaluation_factors for all agents.

For each agent that has evaluation_factors, for each outer key (system type), this method computes, for each evaluation column, the difference between the evaluation of an inner key (target system) and the evaluation of the outer key (representative). Differences are collected from all agents. Finally, for each outer key and inner key, quartiles (Q1, median, Q3) are computed for each attribute.

Returns:
quartile_dictdict
A nested dictionary where:
  • The first-level keys are the outer system types.

  • The second-level keys are the inner system types (all keys from the inner dictionary except the outer key).

  • Each inner value is a dictionary mapping each attribute to a tuple of quartiles (Q1, median, Q3) representing the distribution of differences (inner - outer) for that attribute.

get_attribute_ratings()[source]

Creates a nested dictionary of quartiles of differences of opinions of all owners of non-target systems towards target systems relative to their owned system.

Returns:
quartile_dictdict
A nested dictionary where:
  • The first-level keys are non-target systems (i.e. the owned system of the agent).

  • The second-level keys are target systems.

  • Each inner value is a dictionary mapping each attribute to a tuple of quartiles (Q1, median, Q3) representing the distribution of differences between the target system’s ratings and the owned system’s ratings.

count_known_subsidies()[source]

Counts the total number of times each subsidy is known by a houseowner.

count_known_hs()[source]

Counts the total number of times each heating system is known by a houseowner.

calculate_target_fulfilment(scenario)[source]

Calculate the fulfilment percentages for each heating system in the scenario.

Parameters:
scenarioobject

The scenario object containing the target distribution of heating systems.

Returns:
float

The total fulfillment percentage.

count_heating_system(heating_system)[source]

Counts the number of houses with a specific heating system installed.

Parameters:
heating_systemstr

The class name of the heating system to count.

Returns:
int

The total count of the specified system.

gather_house_data()[source]

Generates an Excel file with summary data for all houses in the model.