Source code for macrostat.models.GL06SIMEX.behavior

"""
Behavior classes for the Godley-Lavoie 2006 SIMEX model.
This module will define the forward and simulate behavior of the Godley-Lavoie 2006 SIMEX model.
"""

__author__ = ["Karl Naumann-Woleske"]
__credits__ = ["Karl Naumann-Woleske"]
__license__ = "MIT"
__maintainer__ = ["Karl Naumann-Woleske"]

import logging

import torch

from macrostat.core.behavior import Behavior
from macrostat.models.GL06SIMEX.parameters import ParametersGL06SIMEX
from macrostat.models.GL06SIMEX.scenarios import ScenariosGL06SIMEX
from macrostat.models.GL06SIMEX.variables import VariablesGL06SIMEX

logger = logging.getLogger(__name__)


[docs] class BehaviorGL06SIMEX(Behavior): """Behavior class for the Godley-Lavoie 2006 SIMEX model.""" version = "GL06SIMEX" def __init__( self, parameters: ParametersGL06SIMEX | None = None, scenarios: ScenariosGL06SIMEX | None = None, variables: VariablesGL06SIMEX | None = None, scenario: int = 0, debug: bool = False, ): """Initialize the behavior of the Godley-Lavoie 2006 SIMEX model. Parameters ---------- parameters: ParametersGL06SIMEX | None The parameters of the model. scenarios: ScenariosGL06SIMEX | None The scenarios of the model. variables: VariablesGL06SIMEX | None The variables of the model. record: bool Whether to record the model output. scenario: int The scenario to use for the model. """ if parameters is None: parameters = ParametersGL06SIMEX() if scenarios is None: scenarios = ScenariosGL06SIMEX() if variables is None: variables = VariablesGL06SIMEX() super().__init__( parameters=parameters, scenarios=scenarios, variables=variables, scenario=scenario, debug=debug, )
[docs] def initialize(self): r"""Initialize the behavior of the Godley-Lavoie 2006 SIMEX model. Within the book the initialization is generally to set all non-scenario variables to zero. Accordingly Equations --------- .. math:: :nowrap: \begin{align} C_d(0) &= C_s(0) = 0 \\ G_d(0) &= G_s(0) = 0 \\ T_s(0) &= T_d(0) = 0 \\ N_s(0) &= N_d(0) = 0 \\ YD(0) &= 0 \\ W(0) &= 0 \\ H_s(0) &= 0 \\ H_h(0) &= 0 \end{align} Dependency ---------- Sets ----- - ConsumptionDemand - ConsumptionSupply - GovernmentDemand - GovernmentSupply - TaxSupply - TaxDemand - LabourSupply - LabourDemand - DisposableIncome - WageRate - HouseholdMoneyStock """ self.state["ConsumptionDemand"] = torch.zeros(1) self.state["ConsumptionSupply"] = torch.zeros(1) self.state["GovernmentDemand"] = torch.zeros(1) self.state["GovernmentSupply"] = torch.zeros(1) self.state["TaxSupply"] = torch.zeros(1) self.state["TaxDemand"] = torch.zeros(1) self.state["LabourSupply"] = torch.zeros(1) self.state["LabourDemand"] = torch.zeros(1) self.state["ExpectedDisposableIncome"] = torch.zeros(1) self.state["DisposableIncome"] = torch.zeros(1) self.state["HouseholdMoneyStock"] = torch.zeros(1)
[docs] def step(self, t: int, scenario: dict, params: dict | None = None): """Step function of the Godley-Lavoie 2006 SIMEX model.""" kwargs = dict(t=t, scenario=scenario, params=params) self.government_supply(**kwargs) self.expected_disposable_income(**kwargs) self.consumption_demand(**kwargs) self.consumption_supply(**kwargs) self.national_income(**kwargs) self.labour_demand(**kwargs) self.labour_supply(**kwargs) self.tax_demand(**kwargs) self.tax_supply(**kwargs) self.labour_income(**kwargs) self.disposable_income(**kwargs) self.government_money_stock(**kwargs) self.household_money_demand(**kwargs) self.household_money_stock(**kwargs)
[docs] def government_supply( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""In the model it is assumed that the supply will adjust to the demand, that is, whatever is demanded can and will be produced. Equation (3.2) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: G_s(t) = G_d(t) Dependency ---------- - scenario: GovernmentDemand Sets ----- - GovernmentSupply """ self.state["GovernmentSupply"] = scenario["GovernmentDemand"]
[docs] def labour_demand( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""We can resolve the labour demand from the national income equation, together with the consumption demand (+ disposable income) and the government demand knowing that labour demand is equal to labour supply. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: N_d(t) =\frac{Y(t)}{W(t)} Dependency ---------- - state: NationalIncome - scenario: WageRate Sets ----- - LabourDemand """ self.state["LabourDemand"] = self.state["NationalIncome"] / scenario["WageRate"]
[docs] def labour_supply( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""In the model it is assumed that the supply will be equal to the amount of labour demanded. Equation (3.4) in the book Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: N_s(t) = N_d(t) Dependency ---------- - state: LabourDemand Sets ----- - LabourSupply """ self.state["LabourSupply"] = self.state["LabourDemand"]
[docs] def tax_demand(self, t: torch.tensor, scenario: dict, params: dict | None = None): r"""The tax demand is a function of the tax rate, the labour supply, and the wage rate. Equation (3.6) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: T_d(t) = \theta N_s(t) W(t) Dependency ---------- - parameters: TaxRate - state: LabourSupply - scenario: WageRate Sets ----- - TaxDemand """ self.state["TaxDemand"] = ( params["TaxRate"] * self.state["LabourSupply"] * scenario["WageRate"] )
[docs] def tax_supply(self, t: torch.tensor, scenario: dict, params: dict | None = None): r"""In the model it is assumed that the supply will be equal to the amount of taxes demanded. Equation (3.3) in the book Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: T_s(t) = T_d(t) Dependency ---------- - state: TaxDemand Sets ----- - TaxSupply """ self.state["TaxSupply"] = self.state["TaxDemand"]
[docs] def expected_disposable_income( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""The expected disposable income is simply the prior period's disposable income. Equation (3.20) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Equations --------- .. math:: YD^e(t) = YD(t-1) Dependency ---------- - prior: DisposableIncome Sets ----- - ExpectedDisposableIncome """ self.state["ExpectedDisposableIncome"] = self.prior["DisposableIncome"]
[docs] def labour_income( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""The labour income is the wage rate times the labour supply. This is an intermediate variable used to calculate the disposable income, but is computed explicitly here to compute the transaction flows. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: W(t) N_s(t) Dependency ---------- - scenario: WageRate - state: LabourSupply Sets ----- - LabourIncome """ self.state["LabourIncome"] = scenario["WageRate"] * self.state["LabourSupply"]
[docs] def disposable_income( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""The disposable income is the wage bill minus the taxes. Equation (3.5) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Equations --------- .. math:: YD(t) = W(t) N_s(t) - T_s(t) Dependency ---------- - state: LabourIncome - state: TaxSupply Sets ----- - DisposableIncome """ self.state["DisposableIncome"] = ( self.state["LabourIncome"] - self.state["TaxSupply"] )
[docs] def consumption_demand( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""The consumption demand is a function of the disposable income, the propensity to consume income, and the propensity to consume savings. Equation (3.7) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: C_d(t) = \alpha_1 YD(t) + \alpha_2 H_h(t-1) Dependency ---------- - state: ExpectedDisposableIncome - prior: HouseholdMoneyStock Sets ----- - ConsumptionDemand """ self.state["ConsumptionDemand"] = ( params["PropensityToConsumeIncome"] * self.state["ExpectedDisposableIncome"] + params["PropensityToConsumeSavings"] * self.prior["HouseholdMoneyStock"] )
[docs] def consumption_supply( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""In the model it is assumed that the supply will adjust to the demand, that is, whatever is demanded can and will be produced. Equation (3.1) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: C_s(t) = C_d(t) Dependency ---------- - state: ConsumptionDemand Sets ----- - ConsumptionSupply """ self.state["ConsumptionSupply"] = self.state["ConsumptionDemand"]
[docs] def government_money_stock( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""The government money stock is a function of the government demand, and the tax supply. Equation (3.8) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: H_s(t) = H_s(t-1) + G_d(t) - T_d(t) Dependency ---------- - scenario: GovernmentDemand - state: TaxDemand - prior: GovernmentMoneyStock Sets ----- - GovernmentMoneyStock """ self.state["GovernmentMoneyStock"] = ( self.prior["GovernmentMoneyStock"] + scenario["GovernmentDemand"] - self.state["TaxDemand"] )
[docs] def household_money_demand( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""The household demand for money is equivalent to their expected income in excess of consumption demand Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: H_d(t) = H_h(t-1) + YD^e(t) - C_d(t) Dependency ---------- - state: ExpectedDisposableIncome - state: ConsumptionDemand - prior: HouseholdMoneyStock Sets ----- - HouseholdMoneyDemand """ self.state["HouseholdMoneyDemand"] = ( self.prior["HouseholdMoneyStock"] + self.state["ExpectedDisposableIncome"] - self.state["ConsumptionDemand"] )
[docs] def household_money_stock( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""The household money stock is a function of the disposable income, the propensity to consume income, and the propensity to consume savings. Equation (3.9) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: H_h(t) = H_h(t-1) + YD(t) - C_d(t) Dependency ---------- - state: DisposableIncome - state: ConsumptionDemand - prior: HouseholdMoneyStock Sets ----- - HouseholdMoneyStock """ self.state["HouseholdMoneyStock"] = ( self.prior["HouseholdMoneyStock"] + self.state["DisposableIncome"] - self.state["ConsumptionDemand"] )
[docs] def national_income( self, t: torch.tensor, scenario: dict, params: dict | None = None ): r"""The national income is the sum of the consumption demand, the government demand, and the tax supply. Equation (3.10) in the book. Parameters ---------- t : torch.tensor Current time step scenario : dict Scenario dictionary Equations --------- .. math:: Y(t) = C_s(t) + G_s(t) Dependency ---------- - state: ConsumptionSupply - state: GovernmentSupply Sets ----- - NationalIncome """ self.state["NationalIncome"] = ( self.state["ConsumptionSupply"] + self.state["GovernmentSupply"] )