3
3
import theano .tensor as tt
4
4
5
5
6
- def augment_system (ode_func , n , m ):
6
+ def make_sens_ic (n_states , n_theta , floatX ):
7
+ """
8
+ The sensitivity matrix will always have consistent form. (n_states, n_states + n_theta)
9
+
10
+ If the first n_states entries of the parameters vector in the simulate call
11
+ correspond to initial conditions of the system,
12
+ then the first n_states columns of the sensitivity matrix should form
13
+ an identity matrix.
14
+
15
+ If the last n_theta entries of the parameters vector in the simulate call
16
+ correspond to ode paramaters, then the last n_theta columns in
17
+ the sensitivity matrix will be 0.
18
+
19
+ Parameters
20
+ ----------
21
+ n_states : int
22
+ Number of state variables in the ODE
23
+ n_theta : int
24
+ Number of ODE parameters
25
+ floatX : str
26
+ dtype to be used for the array
27
+
28
+ Returns
29
+ -------
30
+ dydp : array
31
+ 1D-array of shape (n_states * (n_states + n_theta),), representing the initial condition of the sensitivities
32
+ """
33
+
34
+ # Initialize the sensitivity matrix to be 0 everywhere
35
+ sens_matrix = np .zeros ((n_states , n_states + n_theta ), dtype = floatX )
36
+
37
+ # Slip in the identity matrix in the appropirate place
38
+ sens_matrix [:,:n_states ] = np .eye (n_states , dtype = floatX )
39
+
40
+ # We need the sensitivity matrix to be a vector (see augmented_function)
41
+ # Ravel and return
42
+ dydp = sens_matrix .ravel ()
43
+ return dydp
44
+
45
+
46
+ def augment_system (ode_func , n_states , n_theta ):
7
47
"""
8
48
Function to create augmented system.
9
49
@@ -17,10 +57,10 @@ def augment_system(ode_func, n, m):
17
57
----------
18
58
ode_func : function
19
59
Differential equation. Returns array-like.
20
- n : int
60
+ n_states : int
21
61
Number of rows of the sensitivity matrix. (n_states)
22
- m : int
23
- Number of columns of the sensitivity matrix. (n_states + n_theta)
62
+ n_theta : int
63
+ Number of ODE parameters
24
64
25
65
Returns
26
66
-------
@@ -30,11 +70,11 @@ def augment_system(ode_func, n, m):
30
70
31
71
# Present state of the system
32
72
t_y = tt .vector ("y" , dtype = 'float64' )
33
- t_y .tag .test_value = np .zeros (( n ,), dtype = 'float64' )
73
+ t_y .tag .test_value = np .ones (( n_states ,), dtype = 'float64' )
34
74
# Parameter(s). Should be vector to allow for generaliztion to multiparameter
35
75
# systems of ODEs. Is m dimensional because it includes all initial conditions as well as ode parameters
36
76
t_p = tt .vector ("p" , dtype = 'float64' )
37
- t_p .tag .test_value = np .zeros (( m ,), dtype = 'float64' )
77
+ t_p .tag .test_value = np .ones (( n_states + n_theta ,), dtype = 'float64' )
38
78
# Time. Allow for non-automonous systems of ODEs to be analyzed
39
79
t_t = tt .scalar ("t" , dtype = 'float64' )
40
80
t_t .tag .test_value = 2.459
@@ -43,12 +83,12 @@ def augment_system(ode_func, n, m):
43
83
# Will always be 0 unless the parameter is the inital condition
44
84
# Entry i,j is partial of y[i] wrt to p[j]
45
85
dydp_vec = tt .vector ("dydp" , dtype = 'float64' )
46
- dydp_vec .tag .test_value = np . zeros ( n * m , dtype = 'float64' )
86
+ dydp_vec .tag .test_value = make_sens_ic ( n_states , n_theta , 'float64' )
47
87
48
- dydp = dydp_vec .reshape ((n , m ))
88
+ dydp = dydp_vec .reshape ((n_states , n_states + n_theta ))
49
89
50
90
# Get symbolic representation of the ODEs by passing tensors for y, t and theta
51
- yhat = ode_func (t_y , t_t , t_p [n :])
91
+ yhat = ode_func (t_y , t_t , t_p [n_states :])
52
92
# Stack the results of the ode_func into a single tensor variable
53
93
if not isinstance (yhat , (list , tuple )):
54
94
yhat = (yhat ,)
0 commit comments