Skip to content

Commit 9e4a41a

Browse files
committed
Adjusted prior FIM handling
Moved prior FIM addition to the objective functions (and cholesky factorization for D-opt). Also added a fixed variable on the model to access the prior FIM with the same indexing as the FIM and the jacobian...
1 parent 2d05305 commit 9e4a41a

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

pyomo/contrib/doe/doe.py

+18-8
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,15 @@ def initialize_fim(m, j, d):
816816
model.fim = pyo.Var(
817817
model.parameter_names, model.parameter_names, initialize=identity_matrix
818818
)
819+
820+
# Create the prior FIM variable and fix it.
821+
def initialize_prior_fim(m, c, d):
822+
return self.prior_FIM[list(m.parameter_names).index(c), list(m.parameter_names).index(d)]
823+
824+
model.prior_FIM = pyo.Var(
825+
model.parameter_names, model.parameter_names, initialize=initialize_prior_fim
826+
)
827+
model.prior_FIM.fix()
819828

820829
# To-Do: Look into this functionality.....
821830
# if cholesky, define L elements as variables
@@ -925,7 +934,6 @@ def fim_rule(m, p, q):
925934
* m.sensitivity_jacobian[n, q]
926935
for n in m.output_names
927936
)
928-
+ m.prior_FIM[p, q]
929937
)
930938

931939
model.jacobian_constraint = pyo.Constraint(
@@ -1153,9 +1161,9 @@ def create_objective_function(self, model=None):
11531161

11541162
# Assemble the FIM matrix. This is helpful for initialization!
11551163
fim_vals = [
1156-
model.fim[bu, un].value
1157-
for i, bu in enumerate(model.parameter_names)
1158-
for j, un in enumerate(model.parameter_names)
1164+
pyo.value(model.fim[i, j].value) + pyo.value(model.prior_FIM[i, j])
1165+
for i in model.parameter_names
1166+
for j in model.parameter_names
11591167
]
11601168
fim = np.array(fim_vals).reshape(
11611169
len(model.parameter_names), len(model.parameter_names)
@@ -1164,6 +1172,7 @@ def create_objective_function(self, model=None):
11641172
### Initialize the Cholesky decomposition matrix
11651173
if self.Cholesky_option and self.objective_option == ObjectiveLib.determinant:
11661174
# Calculate the eigenvalues of the FIM matrix
1175+
print(fim)
11671176
eig = np.linalg.eigvals(fim)
11681177

11691178
# If the smallest eigenvalue is (practically) negative, add a diagonal matrix to make it positive definite
@@ -1190,7 +1199,7 @@ def cholesky_imp(b, c, d):
11901199
# This region is where our equations are well-defined.
11911200
m = b.model()
11921201
if list(m.parameter_names).index(c) >= list(m.parameter_names).index(d):
1193-
return m.fim[c, d] == sum(
1202+
return m.fim[c, d] + m.prior_FIM[c, d] == sum(
11941203
m.L[c, m.parameter_names.at(k + 1)]
11951204
* m.L[d, m.parameter_names.at(k + 1)]
11961205
for k in range(list(m.parameter_names).index(d) + 1)
@@ -1204,7 +1213,7 @@ def trace_calc(b):
12041213
Calculate FIM elements. Can scale each element with 1000 for performance
12051214
"""
12061215
m = b.model()
1207-
return m.trace == sum(m.fim[j, j] for j in m.parameter_names)
1216+
return m.trace == sum(m.fim[j, j] + m.prior_FIM[j, j] for j in m.parameter_names)
12081217

12091218
def determinant_general(b):
12101219
r"""Calculate determinant. Can be applied to FIM of any size.
@@ -1231,7 +1240,8 @@ def determinant_general(b):
12311240
det_perm = sum(
12321241
self._sgn(list_p[d])
12331242
* math.prod(
1234-
m.fim[m.parameter_names.at(val + 1), m.parameter_names.at(ind + 1)]
1243+
m.fim[m.parameter_names.at(val + 1), m.parameter_names.at(ind + 1)] +
1244+
m.prior_FIM[m.parameter_names.at(val + 1), m.parameter_names.at(ind + 1)]
12351245
for ind, val in enumerate(list_p[d])
12361246
)
12371247
for d in range(len(list_p))
@@ -2037,7 +2047,7 @@ def get_FIM(self, model=None):
20372047
)
20382048

20392049
fim_vals = [
2040-
pyo.value(model.fim[i, j])
2050+
pyo.value(model.fim[i, j]) + pyo.value(model.prior_FIM[i, j])
20412051
for i in model.parameter_names
20422052
for j in model.parameter_names
20432053
]

0 commit comments

Comments
 (0)