-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFunctionalResponse.h
More file actions
487 lines (384 loc) · 17.4 KB
/
FunctionalResponse.h
File metadata and controls
487 lines (384 loc) · 17.4 KB
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
/*
* FunctionalResponse.h
*
* Created on: 7 May 2014
* Author: rusty
*/
#ifndef FUNCTIONALRESPONSE_H_
#define FUNCTIONALRESPONSE_H_
#include <fstream>
#include <math.h>
using namespace std;
class FunctionalResponse{
private:
string type; // Linear, Holling I,II,III. Other?
string topology; // currently used to distinguish between CE and AC in 3 species simulations
public:
FunctionalResponse(string _type):type(_type),topology("NA"){} // topology not required for 2 species simulations
FunctionalResponse(string _type, string _topology):type(_type),topology(_topology){}
// friend RM_Nsp_unit;
// return double based on types. needs access to units[i], parameters
// this class should also be responsible for evaluating simulation IM elements, since this is based on analytic derivation of the functional response
double getResponse(int unitID, int j, int unitCount, vector <vector <double> >& connectionMatrix, IDynamicalUnit** allUnits, int masterClock, RM_Nsp_Parameters* parameters){
double response = 0;
if (type=="Holling_II"){
return Holling_II_response(unitID, j, unitCount, connectionMatrix, allUnits, masterClock, parameters);
}
else if (type=="Holling_III"){
return Holling_III_response(unitID, j, unitCount, connectionMatrix, allUnits, masterClock, parameters);
}
else if (type=="Holling_II_no_passive_switching"){
return Holling_II_response_no_passive_switching(unitID, j, unitCount, connectionMatrix, allUnits, masterClock, parameters);
}
else {
cout << "WARNING REPSONSE TYPE UNKNOWN: SPEICES INTERACTION = 0" << endl;
}
return response;
}
bool evaluateSimulationIM(RM_Nsp_Parameters* parameters, IDynamicalUnit** units, int unitCount, int timestepCount, vector <double>& IM){
// only works for Holling II and III:
if(!evaluateSimulationIM_Holling(parameters, units, unitCount, timestepCount, IM)){return false;}
return true;
}
bool saveInteractionFunctions(int unitCount, int timestepCount, vector <vector <double> >& connectionMatrix, IDynamicalUnit** units, RM_Nsp_Parameters* parameters){
// this saves the interaction functions by evaluating the simulation IM elemtents of the course of the simulation
// i.e. it assumes that we are interested in the whole simulation rather than just the sampling period
stringstream ID_ss;
ID_ss << parameters->ID;
string fname = type+"_interaction_function_params"+ID_ss.str()+".fn";
ofstream ofile;
ofile.open(fname.c_str());
if(!save_Holling_interaction(ofile, parameters, units, unitCount, timestepCount, connectionMatrix)){ofile.close(); return false;}
ofile.close();
return true;
}
bool saveFunctionalResponse(int unitCount, int timestepCount, vector <vector <double> >& connectionMatrix, IDynamicalUnit** units, RM_Nsp_Parameters* parameters){
// this saves the interaction functions by evaluating the simulation IM elemtents of the course of the simulation
// i.e. it assumes that we are interested in the whole simulation rather than just the sampling period
stringstream ID_ss;
ID_ss << parameters->ID;
string fname = type+"_FUNCTIONALRESPONSE_params"+ID_ss.str()+".fn";
ofstream ofile;
ofile.open(fname.c_str());
if(!save_Holling_functional(ofile, parameters, units, unitCount, timestepCount, connectionMatrix)){ofile.close(); return false;}
ofile.close();
return true;
}
bool saveIM_timseries(RM_Nsp_Parameters* parameters, IDynamicalUnit** units, int unitCount, int timestepCount, double timestepSize){
// this to calculate the Interaction Matrix (with elements averaged over the inference sampling period)
// current implementation for RM 2species with Holling Type2 and linear predator mortality. Need to add more
// for other functional response forms.
ofstream ofile;
ofile.open("IM_timseries.ts");
// assign parameters for ease of use, this asusmes that prey is species0
double r0 = parameters->growthRates.at(0);
// double r1 = parameters->growthRates.at(1);
double K0 = parameters->carryingCapacities.at(0);
double Ks = parameters->saturationConstants.at(1);
double a01 = parameters->couplingMatrix.at(0).at(1);
double a10 = parameters->couplingMatrix.at(1).at(0);
double x0 = 0;
double x1 = 0;
for (int t=0; t<timestepCount; t++){
x0 = units[0]->getHistory()->getHistoryTi(t);
x1 = units[1]->getHistory()->getHistoryTi(t);
ofile << timestepSize*t << ", ";
if (type=="Holling_II"){
ofile << -(r0/K0)-x1*a01/pow(Ks + x0,2) << ", ";
ofile << a01/(Ks + x0)<< ", ";
ofile << a10/(Ks + x0) -x0*a10/pow(Ks + x0,2)<< ", ";
ofile << 0<< endl;
}
else if (type=="Holling_III"){
double alpha = 2; // default
ofile << 0 << ", "; // it doesn't really but we are not interested in self-interactions for now
ofile << (pow(x0,alpha-1)*a01)/(pow(Ks,alpha) + pow(x0,alpha)) << ", ";
ofile << alpha*a10*pow(x0,alpha-1)/(pow(Ks,alpha) + pow(x0,alpha)) -alpha*pow(x0,alpha+1)*a10/pow(pow(Ks,alpha) + pow(x0,alpha),2) << ", ";
ofile << 0 << endl;;
}
}
ofile.close();
return true;
}
bool saveBiomassFlows(RM_Nsp_Parameters* parameters, IDynamicalUnit** units, int unitCount, int timestepCount, double timestepSize){
// this to calculate the Interaction Matrix (with elements averaged over the inference sampling period)
// current implementation for RM 2species with Holling Type2 and linear predator mortality. Need to add more
// for other functional response forms.
ofstream ofile;
ofile.open("Biomass_timseries.ts");
// assign parameters for ease of use, this asusmes that prey is species0
double r0 = parameters->growthRates.at(0);
// double r1 = parameters->growthRates.at(1);
double K0 = parameters->carryingCapacities.at(0);
double Ks = parameters->saturationConstants.at(1);
double a01 = parameters->couplingMatrix.at(0).at(1);
double a10 = parameters->couplingMatrix.at(1).at(0);
double x0 = 0;
double x1 = 0;
for (int t=0; t<timestepCount; t++){
x0 = units[0]->getHistory()->getHistoryTi(t);
x1 = units[1]->getHistory()->getHistoryTi(t);
ofile << timestepSize*t << ", ";
if (type=="Holling_II"){
// ofile << -(r0/K0)-x1*a01/pow(Ks + x0,2) << ", ";
ofile << a01*x0*x1/(Ks + x0)<< ", ";
ofile << a10*x0*x1/(Ks + x0) <<endl;
}
else if (type=="Holling_III"){
double alpha = 2; // default
ofile << (pow(x0,alpha)*a01*x1)/(pow(Ks,alpha) + pow(x0,alpha)) << ", ";
ofile << alpha*a10*pow(x0,alpha)*x1/(pow(Ks,alpha) + pow(x0,alpha)) << endl;
}
}
ofile.close();
return true;
}
private:
double Holling_II_response(int unitID, int j, int unitCount, vector <vector <double> >& connectionMatrix, IDynamicalUnit** allUnits, int masterClock, RM_Nsp_Parameters* parameters){
// unitID is the unit calling the response function
// j is the species to calculate coupling with
double Ks = 0;
double aij = connectionMatrix.at(unitID).at(j);
double xi = allUnits[unitID]->getHistory()->getHistoryTi(masterClock);
double xj = allUnits[j]->getHistory()->getHistoryTi(masterClock);
double denominator = 0;
if (aij==0){
return 0;
}
else if(aij>0){
// species i is the predator..
Ks = parameters->saturationConstants.at(unitID);
denominator += Ks;
for (int i=0; i<unitCount; i++){
if(connectionMatrix.at(unitID).at(i)>0){
denominator += allUnits[i]->getHistory()->getHistoryTi(masterClock);
}
}
}
else {
// species i is being predated by species j
Ks = parameters->saturationConstants.at(j);
denominator += Ks;
for (int i=0; i<unitCount; i++){
if(connectionMatrix.at(j).at(i)>0){
denominator += allUnits[i]->getHistory()->getHistoryTi(masterClock);
}
}
}
return (aij*xi*xj)/(denominator);
// return (xi*xj)/(xi+Ks);
}
double Holling_II_response_no_passive_switching(int unitID, int j, int unitCount, vector <vector <double> >& connectionMatrix, IDynamicalUnit** allUnits, int masterClock, RM_Nsp_Parameters* parameters){
// unitID is the unit calling the response function
// j is the species to calculate coupling with
// this version does not include passive prey switching, such that the denominator is simple and there ar eonly pairwise interactions..
double Ks = 0;
double aij = connectionMatrix.at(unitID).at(j);
double xi = allUnits[unitID]->getHistory()->getHistoryTi(masterClock);
double xj = allUnits[j]->getHistory()->getHistoryTi(masterClock);
double denominator = 0;
if (aij==0){
return 0;
}
else if(aij>0){
// species i is the predator..
Ks = parameters->saturationConstants.at(unitID);
denominator += allUnits[unitID]->getHistory()->getHistoryTi(masterClock);
denominator += Ks;
}
else {
// species i is being predated by species j
Ks = parameters->saturationConstants.at(j);
denominator += Ks;
denominator += allUnits[j]->getHistory()->getHistoryTi(masterClock);
}
return (aij*xi*xj)/(denominator);
// return (xi*xj)/(xi+Ks);
}
double Holling_III_response(int unitID, int j, int unitCount, vector <vector <double> >& connectionMatrix, IDynamicalUnit** allUnits, int masterClock, RM_Nsp_Parameters* parameters){
double alpha = 2; // Holling type3 has an exponent which we set as default=2.
// unitID is the unit calling the response function
// j is the species to calculate coupling with
double Ks = 0;
double aij = connectionMatrix.at(unitID).at(j);
double xi = allUnits[unitID]->getHistory()->getHistoryTi(masterClock);
double xj = allUnits[j]->getHistory()->getHistoryTi(masterClock);
double denominator = 0;
if (aij==0){
return 0;
}
else if(aij>0){
// species i is the predator..
Ks = parameters->saturationConstants.at(unitID);
denominator += pow(Ks,alpha);
for (int i=0; i<unitCount; i++){
if(connectionMatrix.at(unitID).at(i)>0){
denominator += pow(allUnits[i]->getHistory()->getHistoryTi(masterClock), alpha);
}
}
}
else {
// species i is being predated by species j
Ks = parameters->saturationConstants.at(j);
denominator +=pow( Ks, alpha);
for (int i=0; i<unitCount; i++){
if(connectionMatrix.at(j).at(i)>0){
denominator += pow(allUnits[i]->getHistory()->getHistoryTi(masterClock),alpha);
}
}
}
if(aij>0){
return (aij*pow(xj,alpha)*xi)/(denominator);
}
else{
return (aij*pow(xi,alpha)*xj)/(denominator);
}
}
bool evaluateSimulationIM_Holling(RM_Nsp_Parameters* parameters, IDynamicalUnit** units, int unitCount, int timestepCount, vector <double>& IM){
// this to calculate the Interaction Matrix (with elements averaged over the inference sampling period)
// current implementation for RM 2species with Holling Type2 and linear predator mortality. Need to add more
// for other functional response forms.
// IM must be passed in with zero elements
// make sure the same parameters are passed in as are stored by the units!!
if (IM.size()!=(unsigned int)unitCount*unitCount){
cerr << "wrong number of elements in IM" << endl;
return false;
}
// assign parameters for ease of use, this asusmes that prey is species0
double r0 = parameters->growthRates.at(0);
// double r1 = parameters->growthRates.at(1);
double K0 = parameters->carryingCapacities.at(0);
double Ks = parameters->saturationConstants.at(1);
double a01 = parameters->couplingMatrix.at(0).at(1);
double a10 = parameters->couplingMatrix.at(1).at(0);
double x0 = 0;
double x1 = 0;
for (int t=0; t<timestepCount; t++){
x0 = units[0]->getHistory()->getHistoryTi(t);
x1 = units[1]->getHistory()->getHistoryTi(t);
if (type=="Holling_II"){
IM.at(0) += -(r0/K0)-x1*a01/pow(Ks + x0,2);
IM.at(1) += a01/(Ks + x0);
IM.at(2) += a10/(Ks + x0) -x0*a10/pow(Ks + x0,2);
IM.at(3) += 0;
}
else if (type=="Holling_III"){
double alpha = 2; // default
IM.at(0) += 0; // it doesn't really but we are not interested in self-interactions for now
IM.at(1) += (pow(x0,alpha-1)*a01)/(pow(Ks,alpha) + pow(x0,alpha));
IM.at(2) += alpha*a10*pow(x0,alpha-1)/(pow(Ks,alpha) + pow(x0,alpha)) -alpha*pow(x0,alpha+1)*a10/pow(pow(Ks,alpha) + pow(x0,alpha),2); //right yeah??
IM.at(3) += 0;
}
}
for (unsigned int i =0; i<IM.size(); i++){
IM.at(i) = IM.at(i)/timestepCount; // take the mean value over the sampling period
}
return true;
}
bool save_Holling_interaction(ofstream& ofile, RM_Nsp_Parameters* parameters, IDynamicalUnit** units, int unitCount, int timestepCount,vector <vector <double> >& connectionMatrix){
// save the interactions as a function of prey density
double prey_min = 0;
double prey_max = 0;
if (unitCount==2){
prey_max =parameters->carryingCapacities.at(0);
// generate and save functional response:
double Ks = parameters->saturationConstants.at(1);
double a01 = parameters->couplingMatrix.at(0).at(1);
double a10 = parameters->couplingMatrix.at(1).at(0);
if (type=="Holling_II"){
for (double x0=prey_min; x0<prey_max; x0+=0.1){
ofile << x0 << ", " << a01/(Ks + x0) << ", " << a10/(Ks + x0) -x0*a10/pow(Ks + x0,2) << endl;
}
}
else if (type=="Holling_III"){
double alpha = 2;
for (double x0=prey_min; x0<prey_max; x0+=0.1){
ofile << x0 << ", " << (pow(x0,alpha-1)*a01)/(pow(Ks,alpha) + pow(x0,alpha)) << ", " << alpha*a10*pow(x0,alpha-1)/(pow(Ks,alpha) + pow(x0,alpha)) -alpha*pow(x0,alpha+1)*a10/pow(pow(Ks,alpha) + pow(x0,alpha),2) << endl;
}
}
}
else if(unitCount==3){
// now we assume HOlling II with CE topology. NEED TO GENERALISE THIS...
if (topology=="CE"){
if(!checkIfBasalSpecies(0, connectionMatrix)){
cerr << "method save_Holling_interaction of class FunctionalResponse assumes that species O is the primary producer in a 3species CE topology" << endl;
return false;
}
prey_max =parameters->carryingCapacities.at(0);
double Ks1 = parameters->saturationConstants.at(1);
double Ks2 = parameters->saturationConstants.at(2); // there are two predators
double a01 = parameters->couplingMatrix.at(0).at(1);
double a02 = parameters->couplingMatrix.at(0).at(2);
double a10 = parameters->couplingMatrix.at(1).at(0);
double a20 = parameters->couplingMatrix.at(2).at(0);
// columns to output: preyX | A01 | A02 | A10 | A12=0 | A20 | A21=0
if (type=="Holling_II"){
for (double x0=prey_min; x0<prey_max; x0+=0.1){
ofile << x0 << ", " << a01/(Ks1 + x0) << ", " << a02/(Ks2 + x0) << ", " << a10/(Ks1 + x0) -x0*a10/pow(Ks1 + x0,2) << ", " << 0 << ", " << a20/(Ks2 + x0) -x0*a20/pow(Ks2 + x0,2) << ", " << 0 << endl;
}
}
}
else if (topology=="AC"){
// this needs working on because the function is actually a surface: (plot it for now at half carrying capacity of prey2)
if(!checkIfBasalSpecies(0, connectionMatrix) || !checkIfBasalSpecies(1, connectionMatrix)){
cerr << "method save_Holling_interaction of class FunctionalResponse assumes that species O and 1 are primary producers in a 3species AC topology" << endl;
return false;
}
prey_max =parameters->carryingCapacities.at(0);
double x1 = parameters->carryingCapacities.at(1)/2; // prey2_half_capacity
double x2 = parameters->saturationConstants.at(1)*4; // abitrary predator population level
double Ks = parameters->saturationConstants.at(1);
// double a01 = parameters->couplingMatrix.at(0).at(1);
double a02 = parameters->couplingMatrix.at(0).at(2);
// double a10 = parameters->couplingMatrix.at(1).at(0);
double a12 = parameters->couplingMatrix.at(1).at(2);
double a20 = parameters->couplingMatrix.at(2).at(0);
double a21 = parameters->couplingMatrix.at(2).at(1);
// columns to output: preyX | A01 | A02 | A10 | A12 | A20 | A21
if (type=="Holling_II"){
for (double x0=prey_min; x0<prey_max; x0+=0.1){
ofile << x0 << ", " << -a02*x2/(Ks + x0 + x1) << ", " << a02/(Ks + x0 + x1) << ", " << -a12*x2/pow(Ks + x0 + x1,2) << ", " << a12/(Ks + x0 + x1) << ", " << a20/(Ks + x0 + x1) -x0*a20/pow(Ks + x0 + x1,2) -x1*a21/pow(Ks + x0 + x1,2) << ", " << a21/(Ks + x0 + x1) -x0*a20/pow(Ks + x0 + x1,2) -x1*a21/pow(Ks + x0 + x1,2) << endl;
}
}
}
}
return true;
}
bool save_Holling_functional(ofstream& ofile, RM_Nsp_Parameters* parameters, IDynamicalUnit** units, int unitCount, int timestepCount,vector <vector <double> >& connectionMatrix){
// save the interactions as a function of prey density
double prey_min = 0;
double prey_max = 0;
if (unitCount!=2){
cerr << "only implemented functional saving for 2 species" << endl;
return false;
}
prey_max =parameters->carryingCapacities.at(0);
// generate and save functional response:
double Ks = parameters->saturationConstants.at(1);
double a01 = parameters->couplingMatrix.at(0).at(1);
double a10 = parameters->couplingMatrix.at(1).at(0);
if (type=="Holling_II"){
for (double x0=prey_min; x0<prey_max; x0+=0.1){
ofile << x0 << ", " << a01*x0/(Ks + x0) << ", " << a10*x0/(Ks + x0) << endl;
}
}
else if (type=="Holling_III"){
double alpha = 2;
for (double x0=prey_min; x0<prey_max; x0+=0.1){
ofile << x0 << ", " << (pow(x0,alpha)*a01)/(pow(Ks,alpha) + pow(x0,alpha)) << ", " << alpha*a10*pow(x0,alpha)/(pow(Ks,alpha) + pow(x0,alpha)) << endl;
}
}
return true;
}
private:
bool checkIfBasalSpecies(int unitID, vector <vector<double> >& connectionMatrix){
for (unsigned int i=0; i<connectionMatrix.size(); i++){
if (connectionMatrix.at(unitID).at(i)>0){
return false;
}
}
// otherwise it must be a basal species..(primary producer)
return true;
}
};
#endif /* FUNCTIONALRESPONSE_H_ */