@@ -816,6 +816,15 @@ def initialize_fim(m, j, d):
816
816
model .fim = pyo .Var (
817
817
model .parameter_names , model .parameter_names , initialize = identity_matrix
818
818
)
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 ()
819
828
820
829
# To-Do: Look into this functionality.....
821
830
# if cholesky, define L elements as variables
@@ -925,7 +934,6 @@ def fim_rule(m, p, q):
925
934
* m .sensitivity_jacobian [n , q ]
926
935
for n in m .output_names
927
936
)
928
- + m .prior_FIM [p , q ]
929
937
)
930
938
931
939
model .jacobian_constraint = pyo .Constraint (
@@ -1153,9 +1161,9 @@ def create_objective_function(self, model=None):
1153
1161
1154
1162
# Assemble the FIM matrix. This is helpful for initialization!
1155
1163
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
1159
1167
]
1160
1168
fim = np .array (fim_vals ).reshape (
1161
1169
len (model .parameter_names ), len (model .parameter_names )
@@ -1164,6 +1172,7 @@ def create_objective_function(self, model=None):
1164
1172
### Initialize the Cholesky decomposition matrix
1165
1173
if self .Cholesky_option and self .objective_option == ObjectiveLib .determinant :
1166
1174
# Calculate the eigenvalues of the FIM matrix
1175
+ print (fim )
1167
1176
eig = np .linalg .eigvals (fim )
1168
1177
1169
1178
# 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):
1190
1199
# This region is where our equations are well-defined.
1191
1200
m = b .model ()
1192
1201
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 (
1194
1203
m .L [c , m .parameter_names .at (k + 1 )]
1195
1204
* m .L [d , m .parameter_names .at (k + 1 )]
1196
1205
for k in range (list (m .parameter_names ).index (d ) + 1 )
@@ -1204,7 +1213,7 @@ def trace_calc(b):
1204
1213
Calculate FIM elements. Can scale each element with 1000 for performance
1205
1214
"""
1206
1215
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 )
1208
1217
1209
1218
def determinant_general (b ):
1210
1219
r"""Calculate determinant. Can be applied to FIM of any size.
@@ -1231,7 +1240,8 @@ def determinant_general(b):
1231
1240
det_perm = sum (
1232
1241
self ._sgn (list_p [d ])
1233
1242
* 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 )]
1235
1245
for ind , val in enumerate (list_p [d ])
1236
1246
)
1237
1247
for d in range (len (list_p ))
@@ -2037,7 +2047,7 @@ def get_FIM(self, model=None):
2037
2047
)
2038
2048
2039
2049
fim_vals = [
2040
- pyo .value (model .fim [i , j ])
2050
+ pyo .value (model .fim [i , j ]) + pyo . value ( model . prior_FIM [ i , j ])
2041
2051
for i in model .parameter_names
2042
2052
for j in model .parameter_names
2043
2053
]
0 commit comments