Skip to content

Commit 7b376ef

Browse files
authored
Merge pull request #9 from ousema-bouaneni/main
Refactoring Model class
2 parents 7876726 + fdd043f commit 7b376ef

File tree

14 files changed

+708
-239
lines changed

14 files changed

+708
-239
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ poetry.lock
99
**/__pycache__/*
1010
temp*.yml
1111
.mypy*
12-
*ipynb*
12+
*ipynb*
13+
.github/workflows/.ci_pixi.yaml

dyno/gui/dynare.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def sim_to_nsim(irfs):
2121

2222
txt = open(filename).read()
2323

24-
from dyno.modfile import Modfile
24+
from dyno.modfile_preprocessor import Modfile
2525

2626
model = Modfile(txt=txt)
2727
dr0 = model.solve()
@@ -113,7 +113,7 @@ def import_model(txt):
113113
else:
114114
method = "ti"
115115

116-
parms = {k: v for k, v in parameters.items()}
116+
parms = {k: float(v.value) for k, v in parameters.items()}
117117

118118
dr.value = model.solve(method=method, calibration=parms)
119119

dyno/language.py

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import numpy as np
1010

11+
from scipy.stats import multivariate_normal
12+
1113

1214
class NotPositiveSemidefinite(np.linalg.LinAlgError):
1315
"""An exception raised when a normal process is created with a covariance matrix that is not positive semidefinite"""
@@ -29,16 +31,48 @@ def Vector(*elements):
2931
return mat
3032

3133

34+
class Exogenous:
35+
pass
36+
37+
38+
class Deterministic(Exogenous):
39+
"""Deterministic exogenous variables clas
40+
41+
Parameters
42+
----------
43+
horizon: int
44+
time horizon over which the perfect foresight solver will simulate the model
45+
46+
values_dict: dict[str, list[float]]
47+
dictionary containing the values that each exogenous variable takes on at each time period before the horizon,
48+
empty fields are assumed to be zero
49+
"""
50+
51+
horizon: int
52+
"""time horizon over which the model will be simulated"""
53+
54+
values: dict[str, list[float]]
55+
"""values taken on by each exogenous variable"""
56+
57+
def __init__(self, horizon: int, values_dict: dict[str, list[float]]):
58+
horizon = max(horizon, max([len(periods) for periods in values_dict.values()]))
59+
for var, values in values_dict.items():
60+
if len(values) < horizon:
61+
values_dict[var] = pad_list(values, horizon)
62+
self.horizon = horizon
63+
self.values = values_dict
64+
65+
3266
@language_element
33-
class Normal:
67+
class Normal(Exogenous):
3468
"""Multivariate normal process class, can be used to model white noise.
3569
3670
Parameters
3771
----------
3872
Μ: d Vector | None
3973
Mean vector for the normal process, taken to be equal to zero if not passed
4074
41-
Σ : (d,d) Matrix
75+
Σ: (d,d) Matrix
4276
Covariance matrix for the normal process, needs to be positive semidefinite
4377
4478
Attributes
@@ -61,39 +95,30 @@ class Normal:
6195

6296
@greek_tolerance
6397
def __init__(self, Σ, Μ=None):
64-
6598
Sigma = np.array(Σ)
6699
mu = Μ
67-
68100
self.Σ = np.atleast_2d(np.array(Sigma, dtype=float))
69101
try:
70102
assert np.array_equal(Sigma, Sigma.T)
71-
np.linalg.cholesky(Sigma)
72-
except (AssertionError, np.linalg.LinAlgError):
73-
raise (
74-
NotPositiveSemidefinite,
103+
assert np.all(np.linalg.eigvalsh(Sigma) > -1e-12)
104+
except AssertionError:
105+
raise NotPositiveSemidefinite(
75106
"Σ can't be used as a covariance matrix as it is not positive semidefinite",
76107
)
77-
78108
self.d = len(self.Σ)
79109
if mu is None:
80110
self.Μ = np.array([0.0] * self.d)
81111
else:
82112
self.Μ = np.array(mu, dtype=float)
83113

84114
assert self.Σ.shape[0] == self.d
85-
assert self.Σ.shape[0] == self.d
86-
115+
assert self.Σ.shape[1] == self.d
87116
# this class wraps functionality from scipy
88-
import scipy.stats
89-
90-
self._dist_ = scipy.stats.multivariate_normal(
91-
mean=self.Μ, cov=self.Σ, allow_singular=True
92-
)
117+
self._dist_ = multivariate_normal(mean=self.Μ, cov=self.Σ, allow_singular=True)
93118

94119

95120
@language_element
96-
class ProductNormal:
121+
class ProductNormal(Exogenous):
97122
"""Product of multivariate normal processes
98123
99124
Parameters
@@ -124,3 +149,7 @@ def Σ(self):
124149
"""
125150
assert len(self.processes) == 1
126151
return self.processes[0].Σ
152+
153+
154+
def pad_list(l: list, n: int) -> list:
155+
return l + [0] * (n - len(l))

0 commit comments

Comments
 (0)