Indian Ocean Skipjack
parameters.hpp
1 #pragma once
2 
3 #include "model.hpp"
4 #include "variable.hpp"
5 
6 namespace IOSKJ {
7 
12 class Parameters : public Structure<Parameters> {
13 public:
14 
19 
29  Variable<Uniform> spawners_ea;
30 
36  struct SteepnessBeta : Beta {
37  double minimum(void) const {
38  return 0.6;
39  }
40  double maximum(void) const {
41  return 1;
42  }
43  double random(void) const {
44  double trial = 0;
45  while(trial<0.6){
46  trial = (Beta::random()+0.25)/1.25;
47  }
48  return trial;
49  }
50  double loglike(const double& steepness) const {
51  if(steepness<0.6) return -INFINITY;
52  else return std::log(Beta::pdf(steepness*1.25-0.25));
53  }
54  };
55  Variable<SteepnessBeta> recruits_steepness;
56 
61 
69 
73  Array<Variable<Normal>,RecdevYear> recruits_deviations;
74 
79  Variable<Uniform> spawning_1;
80  Variable<Uniform> spawning_2;
81  Variable<Uniform> spawning_3;
82 
83 
88  Variable<Fixed> weight_b;
89 
94  Variable<TruncatedNormal> maturity_steepness;
95 
100 
105  Variable<Fixed> growth_rate_2;
106  Variable<Fixed> growth_assymptote;
107  Variable<Fixed> growth_stanza_inflection;
108  Variable<Fixed> growth_stanza_steepness;
109  Variable<Fixed> growth_age_0;
110  Variable<Fixed> growth_cv_0;
111  Variable<Fixed> growth_cv_old;
112 
117  Variable<Uniform> movement_we_ea;
118  Variable<Uniform> movement_ma_ea;
119  Variable<Uniform> movement_length_inflection;
120  Variable<Uniform> movement_length_steepness;
121 
125  Array<Variable<Uniform>,Method,SelectivityKnot> selectivities;
126 
130  Array<Variable<Fixed>,Year,Quarter,Region,Method> catches;
131 
135  template<class Mirror>
136  void reflect(Mirror& mirror){
137  mirror
138  .data(spawners_unfished,"spawners_unfished")
139  .data(spawners_ma,"spawners_ma")
140  .data(spawners_ea,"spawners_ea")
141 
142  .data(recruits_steepness,"recruits_steepness")
143  .data(recruits_sd,"recruits_sd")
144  .data(recruits_autocorr,"recruits_autocorr")
145  .data(recruits_deviations,"recruits_deviations")
146 
147  .data(spawning_0,"spawning_0")
148  .data(spawning_1,"spawning_1")
149  .data(spawning_2,"spawning_2")
150  .data(spawning_3,"spawning_3")
151 
152  .data(weight_a,"weight_a")
153  .data(weight_b,"weight_b")
154 
155  .data(maturity_inflection,"maturity_inflection")
156  .data(maturity_steepness,"maturity_steepness")
157 
158  .data(mortality_mean,"mortality_mean")
159 
160  .data(growth_rate_1,"growth_rate_1")
161  .data(growth_rate_2,"growth_rate_2")
162  .data(growth_assymptote,"growth_assymptote")
163  .data(growth_stanza_inflection,"growth_stanza_inflection")
164  .data(growth_stanza_steepness,"growth_stanza_steepness")
165  .data(growth_age_0,"growth_age_0")
166  .data(growth_cv_0,"growth_cv_0")
167  .data(growth_cv_old,"growth_cv_old")
168 
169  .data(movement_we_ma,"movement_we_ma")
170  .data(movement_we_ea,"movement_we_ea")
171  .data(movement_ma_ea,"movement_ma_ea")
172 
173  .data(movement_length_inflection,"movement_length_inflection")
174  .data(movement_length_steepness,"movement_length_steepness")
175 
176  .data(selectivities,"selectivities")
177 
178  .data(catches,"catches")
179  ;
180  }
181 
182  using Structure<Parameters>::read;
183 
184  void read(void){
185  Structure<Parameters>::read("parameters/input/parameters.json");
186 
187  recruits_deviations.read("parameters/input/recruits_deviations.tsv",true);
188  selectivities.read("parameters/input/selectivities.tsv",true);
189 
190  catches.read("parameters/input/catches.tsv",true);
191  catches.each([](Variable<Fixed>& catche){
192  if(catche.is_na()) catche = 0;
193  });
194  }
195 
196  using Structure<Parameters>::write;
197 
198  void write(void){
199  Structure<Parameters>::write("parameters/output/parameters.json");
200 
201  recruits_deviations.write("parameters/output/recruits_deviations.tsv",true);
202  selectivities.write("parameters/output/selectivities.tsv",true);
203  catches.write("parameters/output/catches.tsv",true);
204 
205  values().write("parameters/output/values.tsv");
206  }
207 
213  void set(uint time, Model& model, bool catches_apply = true) const {
214  uint year = IOSKJ::year(time);
215  uint quarter = IOSKJ::quarter(time);
216 
217  // Bind time-invariant parameters to model attributes
218  if(time==0){
219  // Stock - recruitment
220  // Apportion `spawners_unfished` to regions
221  Array<double,Region> props = {
222  double(1.0),
223  double(spawners_ma),
224  double(spawners_ea)
225  };
226  props /= sum(props);
227  for(auto region : regions) model.biomass_spawners_unfished(region) = spawners_unfished * props(region);
228 
229  model.recruits_steepness = recruits_steepness;
230  model.recruits_sd = recruits_sd;
231 
232  // Proportion of mature fish spawning in each quarter
233  model.spawning(0) = spawning_0;
234  model.spawning(1) = spawning_1;
235  model.spawning(2) = spawning_2;
236  model.spawning(3) = spawning_3;
237 
238  // Length-weight relationship
239  model.weight_length_a = weight_a;
240  model.weight_length_b = weight_b;
241 
242  // Maturity curve
244  model.maturity_length_steepness = maturity_steepness;
245 
246  // Mortality-at-age curve
248 
249  // Growth curve
251  model.growth_rate_2 = growth_rate_2;
252  model.growth_assymptote = growth_assymptote;
253  model.growth_stanza_inflection = growth_stanza_inflection;
254  model.growth_stanza_steepness = growth_stanza_steepness;
255  model.growth_cv_0 = growth_cv_0;
256  model.growth_cv_old = growth_cv_old;
257 
258  // Movement
259  // Note that in the model.intialise function these
260  // proportional are restricted so that they do not sum to greater
261  // than one.
262  model.movement_region(WE,WE) = 1-movement_we_ma-movement_we_ea;
263  model.movement_region(WE,MA) = movement_we_ma;
264  model.movement_region(WE,EA) = movement_we_ea;
265 
266  model.movement_region(MA,WE) = movement_we_ma;
267  model.movement_region(MA,MA) = 1-movement_we_ma-movement_ma_ea;
268  model.movement_region(MA,EA) = movement_ma_ea;
269 
270  model.movement_region(EA,WE) = movement_we_ea;
271  model.movement_region(EA,MA) = movement_ma_ea;
272  model.movement_region(EA,EA) = 1-movement_ma_ea-movement_we_ea;
273 
274  model.movement_length_inflection = movement_length_inflection;
275  model.movement_length_steepness = movement_length_steepness;
276 
277  // Selectivity
278  for(auto method : methods){
279  for(auto knot : selectivity_knots){
280  model.selectivity_values(method,knot) = selectivities(method,knot);
281  }
282  }
283  }
284 
285  // Alternative parameterization of recruitment variation depending on year..
286  if(year<1985){
287  // Deterministic recruitment
288  model.recruits_variation_on = false;
289  model.recruits_multiplier = 1;
290  }
291  else if(year>=recdev_years.begin() and year<recdev_years.end()){
292  // Stochastic recruitment defined by recruitment deviation parameters
293  model.recruits_variation_on = false;
294  model.recruits_multiplier = std::exp(recruits_deviations(year));
295  }
296  #if 0
297  // Currently this is turned off as it only applies
298  // to certain types of conditioning
299  else if(year>=recdev_years.end() and time<=time_now){
300  // Deterministic recruitment otherwise get
301  // different fits from same parameter sets
302  // during conditioning
303  model.recruits_variation_on = false;
304  model.recruits_multiplier = 1;
305  }
306  #endif
307  else {
308  // Stochastic recruitment defined by recruits_sd and recruits_auto
309  model.recruits_variation_on = true;
310  }
311 
312  // Bind quarterly catch history to the model's catches
313  if(catches_apply and year>=1950 and year<=2014){
314  model.exploit = model.exploit_catch;
315  for(auto region : regions){
316  for(auto method : methods){
317  model.catches(region,method) = catches(
318  year,
319  quarter,
320  region,
321  method
322  );
323  }
324  }
325  }
326 
327  // Set effort for all regions and methods
328  // at a nominal 100 units
329  if(year<2005) model.effort = 0;
330  if(year>=2005 and year<=2014) model.effort = 100;
331 
332  // Initialise in the first year
333  if(time==0) model.initialise();
334  }
335 
339  template<class Derived>
340  struct Variabler : Mirrors::Mirror<Derived> {
341  using Polymorph<Derived>::derived;
342 
343  template<class Distribution, class... Dimensions>
344  Derived& data(Array<Variable<Distribution>,Dimensions...>& array, const std::string& name){
345  // Recurse into arrays of variables
346  array.reflect(derived());
347  return derived();
348  }
349 
350  template<class... Dimensions>
351  Derived& data(Array<Variable<Fixed>,Dimensions...>& array, const std::string& name){
352  // Ignore arrays of fixed variables
353  return derived();
354  }
355 
356  Derived& data(Variable<Fixed>& variable, const std::string& name){
357  // Ignore fixed variables
358  return derived();
359  }
360  };
361 
366  Randomiser().mirror(*this);
367  return *this;
368  }
369  struct Randomiser : Variabler<Randomiser> {
371 
372  template<class Distribution>
373  Randomiser& data(Variable<Distribution>& variable, const std::string& name){
374  variable.value = variable.random();
375  return *this;
376  }
377  };
378 
384  Restrictor().mirror(*this);
385  return *this;
386  }
387  struct Restrictor : Variabler<Restrictor> {
389 
390  template<class Distribution>
391  Restrictor& data(Variable<Distribution>& variable, const std::string& name){
392  if(variable.value>variable.maximum()){
393  variable.value = std::max(variable.maximum()-(variable.value-variable.maximum()),variable.minimum());
394  }
395  else if(variable.value<variable.minimum()){
396  variable.value = std::min(variable.minimum()+(variable.minimum()-variable.value),variable.maximum());
397  }
398  return *this;
399  }
400  };
401 
405  double loglike(void){
406  return Logliker().mirror(*this).loglike;
407  }
408  struct Logliker : Variabler<Logliker> {
410  double loglike = 0;
411 
412  template<class Distribution>
413  Logliker& data(Variable<Distribution>& variable, const std::string& name){
414  loglike += variable.loglike();
415  return *this;
416  }
417  };
418 
422  std::vector<std::string> names(void){
423  return Names().mirror(*this).names;
424  }
425  struct Names : Variabler<Names> {
427  std::vector<std::string> names;
428  std::string prefix;
429 
430  template<class Distribution, class... Dimensions>
431  Names& data(Array<Variable<Distribution>,Dimensions...>& array, const std::string& name){
432  prefix = name;
433  array.reflect(*this);
434  prefix = "";
435  return *this;
436  }
437 
438  template<class Distribution>
439  Names& data(Variable<Distribution>& variable, const std::string& name){
440  names.push_back(prefix+name+".value");
441  return *this;
442  }
443  };
444 
445 
449  Frame values(void){
450  return Values().mirror(*this).values;
451  }
452  struct Values : Variabler<Values> {
454  Frame values;
455  std::string prefix;
456 
457  Values():values(1){}
458 
459  template<class Distribution, class... Dimensions>
460  Values& data(Array<Variable<Distribution>,Dimensions...>& array, const std::string& name){
461  prefix = name;
462  array.reflect(*this);
463  prefix = "";
464  return *this;
465  }
466 
467  template<class Distribution>
468  Values& data(Variable<Distribution>& variable, const std::string& name){
469  values.add(prefix+name+".value",variable.value);
470  return *this;
471  }
472  };
473 
477  std::vector<double> vector(void){
478  return VectorGetter().mirror(*this).values;
479  }
480  struct VectorGetter : Variabler<VectorGetter> {
482  std::vector<double> values;
483 
484  template<class Distribution>
485  VectorGetter& data(Variable<Distribution>& variable, const std::string& name){
486  values.push_back(variable.value);
487  return *this;
488  }
489  };
490 
494  void vector(const std::vector<double>& vector){
495  VectorSetter(vector).mirror(*this);
496  }
497  struct VectorSetter : Variabler<VectorSetter> {
499  std::vector<double> values;
500  int index;
501 
502  VectorSetter(const std::vector<double>& vector){
503  values = vector;
504  index = 0;
505  }
506 
507  template<class Distribution>
508  VectorSetter& data(Variable<Distribution>& variable, const std::string& name){
509  variable.value = values[index];
510  index++;
511  return *this;
512  }
513  };
514 
515 }; // class Parameters
516 
517 } //namespace IOSKJ
double recruits_multiplier
Definition: model.hpp:109
Definition: parameters.hpp:36
Definition: data.hpp:6
void initialise(void)
Definition: model.hpp:539
double mortality_mean
Definition: model.hpp:208
double growth_rate_1
Definition: model.hpp:129
Definition: parameters.hpp:452
Definition: model.hpp:13
Variable< TruncatedNormal > maturity_inflection
Definition: parameters.hpp:93
Array< double, RegionFrom, Region > movement_region
Definition: model.hpp:247
Definition: parameters.hpp:387
Variable< Uniform > recruits_sd
Definition: parameters.hpp:60
Array< double, Region > biomass_spawners_unfished
Definition: model.hpp:37
Variable< Fixed > weight_a
Definition: parameters.hpp:87
Parameters & bounce(void)
Definition: parameters.hpp:383
Definition: dimensions.hpp:22
Array< double, Method, SelectivityKnot > selectivity_values
Definition: model.hpp:274
double recruits_sd
Definition: model.hpp:89
void set(uint time, Model &model, bool catches_apply=true) const
Definition: parameters.hpp:213
std::vector< double > vector(void)
Definition: parameters.hpp:477
Parameters & randomise(void)
Definition: parameters.hpp:365
Definition: parameters.hpp:408
Frame values(void)
Definition: parameters.hpp:449
Definition: distributions.hpp:21
double loglike(void)
Definition: parameters.hpp:405
Definition: parameters.hpp:340
Variable< Uniform > movement_we_ma
Definition: parameters.hpp:116
Definition: parameters.hpp:480
Definition: parameters.hpp:369
Definition: parameters.hpp:12
double weight_length_a
Definition: model.hpp:165
std::vector< std::string > names(void)
Definition: parameters.hpp:422
Variable< Uniform > spawners_ma
Definition: parameters.hpp:28
Variable< Uniform > spawning_0
Definition: parameters.hpp:78
double maturity_length_inflection
Definition: model.hpp:186
Variable< Uniform > mortality_mean
Definition: parameters.hpp:99
Definition: distributions.hpp:153
double recruits_steepness
Definition: model.hpp:68
Variable< Uniform > spawners_unfished
Definition: parameters.hpp:18
double movement_length_inflection
Definition: model.hpp:252
Array< Variable< Normal >, RecdevYear > recruits_deviations
Definition: parameters.hpp:73
Array< double, Region, Method > effort
Definition: model.hpp:321
Variable< Uniform > recruits_autocorr
Definition: parameters.hpp:68
bool recruits_variation_on
Definition: model.hpp:84
Definition: parameters.hpp:497
void vector(const std::vector< double > &vector)
Definition: parameters.hpp:494
Array< Variable< Fixed >, Year, Quarter, Region, Method > catches
Definition: parameters.hpp:130
Variable< Fixed > growth_rate_1
Definition: parameters.hpp:104
Array< double, Region, Method > catches
Definition: model.hpp:313
Definition: parameters.hpp:425
Array< double, Quarter > spawning
Definition: model.hpp:47
void reflect(Mirror &mirror)
Definition: parameters.hpp:136
Array< Variable< Uniform >, Method, SelectivityKnot > selectivities
Definition: parameters.hpp:125