From a7ea228977ed29b098ea1f349fc90daf8a98ff99 Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Wed, 19 Jul 2023 14:36:55 -0400 Subject: [PATCH 01/10] Create variables.py --- HARK/variables.py | 164 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 HARK/variables.py diff --git a/HARK/variables.py b/HARK/variables.py new file mode 100644 index 000000000..efe3093fb --- /dev/null +++ b/HARK/variables.py @@ -0,0 +1,164 @@ +from dataclasses import dataclass, field +from typing import Optional, Union +from warnings import warn + +import numpy as np +import xarray as xr +from yaml import YAMLObject + +rng = np.random.default_rng() + + +@dataclass +class Variable(YAMLObject): + name: str # The name of the variable, required + domain: Union[list, tuple] # The domain of the state, required + is_discrete: bool = False # Whether the state is continuous or discrete, optional + attrs: dict = field(default_factory=dict) # Additional attributes, optional + yaml_tag: str = "!Variable" # The YAML tag for the variable, required + + def __post_init__(self): + for key in ["long_name", "short_name", "latex_repr"]: + self.attrs.setdefault(key, self.name) + + +@dataclass +class VariableSpace(YAMLObject): + variables: list[Variable] + yaml_tag: str = "!VariableSpace" + + +@dataclass +class State(Variable): + yaml_tag: str = "!State" + + def assign_values(self, values): + return make_state(values, self.name, self.attrs) + + def discretize(self, min, max, N, method): + # linear for now + self.assign_values(np.linspace(min, max, N)) + + +@dataclass +class StateSpace(VariableSpace): + states: list[State] + yaml_tag: str = "!StateSpace" + + def __post_init__(self): + self.states = xr.merge(self.states) + + +@dataclass +class Action(Variable): + """ + Class for representing actions. Actions are variables that are chosen by the agent. + Can also be called a choice, control, decision, or a policy. + + Args: + Variable (_type_): _description_ + """ + + yaml_tag: str = "!Action" + + is_optimal: bool = True + + def discretize(self, *args, **kwargs): + warn("Actions cannot be discretized.") + + +@dataclass +class ActionSpace: + actions: list[Action] + yaml_tag: str = "!ActionSpace" + + def __post_init__(self): + self.actions = xr.merge(self.actions) + + +@dataclass +class Shock(Variable): + """ + Class for representing shocks. Shocks are variables that are not + chosen by the agent. + Can also be called a random variable, or a state variable. + + Args: + Variable (_type_): _description_ + """ + + yaml_tag: str = "!Shock" + + +@dataclass +class ShockSpace: + shocks: list[Shock] + yaml_tag: str = "!ShockSpace" + + def __post_init__(self): + self.shocks = xr.merge(self.shocks) + + +@dataclass +class Auxilliary(Variable): + yaml_tag: str = "!Auxilliary" + + +def make_state( + values: np.ndarray, + name: Optional[str] = None, + attrs: Optional[dict] = None, +) -> xr.Dataset: + """ + Function to create a state with given values, name and attrs. + + Parameters: + values (np.ndarray): The values for the state. + name (str, optional): The name of the state. Defaults to 'state'. + attrs (dict, optional): The attrs for the state. Defaults to None. + + Returns: + State: An xarray DataArray representing the state. + """ + # Use a default name only when no name is provided + name = name or f"state{rng.integers(0, 100)}" + attrs = attrs or {} + + return xr.Dataset( + { + name: xr.DataArray( + values, + name=name, + dims=(name,), + attrs=attrs, + ) + } + ) + + +def make_states( + values: Union[np.ndarray, list], + names: Optional[list[str]] = None, + attrs: Optional[list[dict]] = None, +) -> xr.Dataset: + """ + Function to create states with given values, names and attrs. + + Parameters: + values (Union[np.ndarray, States]): The values for the states. + names (list[str], optional): The names of the states. Defaults to None. + attrs (list[dict], optional): The attrs for the states. Defaults to None. + + Returns: + States: An arrayray Dataset representing the states. + """ + + # Use default names and attrs only when they are not provided + names = names or [f"state{rng.integers(0, 100)}" for _ in range(len(values))] + attrs = attrs or [{}] * len(values) + + states = [ + make_state(value, name, attr) for value, name, attr in zip(values, names, attrs) + ] + + return xr.merge(states) From 19ceb72c3c620fb02d161d4cb60a65e2503771f2 Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Wed, 19 Jul 2023 14:40:50 -0400 Subject: [PATCH 02/10] values can be list or array --- HARK/variables.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/HARK/variables.py b/HARK/variables.py index efe3093fb..db950fa8c 100644 --- a/HARK/variables.py +++ b/HARK/variables.py @@ -152,10 +152,14 @@ def make_states( Returns: States: An arrayray Dataset representing the states. """ + if isinstance(values, list): + values_len = len(values) + elif isinstance(values, np.ndarray): + values_len = values.shape[0] # Use default names and attrs only when they are not provided - names = names or [f"state{rng.integers(0, 100)}" for _ in range(len(values))] - attrs = attrs or [{}] * len(values) + names = names or [f"state{rng.integers(0, 100)}" for _ in range(values_len)] + attrs = attrs or [{}] * values_len states = [ make_state(value, name, attr) for value, name, attr in zip(values, names, attrs) From f41c9446557660b7510653e60f0df5958f7731fe Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Wed, 19 Jul 2023 14:45:10 -0400 Subject: [PATCH 03/10] rename make_states --- HARK/variables.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/HARK/variables.py b/HARK/variables.py index db950fa8c..90ec3281e 100644 --- a/HARK/variables.py +++ b/HARK/variables.py @@ -33,7 +33,7 @@ class State(Variable): yaml_tag: str = "!State" def assign_values(self, values): - return make_state(values, self.name, self.attrs) + return make_state_array(values, self.name, self.attrs) def discretize(self, min, max, N, method): # linear for now @@ -59,9 +59,8 @@ class Action(Variable): Variable (_type_): _description_ """ - yaml_tag: str = "!Action" - is_optimal: bool = True + yaml_tag: str = "!Action" def discretize(self, *args, **kwargs): warn("Actions cannot be discretized.") @@ -104,7 +103,7 @@ class Auxilliary(Variable): yaml_tag: str = "!Auxilliary" -def make_state( +def make_state_array( values: np.ndarray, name: Optional[str] = None, attrs: Optional[dict] = None, @@ -136,7 +135,7 @@ def make_state( ) -def make_states( +def make_states_array( values: Union[np.ndarray, list], names: Optional[list[str]] = None, attrs: Optional[list[dict]] = None, @@ -162,7 +161,8 @@ def make_states( attrs = attrs or [{}] * values_len states = [ - make_state(value, name, attr) for value, name, attr in zip(values, names, attrs) + make_state_array(value, name, attr) + for value, name, attr in zip(values, names, attrs) ] return xr.merge(states) From c523d4b50a819be3cb66e6298c856eeb508d976f Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Tue, 25 Jul 2023 09:45:58 -0400 Subject: [PATCH 04/10] implement abstract classes --- HARK/abstract/tests/consindshk.yml | 52 ++++++ HARK/abstract/variables.py | 265 +++++++++++++++++++++++++++++ HARK/variables.py | 168 ------------------ 3 files changed, 317 insertions(+), 168 deletions(-) create mode 100644 HARK/abstract/tests/consindshk.yml create mode 100644 HARK/abstract/variables.py delete mode 100644 HARK/variables.py diff --git a/HARK/abstract/tests/consindshk.yml b/HARK/abstract/tests/consindshk.yml new file mode 100644 index 000000000..0d9d59ee3 --- /dev/null +++ b/HARK/abstract/tests/consindshk.yml @@ -0,0 +1,52 @@ +--- +states: !StateSpace + variables: + - !State + name: m + short_name: money + long_name: market resources + latex_repr: \mNrm + - !State + name: &name stigma + short_name: &short_name risky share + long_name: &long_name risky share of portfolio + latex_repr: &latex_repr \stigma + +actions: !ActionSpace + variables: + - !Action + name: c + short_name: consumption + long_name: consumption + latex_repr: \cNrm + - !Action + name: *name + short_name: *short_name + long_name: *long_name + latex_repr: *latex_repr + +post_states: !PostStateSpace + variables: + - !PostState + name: a + short_name: assets + long_name: savings + latex_repr: \aNrm + - !PostState + name: *name + short_name: *short_name + long_name: *long_name + latex_repr: *latex_repr + +parameters: !Parameters + variables: + - !Parameter + name: DiscFac + short_name: discount factor + long_name: discount factor + latex_repr: \beta + - !Parameter + name: CRRA + short_name: risk aversion + long_name: coefficient of relative risk aversion + latex_repr: \rho diff --git a/HARK/abstract/variables.py b/HARK/abstract/variables.py new file mode 100644 index 000000000..f0658b890 --- /dev/null +++ b/HARK/abstract/variables.py @@ -0,0 +1,265 @@ +from dataclasses import dataclass, field +from typing import Any, Mapping, Optional, Union +from warnings import warn + +import numpy as np +import xarray as xr +from yaml import SafeLoader, YAMLObject + +rng = np.random.default_rng() + + +@dataclass +class Variable(YAMLObject): + """ + Abstract class for representing variables. Variables are the building blocks + of models. They can be parameters, states, actions, shocks, or auxiliaries. + """ + + name: str # The name of the variable, required + attrs: dict = field(default_factory=dict, kw_only=True) + short_name: str = field(default=None, kw_only=True) + long_name: str = field(default=None, kw_only=True) + latex_repr: str = field(default=None, kw_only=True) + yaml_tag: str = field(default="!Variable", kw_only=False) + yaml_loader = SafeLoader + + def __post_init__(self): + for key in ["long_name", "short_name", "latex_repr"]: + self.attrs.setdefault(key, None) + + @classmethod + def from_yaml(cls, loader, node): + fields = loader.construct_mapping(node, deep=True) + return cls(**fields) + + def __repr__(self): + """ + String representation of the variable. + + Returns: + str: The string representation of the variable. + """ + return f"{self.__class__.__name__}({self.name})" + + +@dataclass +class VariableSpace(YAMLObject): + """ + Abstract class for representing a collection of variables. + """ + + variables: list[Variable] + yaml_tag: str = field(default="!VariableSpace", kw_only=True) + yaml_loader = SafeLoader + + def __post_init__(self): + """ + Save the variables in a dictionary for easy access. + """ + self.variables = {var.name: var for var in self.variables} + + +@dataclass +class Parameter(Variable): + """ + A `Parameter` is a variable that has a fixed value. + """ + + value: Union[int, float] = 0 + yaml_tag: str = field(default="!Parameter", kw_only=True) + + def __repr__(self): + """ + String representation of the parameter. + + Returns: + str: The string representation of the parameter. + """ + return f"{self.__class__.__name__}({self.name}, {self.value})" + + +@dataclass +class Parameters(VariableSpace): + """ + A `Parameters` is a collection of parameters. + """ + + yaml_tag: str = "!Parameters" + + +@dataclass +class Auxiliary(Variable): + """ + Class for representing auxiliaries. Auxiliaries are abstract variables that + have an array structure but are not states, actions, or shocks. They may + include information like domain, measure (discrete or continuous), etc. + """ + + array: Union[list, np.ndarray, xr.DataArray] = None + domain: Union[list, tuple] = field(default=None, kw_only=True) + is_discrete: bool = field(default=False, kw_only=True) + yaml_tag: str = field(default="!Auxiliary", kw_only=True) + + +@dataclass +class AuxiliarySpace(VariableSpace): + """ + A `AuxiliarySpace` is a collection of auxiliary variables. + """ + + yaml_tag: str = "!AuxiliarySpace" + + +@dataclass(kw_only=True) +class State(Auxiliary): + """ + Class for representing a state variable. + """ + + yaml_tag: str = "!State" + + def assign_values(self, values): + return make_state_array(values, self.name, self.attrs) + + def discretize(self, min, max, N, method): + # linear for now + self.assign_values(np.linspace(min, max, N)) + + +@dataclass(kw_only=True) +class StateSpace(AuxiliarySpace): + states: Mapping[str, State] = field(init=False) + yaml_tag: str = "!StateSpace" + + def __post_init__(self): + super().__post_init__() + self.states = xr.merge([self.variables]) + + +@dataclass(kw_only=True) +class PostState(State): + yaml_tag: str = "!PostState" + + +@dataclass(kw_only=True) +class PostStateSpace(StateSpace): + post_states: Mapping[str, State] = field(init=False) + yaml_tag: str = "!PostStateSpace" + + def __post_init__(self): + self.post_states = xr.merge(self.variables) + + +@dataclass(kw_only=True) +class Action(Auxiliary): + """ + Class for representing actions. Actions are variables that are chosen by the agent. + Can also be called a choice, control, decision, or a policy. + + Args: + Variable (_type_): _description_ + """ + + is_optimal: bool = True + yaml_tag: str = "!Action" + + def discretize(self, *args, **kwargs): + warn("Actions cannot be discretized.") + + +@dataclass(kw_only=True) +class ActionSpace(AuxiliarySpace): + actions: Mapping[str, State] = field(init=False) + yaml_tag: str = "!ActionSpace" + + def __post_init__(self): + self.actions = xr.merge(self.variables) + + +@dataclass(kw_only=True) +class Shock(Variable): + """ + Class for representing shocks. Shocks are variables that are not + chosen by the agent. + Can also be called a random variable, or a state variable. + + Args: + Variable (_type_): _description_ + """ + + yaml_tag: str = "!Shock" + + +@dataclass(kw_only=True) +class ShockSpace(VariableSpace): + shocks: list[Shock] + yaml_tag: str = "!ShockSpace" + + def __post_init__(self): + self.shocks = xr.merge(self.shocks) + + +def make_state_array( + values: np.ndarray, + name: Optional[str] = None, + attrs: Optional[dict] = None, +) -> xr.Dataset: + """ + Function to create a state with given values, name and attrs. + + Parameters: + values (np.ndarray): The values for the state. + name (str, optional): The name of the state. Defaults to 'state'. + attrs (dict, optional): The attrs for the state. Defaults to None. + + Returns: + State: An xarray DataArray representing the state. + """ + # Use a default name only when no name is provided + name = name or f"state{rng.integers(0, 100)}" + attrs = attrs or {} + + return xr.Dataset( + { + name: xr.DataArray( + values, + name=name, + dims=(name,), + attrs=attrs, + ) + } + ) + + +def make_states_array( + values: Union[np.ndarray, list], + names: Optional[list[str]] = None, + attrs: Optional[list[dict]] = None, +) -> xr.Dataset: + """ + Function to create states with given values, names and attrs. + + Parameters: + values (Union[np.ndarray, States]): The values for the states. + names (list[str], optional): The names of the states. Defaults to None. + attrs (list[dict], optional): The attrs for the states. Defaults to None. + + Returns: + States: An xarray Dataset representing the states. + """ + if isinstance(values, list): + values_len = len(values) + elif isinstance(values, np.ndarray): + values_len = values.shape[0] + + # Use default names and attrs only when they are not provided + names = names or [f"state{rng.integers(0, 100)}" for _ in range(values_len)] + attrs = attrs or [{}] * values_len + + states = [ + make_state_array(value, name, attr) + for value, name, attr in zip(values, names, attrs) + ] + + return xr.merge(states) diff --git a/HARK/variables.py b/HARK/variables.py deleted file mode 100644 index 90ec3281e..000000000 --- a/HARK/variables.py +++ /dev/null @@ -1,168 +0,0 @@ -from dataclasses import dataclass, field -from typing import Optional, Union -from warnings import warn - -import numpy as np -import xarray as xr -from yaml import YAMLObject - -rng = np.random.default_rng() - - -@dataclass -class Variable(YAMLObject): - name: str # The name of the variable, required - domain: Union[list, tuple] # The domain of the state, required - is_discrete: bool = False # Whether the state is continuous or discrete, optional - attrs: dict = field(default_factory=dict) # Additional attributes, optional - yaml_tag: str = "!Variable" # The YAML tag for the variable, required - - def __post_init__(self): - for key in ["long_name", "short_name", "latex_repr"]: - self.attrs.setdefault(key, self.name) - - -@dataclass -class VariableSpace(YAMLObject): - variables: list[Variable] - yaml_tag: str = "!VariableSpace" - - -@dataclass -class State(Variable): - yaml_tag: str = "!State" - - def assign_values(self, values): - return make_state_array(values, self.name, self.attrs) - - def discretize(self, min, max, N, method): - # linear for now - self.assign_values(np.linspace(min, max, N)) - - -@dataclass -class StateSpace(VariableSpace): - states: list[State] - yaml_tag: str = "!StateSpace" - - def __post_init__(self): - self.states = xr.merge(self.states) - - -@dataclass -class Action(Variable): - """ - Class for representing actions. Actions are variables that are chosen by the agent. - Can also be called a choice, control, decision, or a policy. - - Args: - Variable (_type_): _description_ - """ - - is_optimal: bool = True - yaml_tag: str = "!Action" - - def discretize(self, *args, **kwargs): - warn("Actions cannot be discretized.") - - -@dataclass -class ActionSpace: - actions: list[Action] - yaml_tag: str = "!ActionSpace" - - def __post_init__(self): - self.actions = xr.merge(self.actions) - - -@dataclass -class Shock(Variable): - """ - Class for representing shocks. Shocks are variables that are not - chosen by the agent. - Can also be called a random variable, or a state variable. - - Args: - Variable (_type_): _description_ - """ - - yaml_tag: str = "!Shock" - - -@dataclass -class ShockSpace: - shocks: list[Shock] - yaml_tag: str = "!ShockSpace" - - def __post_init__(self): - self.shocks = xr.merge(self.shocks) - - -@dataclass -class Auxilliary(Variable): - yaml_tag: str = "!Auxilliary" - - -def make_state_array( - values: np.ndarray, - name: Optional[str] = None, - attrs: Optional[dict] = None, -) -> xr.Dataset: - """ - Function to create a state with given values, name and attrs. - - Parameters: - values (np.ndarray): The values for the state. - name (str, optional): The name of the state. Defaults to 'state'. - attrs (dict, optional): The attrs for the state. Defaults to None. - - Returns: - State: An xarray DataArray representing the state. - """ - # Use a default name only when no name is provided - name = name or f"state{rng.integers(0, 100)}" - attrs = attrs or {} - - return xr.Dataset( - { - name: xr.DataArray( - values, - name=name, - dims=(name,), - attrs=attrs, - ) - } - ) - - -def make_states_array( - values: Union[np.ndarray, list], - names: Optional[list[str]] = None, - attrs: Optional[list[dict]] = None, -) -> xr.Dataset: - """ - Function to create states with given values, names and attrs. - - Parameters: - values (Union[np.ndarray, States]): The values for the states. - names (list[str], optional): The names of the states. Defaults to None. - attrs (list[dict], optional): The attrs for the states. Defaults to None. - - Returns: - States: An arrayray Dataset representing the states. - """ - if isinstance(values, list): - values_len = len(values) - elif isinstance(values, np.ndarray): - values_len = values.shape[0] - - # Use default names and attrs only when they are not provided - names = names or [f"state{rng.integers(0, 100)}" for _ in range(values_len)] - attrs = attrs or [{}] * values_len - - states = [ - make_state_array(value, name, attr) - for value, name, attr in zip(values, names, attrs) - ] - - return xr.merge(states) From ccdf96e50d77545885dc4cb6726b6af14d9dc781 Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Tue, 25 Jul 2023 10:46:27 -0400 Subject: [PATCH 05/10] remove xarray merge for now --- HARK/abstract/variables.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/HARK/abstract/variables.py b/HARK/abstract/variables.py index f0658b890..2f243aa56 100644 --- a/HARK/abstract/variables.py +++ b/HARK/abstract/variables.py @@ -1,5 +1,5 @@ from dataclasses import dataclass, field -from typing import Any, Mapping, Optional, Union +from typing import Mapping, Optional, Union from warnings import warn import numpy as np @@ -27,6 +27,9 @@ class Variable(YAMLObject): def __post_init__(self): for key in ["long_name", "short_name", "latex_repr"]: self.attrs.setdefault(key, None) + self.name = self.name.strip() + if not self.name: + raise ValueError("Empty variable name") @classmethod def from_yaml(cls, loader, node): @@ -59,6 +62,11 @@ def __post_init__(self): """ self.variables = {var.name: var for var in self.variables} + @classmethod + def from_yaml(cls, loader, node): + fields = loader.construct_mapping(node, deep=True) + return cls(**fields) + @dataclass class Parameter(Variable): @@ -68,6 +76,7 @@ class Parameter(Variable): value: Union[int, float] = 0 yaml_tag: str = field(default="!Parameter", kw_only=True) + yaml_loader = SafeLoader def __repr__(self): """ @@ -134,7 +143,7 @@ class StateSpace(AuxiliarySpace): def __post_init__(self): super().__post_init__() - self.states = xr.merge([self.variables]) + self.states = self.variables @dataclass(kw_only=True) @@ -148,7 +157,8 @@ class PostStateSpace(StateSpace): yaml_tag: str = "!PostStateSpace" def __post_init__(self): - self.post_states = xr.merge(self.variables) + super().__post_init__() + self.post_states = self.variables @dataclass(kw_only=True) @@ -174,7 +184,8 @@ class ActionSpace(AuxiliarySpace): yaml_tag: str = "!ActionSpace" def __post_init__(self): - self.actions = xr.merge(self.variables) + super().__post_init__() + self.actions = self.variables @dataclass(kw_only=True) @@ -197,7 +208,8 @@ class ShockSpace(VariableSpace): yaml_tag: str = "!ShockSpace" def __post_init__(self): - self.shocks = xr.merge(self.shocks) + super().__post_init__() + self.shocks = self.variables def make_state_array( @@ -262,4 +274,4 @@ def make_states_array( for value, name, attr in zip(values, names, attrs) ] - return xr.merge(states) + return xr.merge([states]) From 207696f2eb1f7a1b09fb80bc27ec470c91c16d7c Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Tue, 25 Jul 2023 10:46:41 -0400 Subject: [PATCH 06/10] add tests --- HARK/abstract/tests/consindshk.yml | 13 ------- HARK/abstract/tests/consindshk_full.yml | 52 +++++++++++++++++++++++++ HARK/abstract/tests/test_variables.py | 19 +++++++++ 3 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 HARK/abstract/tests/consindshk_full.yml create mode 100644 HARK/abstract/tests/test_variables.py diff --git a/HARK/abstract/tests/consindshk.yml b/HARK/abstract/tests/consindshk.yml index 0d9d59ee3..5979c85bc 100644 --- a/HARK/abstract/tests/consindshk.yml +++ b/HARK/abstract/tests/consindshk.yml @@ -37,16 +37,3 @@ post_states: !PostStateSpace short_name: *short_name long_name: *long_name latex_repr: *latex_repr - -parameters: !Parameters - variables: - - !Parameter - name: DiscFac - short_name: discount factor - long_name: discount factor - latex_repr: \beta - - !Parameter - name: CRRA - short_name: risk aversion - long_name: coefficient of relative risk aversion - latex_repr: \rho diff --git a/HARK/abstract/tests/consindshk_full.yml b/HARK/abstract/tests/consindshk_full.yml new file mode 100644 index 000000000..0d9d59ee3 --- /dev/null +++ b/HARK/abstract/tests/consindshk_full.yml @@ -0,0 +1,52 @@ +--- +states: !StateSpace + variables: + - !State + name: m + short_name: money + long_name: market resources + latex_repr: \mNrm + - !State + name: &name stigma + short_name: &short_name risky share + long_name: &long_name risky share of portfolio + latex_repr: &latex_repr \stigma + +actions: !ActionSpace + variables: + - !Action + name: c + short_name: consumption + long_name: consumption + latex_repr: \cNrm + - !Action + name: *name + short_name: *short_name + long_name: *long_name + latex_repr: *latex_repr + +post_states: !PostStateSpace + variables: + - !PostState + name: a + short_name: assets + long_name: savings + latex_repr: \aNrm + - !PostState + name: *name + short_name: *short_name + long_name: *long_name + latex_repr: *latex_repr + +parameters: !Parameters + variables: + - !Parameter + name: DiscFac + short_name: discount factor + long_name: discount factor + latex_repr: \beta + - !Parameter + name: CRRA + short_name: risk aversion + long_name: coefficient of relative risk aversion + latex_repr: \rho diff --git a/HARK/abstract/tests/test_variables.py b/HARK/abstract/tests/test_variables.py new file mode 100644 index 000000000..fbc31d4d4 --- /dev/null +++ b/HARK/abstract/tests/test_variables.py @@ -0,0 +1,19 @@ +import unittest + +import numpy as np +import yaml + +import HARK.abstract.variables + + +class test_pyyaml(unittest.TestCase): + def setUp(self): + pass + + def test_partial(self): + with open("consindshk.yml") as f: + data = yaml.safe_load(f) + + def test_full(self): + with open("consindshk_full.yml") as f: + data = yaml.safe_load(f) From 918177d5c57942e480fcd2b18bb7cb53cf4bb51c Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Tue, 25 Jul 2023 11:10:54 -0400 Subject: [PATCH 07/10] update path --- HARK/abstract/tests/test_variables.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/HARK/abstract/tests/test_variables.py b/HARK/abstract/tests/test_variables.py index fbc31d4d4..85f8b3372 100644 --- a/HARK/abstract/tests/test_variables.py +++ b/HARK/abstract/tests/test_variables.py @@ -8,12 +8,12 @@ class test_pyyaml(unittest.TestCase): def setUp(self): - pass + self.path = "HARK/abstract/tests/" def test_partial(self): - with open("consindshk.yml") as f: + with open(self.path + "consindshk.yml") as f: data = yaml.safe_load(f) def test_full(self): - with open("consindshk_full.yml") as f: + with open(self.path + "consindshk_full.yml") as f: data = yaml.safe_load(f) From 376a49a5577084eab61c5f2dc9b555ad6cebe333 Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Tue, 25 Jul 2023 11:19:39 -0400 Subject: [PATCH 08/10] update requirements --- requirements/base.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements/base.txt b/requirements/base.txt index 5821f865e..f6443b8bc 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -5,6 +5,7 @@ networkx>=3 numba>=0.56 numpy>=1.23 pandas>=1.5 +pyyaml quantecon scipy>=1.10 seaborn>=0.12 From 64e4c09c08237ddf2a3edb45bfe42ba0f8062cce Mon Sep 17 00:00:00 2001 From: Mridul Seth Date: Wed, 2 Aug 2023 21:53:12 +0400 Subject: [PATCH 09/10] turn off 3.8, 3.9 tests for now --- .github/workflows/hark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hark.yml b/.github/workflows/hark.yml index eca382a58..729e282d0 100644 --- a/.github/workflows/hark.yml +++ b/.github/workflows/hark.yml @@ -21,7 +21,7 @@ jobs: max-parallel: 5 matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: [3.8, 3.9, "3.10"] + python-version: ["3.10"] steps: - uses: actions/checkout@v3 From e4d2850eb4c5f136dc97d58d8f0338238211cb45 Mon Sep 17 00:00:00 2001 From: Alan Lujan Date: Mon, 7 Aug 2023 17:31:50 -0400 Subject: [PATCH 10/10] Update HARK/abstract/variables.py Co-authored-by: Mridul Seth --- HARK/abstract/variables.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HARK/abstract/variables.py b/HARK/abstract/variables.py index 2f243aa56..d2e9c9479 100644 --- a/HARK/abstract/variables.py +++ b/HARK/abstract/variables.py @@ -68,14 +68,14 @@ def from_yaml(cls, loader, node): return cls(**fields) -@dataclass +@dataclass(kw_only=True) class Parameter(Variable): """ A `Parameter` is a variable that has a fixed value. """ value: Union[int, float] = 0 - yaml_tag: str = field(default="!Parameter", kw_only=True) + yaml_tag: str = "!Parameter" yaml_loader = SafeLoader def __repr__(self):