forked from oliviergimenez/hmm_tmb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmultievent_tmb.cpp
executable file
·209 lines (191 loc) · 5.02 KB
/
multievent_tmb.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// linear regression
#include <TMB.hpp>
//template<class Type>
//matrix<Type> multmat(array<Type> A, matrix<Type> B) {
// int nrowa = A.rows();
// int ncola = A.cols();
// int ncolb = B.cols();
// matrix<Type> C(nrowa,ncolb);
// for (int i = 0; i < nrowa; i++)
// {
// for (int j = 0; j < ncolb; j++)
// {
// C(i,j) = Type(0);
// for (int k = 0; k < ncola; k++)
// C(i,j) += A(i,k)*B(k,j);
// }
// }
// return C;
//}
//
/* implement the vector - matrix product */
template<class Type>
vector<Type> multvecmat(array<Type> A, matrix<Type> B) {
int nrowb = B.rows();
int ncolb = B.cols();
vector<Type> C(ncolb);
for (int i = 0; i < ncolb; i++)
{
C(i) = Type(0);
for (int k = 0; k < nrowb; k++){
C(i) += A(k)*B(k,i);
}
}
return C;
}
template<class Type>
Type objective_function<Type>::operator() () {
// b = parameters
PARAMETER_VECTOR(b);
// ch = capture-recapture histories (individual format)
// fc = date of first capture
// fs = state at first capture
DATA_IMATRIX(ch);
DATA_IVECTOR(fc);
DATA_IVECTOR(fs);
// OBSERVATIONS
// 0 = non-detected
// 1 = seen and ascertained as non-breeder
// 2 = seen and ascertained as breeder
// 3 = not ascertained
//
// STATES
// 1 = alive non-breeder
// 2 = alive breeder
// 3 = dead
//
// PARAMETERS
// phiNB survival prob. of non-breeders
// phiB survival prob. of breeders
// pNB detection prob. of non-breeders
// pB detection prob. of breeders
// psiNBB transition prob. from non-breeder to breeder
// psiBNB transition prob. from breeder to non-breeder
// piNB prob. of being in initial state non-breeder
// deltaNB prob to ascertain the breeding status of an individual encountered as non-breeder
// deltaB prob to ascertain the breeding status of an individual encountered as breeder
//
// logit link for all parameters
// note: below, we decompose the state and obs process in two steps composed of binomial events,
// which makes the use of the logit link appealing;
// if not, a multinomial (aka generalised) logit link should be used
int km = ch.rows();
int nh = ch.cols();
int npar = b.size();
vector<Type> par(npar);
for (int i = 0; i < npar; i++) {
par(i) = Type(1.0) / (Type(1.0) + exp(-b(i)));
}
Type piNB = par(0); // careful, indexing starts at 0 in Rcpp!
Type phiNB = par(1);
Type phiB = par(2);
Type psiNBB = par(3);
Type psiBNB = par(4);
Type pNB = par(5);
Type pB = par(6);
Type deltaNB = par(7);
Type deltaB = par(8);
// prob of obs (rows) cond on states (col)
matrix<Type> B1(3,3);
B1(0,0) = Type(1.0)-pNB;
B1(0,1) = pNB;
B1(0,2) = Type(0.0);
B1(1,0) = Type(1.0)-pB;
B1(1,1) = Type(0.0);
B1(1,2) = pB;
B1(2,0) = Type(1.0);
B1(2,1) = Type(0.0);
B1(2,2) = Type(0.0);
matrix<Type> B2(3, 4);
B2(0,0) = Type(1.0);
B2(0,1) = Type(0.0);
B2(0,2) = Type(0.0);
B2(0,3) = Type(0.0);
B2(1,0) = Type(0.0);
B2(1,1) = deltaNB;
B2(1,2) = Type(0.0);
B2(1,3) = 1-deltaNB;
B2(2,0) = Type(0.0);
B2(2,1) = Type(0.0);
B2(2,2) = deltaB;
B2(2,3) = Type(1.0)-deltaB;
matrix<Type> BB(4, 3);
BB = B1 * B2;
matrix<Type> B(3, 4);
B = BB.transpose();
REPORT(B);
// first encounter
matrix<Type> BE1(3, 3);
BE1(0,0) = Type(0.0);
BE1(0,1) = Type(1.0);
BE1(0,2) = Type(0.0);
BE1(1,0) = Type(0.0);
BE1(1,1) = Type(0.0);
BE1(1,2) = Type(1.0);
BE1(2,0) = Type(1.0);
BE1(2,1) = Type(0.0);
BE1(2,2) = Type(0.0);
matrix<Type> BE2(3, 4);
BE2(0,0) = Type(1.0);
BE2(0,1) = Type(0.0);
BE2(0,2) = Type(0.0);
BE2(0,3) = Type(0.0);
BE2(1,0) = Type(0.0);
BE2(1,1) = deltaNB;
BE2(1,2) = Type(0.0);
BE2(1,3) = Type(1.0)-deltaNB;
BE2(2,0) = Type(0.0);
BE2(2,1) = Type(0.0);
BE2(2,2) = deltaB;
BE2(2,3) = Type(1.0)-deltaB;
matrix<Type> BEE(3,4);
BEE = BE1 * BE2;
matrix<Type> BE(4,3);
BE = BEE.transpose();
REPORT(BE);
// prob of states at t+1 given states at t
matrix<Type> A1(3, 3);
A1(0,0) = phiNB;
A1(0,1) = Type(0.0);
A1(0,2) = Type(1.0)-phiNB;
A1(1,0) = Type(0.0);
A1(1,1) = phiB;
A1(1,2) = Type(1.0)-phiB;
A1(2,0) = Type(0.0);
A1(2,1) = Type(0.0);
A1(2,2) = Type(1.0);
matrix<Type> A2(3, 3);
A2(0,0) = Type(1.0)-psiNBB;
A2(0,1) = psiNBB;
A2(0,2) = Type(0.0);
A2(1,0) = psiBNB;
A2(1,1) = Type(1.0)-psiBNB;
A2(1,2) = Type(0.0);
A2(2,0) = Type(0.0);
A2(2,1) = Type(0.0);
A2(2,2) = Type(1.0);
matrix<Type> A(3, 3);
A = A1 * A2;
REPORT(A);
// init states
vector<Type> PROP(3);
PROP(0) = piNB;
PROP(1) = Type(1.0)-piNB;
PROP(2) = Type(0.0);
REPORT(PROP);
// likelihood
Type ll;
Type nll;
array<Type> ALPHA(3);
for (int i = 0; i < nh; i++) {
int ei = fc(i)-1;
vector<int> evennt = ch.col(i);
ALPHA = PROP * vector<Type>(BE.row(fs(i))); // element-wise vector product
for (int j = ei+1; j < km; j++) {
ALPHA = multvecmat(ALPHA,A) * vector<Type>(B.row(evennt(j))); // vector matrix product, then element-wise vector product
}
ll += log(sum(ALPHA));
}
nll = -ll;
return nll;
}