1 // $Id: ui_vars_forces.cpp,v 1.90 2012/03/09 22:55:20 jmcgill Exp $
2 
3 /*
4  *  Copyright 2004  Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein
5  *
6  *  This software is distributed free of charge for non-commercial use
7  *  and is copyrighted.  Of course, we do not guarantee that the software
8  *  works, and are not responsible for any damage you may cause or have.
9  *
10  */
11 
12 #include <cassert>
13 #include <algorithm>
14 #include <deque>
15 #include <map>
16 #include <vector>
17 
18 #include "calculators.h"
19 #include "constants.h"          // for method_type
20 #include "defaults.h"
21 #include "errhandling.h"
22 #include "registry.h"
23 #include "stringx.h"
24 #include "ui_vars.h"
25 #include "ui_constants.h"
26 #include "ui_vars_forces.h"
27 #include "ui_vars_prior.h"
28 #include "ui_warnings.h"
29 #include "vectorx.h"
30 
31 using std::deque;
32 using std::make_pair;
33 using std::map;
34 using std::vector;
35 using std::list;
36 
37 //------------------------------------------------------------------------------------
38 
UIVarsSingleForce(UIVars * myUIVars,force_type ftype,long int nparams,double defaultVal,method_type methodType,bool canBeSetUnset,bool isOn,long int eventMax,UIVarsPrior defaultPrior)39 UIVarsSingleForce::UIVarsSingleForce
40 (
41     UIVars * myUIVars,
42     force_type ftype,
43     long int nparams,
44     double defaultVal,
45     method_type methodType,
46     bool canBeSetUnset,
47     bool isOn,
48     long int eventMax,
49     UIVarsPrior defaultPrior
50     )
51     :
52     UIVarsComponent(myUIVars),
53     m_numParameters(nparams),
54     m_defaultValue(defaultVal),
55     m_defaultMethodType(methodType),
56     m_canSetOnOff(canBeSetUnset),
57     m_onOff(isOn),
58     m_maxEvents(eventMax),
59     m_profileType(defaults::profileType),
60     m_doProfile(nparams,true),
61     m_userSuppliedStartValues(nparams,FLAGDOUBLE),
62     // we CAN'T have user supplied start values at
63     // the time this structure is created. So we
64     // set them to FLAGDOUBLE. We should never access
65     // these FLAGDOUBLE values because that would
66     // require m_startValueMethodTypes to contain
67     // method_USER, and we assert against that below
68     m_startValueMethodTypes(nparams,methodType),
69     m_pstatusValues(nparams,ParamStatus(pstat_unconstrained)),
70     m_defaultPrior(defaultPrior),
71     m_priors(nparams, defaultPrior),
72     m_useDefaultPrior(nparams, true),
73     m_ftype(ftype)
74 {
75     long i;
76     for (i = 0; i < nparams; ++i)
77     {
78         m_pstatusValues.push_back(ParamStatus(pstat_unconstrained));
79     }
80     assert(methodType        != method_USER);
81     assert(m_defaultMethodType != method_USER);
82     // must be a type that comes with a default value
83     // (e.g. method_PROGRAMDEFAULT) or requires calculation
84     // (method_FST or method_WATTERSON)
85 }
86 
UIVarsSingleForce(UIVars * myUIVars,const UIVarsSingleForce & singleForce)87 UIVarsSingleForce::UIVarsSingleForce
88 (
89     UIVars * myUIVars,
90     const UIVarsSingleForce& singleForce)
91     :
92     UIVarsComponent(myUIVars),
93     m_numParameters                     (singleForce.m_numParameters),
94     m_defaultValue                      (singleForce.m_defaultValue),
95     m_defaultMethodType                 (singleForce.m_defaultMethodType),
96     m_canSetOnOff                       (singleForce.m_canSetOnOff),
97     m_onOff                             (singleForce.m_onOff),
98     m_maxEvents                         (singleForce.m_maxEvents),
99     m_profileType                       (singleForce.m_profileType),
100     m_doProfile                         (singleForce.m_doProfile),
101     m_userSuppliedStartValues           (singleForce.m_userSuppliedStartValues),
102     m_startValueMethodTypes             (singleForce.m_startValueMethodTypes),
103     m_groups                            (singleForce.m_groups),
104     m_pstatusValues                     (singleForce.m_pstatusValues),
105     m_defaultPrior                      (singleForce.m_defaultPrior),
106     m_priors                            (singleForce.m_priors),
107     m_useDefaultPrior                   (singleForce.m_useDefaultPrior),
108     m_ftype                             (singleForce.m_ftype),
109     m_calculatedStartValues             (singleForce.m_calculatedStartValues)
110 {
111 }
112 
checkIndexValue(long int index) const113 void UIVarsSingleForce::checkIndexValue(long int index) const
114 {
115     // if you get an assert here, the menu or xml logic
116     // isn't checking something it should be
117     assert(index >= 0);
118     assert(index < GetNumParameters());
119     // However, allowing the user to put in parameter values in the Group
120     // tag means we check here for that validity, and we need to
121     // throw if it fails:
122     if (index < 0)
123     {
124         throw data_error("Invalid (negative) parameter index in checkIndexValue.");
125     }
126     if (index >= GetNumParameters())
127     {
128         throw data_error("Invalid (too large) parameter index in checkIndexValue.");
129     }
130 }
131 
AssertOnIllegalStartMethod(method_type method)132 void UIVarsSingleForce::AssertOnIllegalStartMethod(method_type method)
133 {
134     assert(method == method_PROGRAMDEFAULT);
135     // assume that there are no calculation start method
136     // types (such as method_FST or method_WATTERSON) for
137     // an arbitrary force. Those that do have them will
138     // override this method
139 }
140 
141 // used to set a start method without providing a value (thus not
142 // suitable for use in Set
SetStartMethod(method_type method,long int index)143 void UIVarsSingleForce::SetStartMethod(method_type method, long int index)
144 {
145     checkIndexValue(index);
146     AssertOnIllegalStartMethod(method);
147     m_startValueMethodTypes[index] = method;
148 
149 }
150 
SetStartMethods(method_type method)151 void UIVarsSingleForce::SetStartMethods(method_type method)
152 {
153     for (int index = 0; index < GetNumParameters(); index++)
154     {
155         // use this method since we want to pick up
156         // sanity checking done in virtual method
157         // SetStartMethod
158         SetStartMethod(method,index);
159     }
160 }
161 
162 string
GetParamName(long int pindex)163 UIVarsSingleForce::GetParamName(long int pindex)
164 {
165     return GetConstUIVars().GetParamNameWithConstraint(m_ftype, pindex);
166 }
167 
168 bool
GetLegal() const169 UIVarsSingleForce::GetLegal() const
170 {
171     return (GetOnOff() || m_canSetOnOff);
172 }
173 
174 bool
GetDoProfile(long int index) const175 UIVarsSingleForce::GetDoProfile(long int index) const
176 {
177     checkIndexValue(index);
178     ParamStatus mystatus = GetParamstatus(index);
179     if (mystatus.Inferred())
180     {
181         if (GetConstUIVars().chains.GetDoBayesianAnalysis())
182         {
183             return true;
184         }
185         return m_doProfile[index];
186     }
187     else
188         return false;
189 }
190 
GetProfileType() const191 proftype UIVarsSingleForce::GetProfileType() const
192 {
193     return m_profileType;
194 }
195 
GetProfileType(long int index) const196 proftype UIVarsSingleForce::GetProfileType(long int index) const
197 {
198     checkIndexValue(index);
199     if( GetDoProfile(index))
200     {
201         return m_profileType;
202     }
203     else
204     {
205         return profile_NONE;
206     }
207 }
208 
209 string
GetProfileTypeSummaryDescription() const210 UIVarsSingleForce::GetProfileTypeSummaryDescription() const
211 {
212     proftype ptype = GetProfileType();
213     paramlistcondition condition = GetParamListCondition();
214     if(condition == paramlist_NO)
215     {
216         return ToString(condition) + "       ";
217     }
218     else
219     {
220         return ToString(ptype) +" (" +ToString(condition) +")";
221     }
222 }
223 
224 string
GetPriorTypeSummaryDescription() const225 UIVarsSingleForce::GetPriorTypeSummaryDescription() const
226 {
227     bool somelinear = false;
228     bool somelog = false;
229     for (unsigned long pnum=0; pnum<m_priors.size(); pnum++)
230     {
231         ParamStatus mystatus = GetParamstatus(pnum);
232         if (mystatus.Inferred())
233         {
234             switch(GetPrior(pnum).GetPriorType())
235             {
236                 case LINEAR:
237                     somelinear = true;
238                     break;
239                 case LOGARITHMIC:
240                     somelog = true;
241                     break;
242             }
243         }
244     }
245     if (somelinear && somelog)
246     {
247         return "(mixed linear/log)";
248     }
249     else if (somelinear && (!somelog))
250     {
251         return "(all linear)";
252     }
253     else if (somelog && (!somelinear))
254     {
255         return "(all logarithmic)";
256     }
257     else
258     {
259         return "(none eligible)";
260     }
261 }
262 
263 paramlistcondition
GetParamListCondition() const264 UIVarsSingleForce::GetParamListCondition() const
265 {
266     bool seenOff = false;
267     bool seenOn  = false;
268     for (int index = 0; index < GetNumParameters(); index++)
269     {
270         // premature optimization being the root of all
271         // evil, I've not chosen to break out of the loop when
272         // seenOn and seenOff are both true, but you can change
273         // it if you want -- ewalkup 8-19-2004
274         if(GetParamValid(index))
275         {
276             if (GetDoProfile(index))
277             {
278                 seenOn = true;
279             }
280             else
281             {
282                 seenOff = true;
283             }
284         }
285     }
286     if(seenOn)
287     {
288         if(seenOff)
289         {
290             return paramlist_MIX;
291         }
292         else
293         {
294             return paramlist_YES;
295         }
296     }
297     else
298     {
299         return paramlist_NO;
300     }
301 }
302 
SetDoProfile(bool doIt,long int index)303 void  UIVarsSingleForce::SetDoProfile(bool doIt, long int index)
304 {
305     checkIndexValue(index);
306     long gindex = ParamInGroup(index);
307     ParamStatus mystatus = GetParamstatus(index);
308     if (doIt && !mystatus.Varies())
309     {
310         // Do nothing--we can't turn on profiling for this parameter.
311         if (GetParamValid(index))
312         {
313             string warning = "Warning:  " + GetParamName(index) +
314                 " may not be profiled because it is currently set to be "
315                 + ToString(mystatus.Status()) + ".";
316             GetConstUIVars().GetUI()->AddWarning(warning);
317         }
318         return;
319     }
320     if (GetConstUIVars().chains.GetDoBayesianAnalysis())
321     {
322         if (doIt==false && mystatus.Inferred())
323         {
324             string warning = "Warning:  Profiling is always on for all valid parameters in a Bayesian analysis, since profiling takes no extra time.";
325             GetConstUIVars().GetUI()->AddWarning(warning);
326             return;
327         }
328     }
329     m_doProfile[index] = doIt;
330     if (gindex != FLAGLONG)
331     {
332         SetDoProfilesForGroup(doIt, gindex);
333     }
334 }
335 
SetDoProfile(bool doIt)336 void  UIVarsSingleForce::SetDoProfile(bool doIt)
337 {
338     if (GetConstUIVars().chains.GetDoBayesianAnalysis())
339     {
340         if (doIt==false)
341         {
342             string warning = "Warning:  Profiling is always on for all valid parameters in a Bayesian analysis, since profiling takes no extra time.";
343             GetConstUIVars().GetUI()->AddWarning(warning);
344             return;
345         }
346     }
347     for (int index = 0; index < GetNumParameters(); index++)
348     {
349         SetDoProfile(doIt,index);
350     }
351 }
352 
SetProfileType(proftype p)353 void UIVarsSingleForce::SetProfileType(proftype p)
354 {
355     m_profileType = p;
356 }
357 
GetParamstatus(long int pindex) const358 ParamStatus UIVarsSingleForce::GetParamstatus(long int pindex)  const
359 {
360     long int gindex = ParamInGroup(pindex);
361     if (gindex != FLAGLONG)
362     {
363         ParamStatus mystatus = m_groups[gindex].first;
364         if ((mystatus.Status() == pstat_identical) && (pindex == m_groups[gindex].second[0]))
365         {
366             return ParamStatus(pstat_identical_head);
367             //MFIX probably needs changing, need to interface here
368             //with finished UI design
369         }
370         else
371             if ((mystatus.Status() == pstat_multiplicative) && (pindex == m_groups[gindex].second[0]))
372             {
373                 return ParamStatus(pstat_multiplicative_head);
374             }
375             else
376             {
377                 return mystatus;
378             }
379     }
380     else return m_pstatusValues[pindex];
381 };
382 
SetParamstatus(const ParamStatus & mystatus,long int index)383 void UIVarsSingleForce::SetParamstatus(const ParamStatus& mystatus, long int index)
384 {
385     long int gindex = ParamInGroup(index);
386     if (gindex == FLAGLONG)
387     {
388         m_pstatusValues[index] = mystatus;
389     }
390     else
391     {
392         SetGroupParamstatus(mystatus.Status(), gindex);
393     }
394 };
395 
GetStartValue(long int pindex) const396 double UIVarsSingleForce::GetStartValue(long int pindex) const
397 {
398     long int gindex = ParamInGroup(pindex);
399     if (gindex == FLAGLONG)
400     {
401         return GetUngroupedStartValue(pindex);
402     }
403     double sum = 0;
404     for (unsigned long int gpindex = 0; gpindex < m_groups[gindex].second.size(); gpindex++)
405     {
406         sum += GetUngroupedStartValue(m_groups[gindex].second[gpindex]);
407     }
408     return (sum/m_groups[gindex].second.size());
409 }
410 
GetUngroupedStartValue(long int index) const411 double UIVarsSingleForce::GetUngroupedStartValue(long int index) const
412 {
413     // start value might have been set by the user, or we might
414     // have to grab it from the calculated start values
415 
416     double retval = 0.0;
417     if (!GetParamstatus(index).Valid()) return 0.0;
418 
419     checkIndexValue(index);
420     method_type thisMethod = m_startValueMethodTypes[index];
421 
422     switch(thisMethod)
423     {
424         case method_PROGRAMDEFAULT:
425             retval = m_defaultValue;
426             break;
427         case method_USER:
428             retval = m_userSuppliedStartValues[index];
429             break;
430         default:
431         {
432             // see if we have calculated values for the
433             // start value method type for this parameter
434             map<method_type,DoubleVec1d>::const_iterator it;
435             it = m_calculatedStartValues.find(thisMethod);
436             if(it == m_calculatedStartValues.end())
437             {
438                 assert(false);
439                 throw implementation_error("Unable to calculate start values for " +
440                                            ToString(thisMethod) + ".");
441             }
442             // we've populated the m_calculatedStartValues for
443             // this method, so grab them and return the correct
444             // one for this parameter
445             retval = (it->second)[index];
446             break;
447         }
448     }
449     double minval = GetMinStartValue(index);
450     double maxval = GetMaxStartValue(index);
451     assert (maxval > minval);
452     if (retval < minval)
453     {
454         return minval;
455     }
456     if (retval > maxval)
457     {
458         return maxval;
459     }
460     return retval;
461 }
462 
463 DoubleVec1d
GetStartValues() const464 UIVarsSingleForce::GetStartValues() const
465 {
466     DoubleVec1d retValue(GetNumParameters(),FLAGDOUBLE);
467     // the user may have calculated start values and
468     // then hand-edited some of them, so we need to
469     // populate a vector with the individual values
470     for(size_t i = 0; i < retValue.size(); i++)
471     {
472         retValue[i] = GetStartValue(i);
473     }
474     return retValue;
475 }
476 
GetMinStartValue(long int pindex) const477 double UIVarsSingleForce::GetMinStartValue(long int pindex) const
478 {
479     ParamStatus mystatus = GetParamstatus(pindex);
480     if (!mystatus.Valid()) return 0;
481     if (GetConstUIVars().chains.GetDoBayesianAnalysis())
482     {
483         if (mystatus.Status() != pstat_constant)
484         {
485             return GetPrior(pindex).GetLowerBound();
486         }
487     }
488     switch(m_ftype)
489     {
490         case force_COAL:
491             return defaults::minTheta;
492         case force_MIG:
493         case force_DIVMIG:
494             return defaults::minMigRate;
495         case force_DISEASE:
496             return defaults::minDiseaseRate;
497         case force_REC:
498             return defaults::minRecRate;
499         case force_EXPGROWSTICK:
500         case force_GROW:
501             return defaults::minGrowRate;
502         case force_REGION_GAMMA:
503             return defaults::minGammaOverRegions;
504             break;
505         case force_LOGSELECTSTICK:
506         case force_LOGISTICSELECTION:
507             return defaults::minLSelectCoeff;
508             break;
509         case force_DIVERGENCE:
510             return defaults::minEpoch;
511             break;
512         default:
513             assert(false);              //Uncaught force type.
514     }
515     return 0.0;  //To prevent compiler warning.
516 }
517 
GetMaxStartValue(long int pindex) const518 double UIVarsSingleForce::GetMaxStartValue(long int pindex) const
519 {
520     ParamStatus mystatus = GetParamstatus(pindex);
521     if (!mystatus.Valid()) return 0;
522     if (GetConstUIVars().chains.GetDoBayesianAnalysis())
523     {
524         if (mystatus.Status() != pstat_constant)
525         {
526             return GetPrior(pindex).GetUpperBound();
527         }
528     }
529     switch(m_ftype)
530     {
531         case force_COAL:
532             return defaults::maxTheta;
533         case force_MIG:
534         case force_DIVMIG:
535             return defaults::maxMigRate;
536         case force_DISEASE:
537             return defaults::maxDiseaseRate;
538         case force_REC:
539             return defaults::maxRecRate;
540         case force_EXPGROWSTICK:
541         case force_GROW:
542             return defaults::maxGrowRate;
543         case force_REGION_GAMMA:
544             return defaults::maxGammaOverRegions;
545             break;
546         case force_LOGSELECTSTICK:
547         case force_LOGISTICSELECTION:
548             return defaults::maxLSelectCoeff;
549             break;
550         case force_DIVERGENCE:
551             return defaults::maxEpoch;
552             break;
553         default:
554             assert(false);              //Uncaught force type.
555     }
556     return 1000.0; // To prevent compiler warning.
557 }
558 
SetUserStartValue(double startVal,long int index)559 void UIVarsSingleForce::SetUserStartValue(double startVal, long int index)
560 {
561     checkIndexValue(index);
562     bool isinvalid = !GetParamstatus(index).Valid();
563     if (isinvalid)
564     {
565         if (startVal != 0)
566         {
567             string warning = "Warning:  " + GetParamName(index) +
568                 " ignores any attempt to set the starting value, since it has been set invalid.";
569             GetConstUIVars().GetUI()->AddWarning(warning);
570         }
571         return;
572     }
573     double minval = GetMinStartValue(index);
574     double maxval = GetMaxStartValue(index);
575     assert ((maxval > minval) || isinvalid);
576     if (startVal < minval)
577     {
578         startVal = minval;
579         string warning = "Warning:  the minimum value for " + GetParamName(index) +
580             " is " + ToString(minval) + ":  setting the starting value there.";
581         GetConstUIVars().GetUI()->AddWarning(warning);
582     }
583     if (startVal > maxval)
584     {
585         startVal = maxval;
586         string warning = "Warning:  the maximum value for " + GetParamName(index) +
587             " is " + ToString(maxval) + ":  setting the starting value there.";
588         GetConstUIVars().GetUI()->AddWarning(warning);
589     }
590     long int gindex = ParamInGroup(index);
591     if (gindex != FLAGLONG)
592     {
593         for (unsigned long int gpindex = 0; gpindex < m_groups[gindex].second.size(); gpindex++)
594         {
595             long int pindex = m_groups[gindex].second[gpindex];
596             m_userSuppliedStartValues[pindex]=startVal;
597             m_startValueMethodTypes[pindex] = method_USER;
598         }
599     }
600     else
601     {
602         m_userSuppliedStartValues[index]=startVal;
603         m_startValueMethodTypes[index] = method_USER; // don't use SetStartMethod
604         // here -- it can block use
605         // of method_USER since
606         // the UI shouldn't set
607         // method_USER without
608         // going through this method
609     }
610 }
611 
SetUserStartValues(double startVal)612 void UIVarsSingleForce::SetUserStartValues(double startVal)
613 {
614     for (int pindex = 0; pindex < GetNumParameters(); pindex++)
615     {
616         if (!GetParamstatus(pindex).Valid())
617         {
618             SetUserStartValue(startVal,pindex);
619         }
620     }
621 }
622 
GetStartMethod(long int index) const623 method_type UIVarsSingleForce::GetStartMethod(long int index) const
624 {
625     checkIndexValue(index);
626     return m_startValueMethodTypes[index];
627 }
628 
SetTrueValue(double trueVal,long int index)629 void UIVarsSingleForce::SetTrueValue(double trueVal, long int index)
630 {
631     checkIndexValue(index);
632     if (!GetParamstatus(index).Valid())
633     {
634         if (trueVal != 0)
635         {
636             string warning = "Warning:  " + GetParamName(index) +
637                 " ignores any attempt to set the starting value, since it has been set invalid.";
638             GetConstUIVars().GetUI()->AddWarning(warning);
639         }
640         return;
641     }
642     if (m_truevalues.empty())
643     {
644         m_truevalues.resize(GetNumParameters());
645     }
646     m_truevalues[index] = trueVal;
647 }
648 
GetTrueValue(long int index) const649 double UIVarsSingleForce::GetTrueValue(long int index) const
650 {
651     checkIndexValue(index);
652     if (m_truevalues.empty()) return FLAGDOUBLE; // JDEBUG
653     else return m_truevalues[index];
654 }
655 
GetPrior(long int pindex) const656 const UIVarsPrior& UIVarsSingleForce::GetPrior(long int pindex) const
657 {
658     if (pindex == uiconst::GLOBAL_ID)
659     {
660         return m_defaultPrior;
661     }
662     checkIndexValue(pindex);
663     if (GetUseDefaultPrior(pindex))
664     {
665         return m_defaultPrior;
666     }
667     return m_priors[pindex];
668 };
669 
GetPriorType(long int pindex) const670 priortype UIVarsSingleForce::GetPriorType(long int pindex) const
671 {
672     checkIndexValue(pindex);
673     return GetPrior(pindex).GetPriorType();
674 };
675 
GetLowerBound(long int pindex) const676 double UIVarsSingleForce::GetLowerBound(long int pindex) const
677 {
678     checkIndexValue(pindex);
679     return GetPrior(pindex).GetLowerBound();
680 };
681 
GetUpperBound(long int pindex) const682 double UIVarsSingleForce::GetUpperBound(long int pindex) const
683 {
684     checkIndexValue(pindex);
685     return GetPrior(pindex).GetUpperBound();
686 };
687 
688 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
GetRelativeSampling(long int pindex) const689 long UIVarsSingleForce::GetRelativeSampling(long int pindex) const
690 {
691     checkIndexValue(pindex);
692     return GetPrior(pindex).GetRelativeSampling();
693 };
694 #endif
695 
SetPriorType(priortype ptype,long int pindex)696 void UIVarsSingleForce::SetPriorType(priortype ptype, long int pindex)
697 {
698     checkIndexValue(pindex);
699     long int gindex = ParamInGroup(pindex);
700     if (gindex == FLAGLONG)
701     {
702         SetUngroupedPriorType(ptype, pindex);
703     }
704     else for (unsigned long int gpindex = 0; gpindex < m_groups[gindex].second.size(); gpindex++)
705          {
706              SetUngroupedPriorType(ptype, m_groups[gindex].second[gpindex]);
707          }
708 }
709 
SetUngroupedPriorType(priortype ptype,long int pindex)710 void UIVarsSingleForce::SetUngroupedPriorType(priortype ptype, long int pindex)
711 {
712     if (GetUseDefaultPrior(pindex))
713     {
714         m_useDefaultPrior[pindex] = false;
715         m_priors[pindex] = m_defaultPrior;
716     }
717     m_priors[pindex].SetPriorType(ptype);
718 }
719 
720 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
SetRelativeSampling(long rate,long int pindex)721 void UIVarsSingleForce::SetRelativeSampling(long rate, long int pindex)
722 {
723     checkIndexValue(pindex);
724     long int gindex = ParamInGroup(pindex);
725     if (gindex == FLAGLONG)
726     {
727         SetUngroupedRelativeSampling(rate, pindex);
728     }
729     else
730         for (unsigned long int gpindex = 0; gpindex < m_groups[gindex].second.size(); gpindex++)
731         {
732             SetUngroupedRelativeSampling(rate, m_groups[gindex].second[gpindex]);
733         }
734 }
735 
SetUngroupedRelativeSampling(long rate,long int pindex)736 void UIVarsSingleForce::SetUngroupedRelativeSampling(long rate, long int pindex)
737 {
738     checkIndexValue(pindex);
739     if (GetUseDefaultPrior(pindex))
740     {
741         m_useDefaultPrior[pindex] = false;
742         m_priors[pindex] = m_defaultPrior;
743     }
744     m_priors[pindex].SetRelativeSampling(rate);
745 }
746 
747 #endif
748 
SetLowerBound(double bound,long int pindex)749 void UIVarsSingleForce::SetLowerBound(double bound, long int pindex)
750 {
751     checkIndexValue(pindex);
752     long int gindex = ParamInGroup(pindex);
753     if (gindex == FLAGLONG)
754     {
755         SetUngroupedLowerBound(bound, pindex);
756     }
757     else
758         for (unsigned long int gpindex = 0; gpindex < m_groups[gindex].second.size(); gpindex++)
759         {
760             SetUngroupedLowerBound(bound, m_groups[gindex].second[gpindex]);
761         }
762 }
763 
SetUngroupedLowerBound(double bound,long int pindex)764 void UIVarsSingleForce::SetUngroupedLowerBound(double bound, long int pindex)
765 {
766     checkIndexValue(pindex);
767     if (GetUseDefaultPrior(pindex))
768     {
769         m_useDefaultPrior[pindex] = false;
770         m_priors[pindex] = m_defaultPrior;
771     }
772     m_priors[pindex].SetLowerBound(bound);
773 }
774 
SetUpperBound(double bound,long int pindex)775 void UIVarsSingleForce::SetUpperBound(double bound, long int pindex)
776 {
777     checkIndexValue(pindex);
778     long int gindex = ParamInGroup(pindex);
779     if (gindex == FLAGLONG)
780     {
781         SetUngroupedUpperBound(bound, pindex);
782     }
783     else for (unsigned long int gpindex = 0; gpindex < m_groups[gindex].second.size(); gpindex++)
784          {
785              SetUngroupedUpperBound(bound, m_groups[gindex].second[gpindex]);
786          }
787 }
788 
SetUngroupedUpperBound(double bound,long int pindex)789 void UIVarsSingleForce::SetUngroupedUpperBound(double bound, long int pindex)
790 {
791     checkIndexValue(pindex);
792     if (GetUseDefaultPrior(pindex))
793     {
794         m_useDefaultPrior[pindex] = false;
795         m_priors[pindex] = m_defaultPrior;
796     }
797     m_priors[pindex].SetUpperBound(bound);
798 }
799 
800 //------------------------------------------------------------------------------------
801 
GetDefaultPrior() const802 const UIVarsPrior& UIVarsSingleForce::GetDefaultPrior() const
803 {
804     return m_defaultPrior;
805 };
806 
GetUseDefaultPrior(long int pindex) const807 bool UIVarsSingleForce::GetUseDefaultPrior(long int pindex) const
808 {
809     checkIndexValue(pindex);
810     return m_useDefaultPrior[pindex];
811 };
812 
GetDefaultPriorType() const813 priortype UIVarsSingleForce::GetDefaultPriorType() const
814 {
815     return m_defaultPrior.GetPriorType();
816 };
817 
GetDefaultLowerBound() const818 double UIVarsSingleForce::GetDefaultLowerBound() const
819 {
820     return m_defaultPrior.GetLowerBound();
821 };
822 
GetDefaultUpperBound() const823 double UIVarsSingleForce::GetDefaultUpperBound() const
824 {
825     return m_defaultPrior.GetUpperBound();
826 };
827 
828 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
GetDefaultRelativeSampling() const829 long UIVarsSingleForce::GetDefaultRelativeSampling() const
830 {
831     return m_defaultPrior.GetRelativeSampling();
832 };
833 #endif
834 
SetUseDefaultPrior(bool val,long int pindex)835 void UIVarsSingleForce::SetUseDefaultPrior(bool val, long int pindex)
836 {
837     checkIndexValue(pindex);
838     m_useDefaultPrior[pindex] = val;
839 };
840 
SetUseAllDefaultPriors()841 void UIVarsSingleForce::SetUseAllDefaultPriors()
842 {
843     for (unsigned long int pindex = 0; pindex < m_useDefaultPrior.size(); pindex++)
844     {
845         m_useDefaultPrior[pindex] = true;
846     }
847 };
848 
SetDefaultPriorType(priortype ptype)849 void UIVarsSingleForce::SetDefaultPriorType(priortype ptype)
850 {
851     m_defaultPrior.SetPriorType(ptype);
852 }
853 
SetDefaultLowerBound(double bound)854 void UIVarsSingleForce::SetDefaultLowerBound(double bound)
855 {
856     m_defaultPrior.SetLowerBound(bound);
857 }
858 
SetDefaultUpperBound(double bound)859 void UIVarsSingleForce::SetDefaultUpperBound(double bound)
860 {
861     m_defaultPrior.SetUpperBound(bound);
862 }
863 
864 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
SetDefaultRelativeSampling(long rate)865 void UIVarsSingleForce::SetDefaultRelativeSampling(long rate)
866 {
867     m_defaultPrior.SetRelativeSampling(rate);
868 }
869 #endif
870 
871 //------------------------------------------------------------------------------------
872 
873 void
SetMaxEvents(long int events)874 UIVarsSingleForce::SetMaxEvents(long int events)
875 {
876     if (m_ftype != force_GROW && m_ftype != force_COAL && events <= 0)
877     {
878         throw data_error("The maximum number of events for force " + ToString(m_ftype) + " must be greater than zero.");
879     }
880     m_maxEvents = events;
881 }
882 
883 void
SetOnOff(bool onOffVal)884 UIVarsSingleForce::SetOnOff(bool onOffVal)
885 {
886     assert( m_canSetOnOff || ( onOffVal == m_onOff ) );
887     m_onOff = onOffVal;
888 }
889 
890 bool
GetParamValid(long int id) const891 UIVarsSingleForce::GetParamValid(long int id) const
892 {
893     return (GetOnOff() && (id >= 0) && (id < m_numParameters));
894 }
895 
896 bool
GetParamUnique(long int id) const897 UIVarsSingleForce::GetParamUnique(long int id) const
898 {
899     long int gindex = ParamInGroup(id);
900     if (gindex == FLAGLONG) return true;
901     if (m_groups[gindex].second[0] == id) return true;
902     return false;
903 }
904 
SomeVariableParams() const905 bool UIVarsSingleForce::SomeVariableParams() const
906 {
907     for (long int pnum = 0; pnum < m_numParameters; pnum++)
908     {
909         if (GetParamstatus(pnum).Varies()) return true;
910     }
911     return false;  // nothing ever varied
912 }
913 
AddGroup(ParamStatus mystatus,LongVec1d indices)914 void UIVarsSingleForce::AddGroup(ParamStatus mystatus, LongVec1d indices)
915 {
916     assert(indices.size() > 1);
917 
918     //Make a new ParamGroup and put it into m_groups.  Don't just put 'indices'
919     // into it because we need to check each entry in it.
920     LongVec1d blanklist;
921     ParamGroup newgroup = make_pair(mystatus,blanklist);
922     m_groups.push_back(newgroup);
923     long int gindex = m_groups.size()-1; //<-OK because we just added one.
924 
925     //AddGroup is at the interface between the user and the program, whether
926     // through the menu or through the XML. As such, the indexes used start
927     // at one instead of zero--this is where that is changed for the program.
928     for (unsigned long int vecindex = 0; vecindex < indices.size(); vecindex++)
929     {
930         AddParamToGroup(indices[vecindex] - 1, gindex);
931     }
932 }
933 
AddParamToGroup(long int pindex,long int gindex)934 void UIVarsSingleForce::AddParamToGroup(long int pindex, long int gindex)
935 {
936     checkGIndexValue(gindex);
937     checkIndexValue(pindex);
938     if (ParamInGroup(pindex) != FLAGLONG)
939     {
940         string e = "Invalid parameter indexes in group constraints for force "
941             + ToString(m_ftype)
942             + ":  The same parameter index is included in more than one group.";
943         throw data_error(e);
944     }
945     if (m_groups[gindex].second.size() > 0)
946     {
947         //copy the prior to the new parameter.
948         long int onegroupparam = m_groups[gindex].second[0];
949         m_useDefaultPrior[pindex] = m_useDefaultPrior[onegroupparam];
950         m_priors[pindex] = m_priors[onegroupparam];
951     }
952     m_groups[gindex].second.push_back(pindex);
953     std::sort(m_groups[gindex].second.begin(), m_groups[gindex].second.end());
954 }
955 
AddParamToNewGroup(long int pindex)956 void UIVarsSingleForce::AddParamToNewGroup(long int pindex)
957 {
958     checkIndexValue(pindex);
959     if (ParamInGroup(pindex) != FLAGLONG)
960     {
961         throw data_error("Cannot add a parameter to a new group because it is already in a group.");
962     }
963     LongVec1d pindices;
964     pindices.push_back(pindex);
965     ParamGroup newgroup = make_pair(defaults::groupPstat, pindices);
966     m_groups.push_back(newgroup);
967 }
968 
RemoveParamIfInAGroup(long int pindex)969 void UIVarsSingleForce::RemoveParamIfInAGroup(long int pindex)
970 {
971     long int gnum = ParamInGroup(pindex);
972     if (gnum != FLAGLONG)
973     {
974         for (vector<long int>::iterator gpindex = m_groups[gnum].second.begin();
975              gpindex != m_groups[gnum].second.end(); )
976         {
977             if ((*gpindex) == pindex)
978             {
979                 ParamStatus old_pstat = GetGroupParamstatus(gnum);
980                 gpindex = m_groups[gnum].second.erase(gpindex);
981                 if (m_groups[gnum].second.size() == 0)
982                 {
983                     //Delete the group--it's empty.
984                     m_groups.erase(m_groups.begin() + gnum);
985                 }
986                 if (old_pstat.Grouped())
987                 {
988                     SetParamstatus(ParamStatus(pstat_unconstrained), pindex);
989                 }
990                 else
991                 {
992                     SetParamstatus(old_pstat, pindex);
993                 }
994                 return;
995             }
996             else
997             {
998                 gpindex++;
999             }
1000         }
1001     }
1002 }
1003 
SetGroupParamstatus(ParamStatus pstat,long int gindex)1004 void UIVarsSingleForce::SetGroupParamstatus(ParamStatus pstat, long int gindex)
1005 {
1006     // MDEBUG not correct for multiplicative!
1007     if (pstat.Status() == pstat_unconstrained)
1008     {
1009         pstat = ParamStatus(pstat_identical);
1010         GetConstUIVars().GetUI()->AddWarning("Warning:  Groups may not be set 'unconstrained'; setting to 'identical' instead.");
1011     }
1012     checkGIndexValue(gindex);
1013     m_groups[gindex].first = pstat;
1014 }
1015 
GetGroupParamstatus(long int gindex) const1016 ParamStatus UIVarsSingleForce::GetGroupParamstatus(long int gindex) const
1017 {
1018     checkGIndexValue(gindex);
1019     return m_groups[gindex].first;
1020 }
1021 
GetGroupParamList(long int gindex) const1022 LongVec1d UIVarsSingleForce::GetGroupParamList(long int gindex) const
1023 {
1024     checkGIndexValue(gindex);
1025     return m_groups[gindex].second;
1026 }
1027 
ParamInGroup(long int pindex) const1028 long int UIVarsSingleForce::ParamInGroup(long int pindex) const
1029 {
1030     checkIndexValue(pindex);
1031     for (long int gindex = 0; gindex < static_cast<long int>(m_groups.size()); gindex++)
1032     {
1033         for (unsigned long int gpindex = 0; gpindex < m_groups[gindex].second.size(); gpindex++)
1034         {
1035             if (pindex == m_groups[gindex].second[gpindex])
1036             {
1037                 return static_cast<long int>(gindex);
1038             }
1039         }
1040     }
1041     return FLAGLONG;
1042 }
1043 
SetDoProfilesForGroup(bool doIt,long int gindex)1044 void UIVarsSingleForce::SetDoProfilesForGroup(bool doIt, long int gindex)
1045 {
1046     //Since this is a private function that runs from SetDoProfile(), all the
1047     // error checking has already been done, and we need only set the
1048     // appropriate values.
1049     checkGIndexValue(gindex);
1050     for (unsigned long int gpindex = 0; gpindex < m_groups[gindex].second.size(); gpindex++)
1051     {
1052         m_doProfile[m_groups[gindex].second[gpindex]] = doIt;
1053     }
1054 }
1055 
checkGIndexValue(long int gindex) const1056 void UIVarsSingleForce::checkGIndexValue(long int gindex) const
1057 {
1058     if (gindex==FLAGLONG) return;
1059     assert (gindex >= 0);
1060     if (gindex<0)
1061         throw data_error("Error:  group index value less than zero.");
1062     assert(gindex < static_cast<long int>(m_groups.size()));
1063     if (gindex >= static_cast<long int>(m_groups.size()))
1064         throw data_error("Error:  group index value greater than the number of groups.");
1065 }
1066 
AreGroupsValid() const1067 bool UIVarsSingleForce::AreGroupsValid() const
1068 {
1069     LongVec1d allpindices;
1070     for (unsigned long int gindex = 0; gindex < m_groups.size(); gindex++)
1071     {
1072         if (m_groups[gindex].second.size() < 2) return false;
1073         allpindices.insert(allpindices.end(), m_groups[gindex].second.begin(), m_groups[gindex].second.end());
1074     }
1075     std::sort(allpindices.begin(), allpindices.end());
1076     for (unsigned long int gpindex=1; gpindex<allpindices.size(); gpindex++)
1077     {
1078         if (allpindices[gpindex] == allpindices[gpindex-1])
1079             return false;
1080     }
1081     return true;
1082 }
1083 
FixGroups()1084 void UIVarsSingleForce::FixGroups()
1085 {
1086     //First, we remove any parameter that existed in more than one group. This
1087     // shouldn't ever be the case due to checks in AddParamToGroup, but hey.
1088     // First we have to find them again.
1089     LongVec1d allpindices;
1090     for (unsigned long int gindex = 0; gindex < m_groups.size(); gindex++)
1091     {
1092         allpindices.insert(allpindices.end(), m_groups[gindex].second.begin(), m_groups[gindex].second.end());
1093     }
1094     std::sort(allpindices.begin(), allpindices.end());
1095     for (unsigned long int gpindex=1; gpindex<allpindices.size(); gpindex++)
1096     {
1097         if (allpindices[gpindex] == allpindices[gpindex-1])
1098         {
1099             RemoveParamIfInAGroup(allpindices[gpindex]);
1100             //This removes the param from all groups.  It's not the ideal solution,
1101             // and the real solution is to never get in this situation in the first
1102             // place.  Which should be covered in AddParamToGroup.  So we're set.
1103         }
1104     }
1105 
1106     //Now, any parameter status flags that are 'joint' or 'identical' but do
1107     // not correspond with any group are set to 'unconstrained'.
1108     for (long int pindex = 0; pindex < m_numParameters; pindex++)
1109     {
1110         ParamStatus mystatus = GetParamstatus(pindex);
1111         if (mystatus.Grouped())
1112         {
1113             if (ParamInGroup(pindex) == FLAGLONG)
1114             {
1115                 SetParamstatus(ParamStatus(pstat_unconstrained), pindex);
1116             }
1117         }
1118         //Also, any truly invalid parameters (i.e. the migration diagonals) may
1119         // not be in a group, nor may they be set to some status other than
1120         // 'invalid'.
1121         if (!GetParamValid(pindex))
1122         {
1123             RemoveParamIfInAGroup(pindex);
1124             SetParamstatus(ParamStatus(pstat_invalid), pindex);
1125         }
1126     }
1127 
1128     //Now, any group with only one parameter in it is deleted, setting the
1129     // corresponding ParamStatus appropriately.
1130     for (vector<ParamGroup>::iterator giter = m_groups.begin();
1131          giter != m_groups.end();)      // <- iterator incremented below.
1132     {
1133         if ((*giter).second.size() == 0)
1134         {
1135             giter = m_groups.erase(giter);
1136         }
1137         else if ((*giter).second.size() == 1)
1138         {
1139             long int pindex = (*giter).second[0];
1140             ParamStatus mystatus((*giter).first);
1141             if (mystatus.Grouped())
1142             {
1143                 SetParamstatus(ParamStatus(pstat_unconstrained), pindex);
1144             }
1145             else
1146             {
1147                 SetParamstatus(ParamStatus((*giter).first), pindex);
1148             }
1149             giter = m_groups.erase(giter);
1150         }
1151         else
1152         {
1153             ++giter;
1154         }
1155     }
1156 }
1157 
1158 //------------------------------------------------------------------------------------
1159 
UIVars2DForce(UIVars * myUIVars,force_type ftype,long int numPartitions,double defaultVal,method_type methodType,bool canBeSetUnset,bool isOn,long int eventMax,UIVarsPrior defaultPrior)1160 UIVars2DForce::UIVars2DForce
1161 (   UIVars * myUIVars,
1162     force_type ftype,
1163     long int numPartitions,
1164     double defaultVal,
1165     method_type methodType,
1166     bool canBeSetUnset,
1167     bool isOn,
1168     long int eventMax,
1169     UIVarsPrior defaultPrior
1170     )
1171     :
1172     UIVarsSingleForce(
1173         myUIVars,
1174         ftype,
1175         numPartitions*numPartitions,
1176         defaultVal,
1177         methodType,
1178         canBeSetUnset,         // can't change original on/off setting
1179         isOn,
1180         eventMax,
1181         defaultPrior),
1182     m_npartitions(numPartitions)
1183 {
1184     // EWFIX.P5 DIMENSIONS -- we need the 1D <=> 2D translation objects
1185     //Make the diagonals of the parameter statuses (stati?) invalid.
1186     for (long int diagonal = 1; diagonal <= numPartitions; diagonal++)
1187     {
1188         SetParamstatus(ParamStatus(pstat_invalid), ((diagonal-1)*numPartitions + diagonal)-1);
1189     }
1190 }
1191 
UIVars2DForce(UIVars * myUIVars,const UIVars2DForce & twoD)1192 UIVars2DForce::UIVars2DForce
1193 (   UIVars * myUIVars, const UIVars2DForce & twoD )
1194     :
1195     UIVarsSingleForce(myUIVars,twoD),
1196     m_npartitions(twoD.m_npartitions)
1197 {
1198 }
1199 
AssertOnIllegalStartMethod(method_type method)1200 void UIVars2DForce::AssertOnIllegalStartMethod(method_type method)
1201 {
1202     assert( (method == method_FST) || (method == method_PROGRAMDEFAULT) );
1203 }
1204 
1205 bool
GetParamValid(long int id) const1206 UIVars2DForce::GetParamValid(long int id) const
1207 {
1208     bool possible = UIVarsSingleForce::GetParamValid(id);
1209     if(possible)
1210     {
1211         // NB I believe this means "is it off-diagonal"?
1212         // MDEBUG This may need to be overridden in DivMig, but I don't
1213         // know how as it requires the Epoch structure to determine which
1214         // off-diagonal entries are invalid
1215         const UIVars& vars = GetConstUIVars();
1216         long int numPops = vars.datapackplus.GetNPartitionsByForceType(m_ftype);
1217         long int intoIndex = id / numPops;
1218         long int fromIndex = id % numPops;
1219         return (intoIndex != fromIndex);
1220     }
1221     return false;
1222 }
1223 
1224 //AreZeroesValid checks to make sure that we haven't set so many migration
1225 // events to zero (and constant) that we can no longer coalesce.  Note that
1226 // setting a parameter to 'pstat_invalid' means that we are setting it to zero
1227 // and constant, too.
1228 //
1229 // This function could make suggestions about what to fix, but it suggestions
1230 // are unlikely to be biologically relevant for the populations involved,
1231 // so it seems better to just force the user to make their own changes, or just
1232 // remove all 0/constant constraints.
1233 //
1234 // If it is to make suggestions, it would need to be non-const.
1235 
1236 bool
AreZeroesValid() const1237 UIVars2DForce::AreZeroesValid() const
1238 {
1239     //The goal of this algorithm is to find 'Rome', a mythical land from which
1240     // all of your current populations descended.  In a migration system with
1241     // no constraints, all partitions could be Rome, but we only need to find
1242     // one to satisfy our test.  If we find at least one Rome, we return true,
1243     // and if not, we return false.
1244     //
1245     // First, we make two lists that will hold partition indexes in them,
1246     // 'reached' and 'unreached'.  At the beginning, everything is in
1247     // 'unreached'.
1248 
1249     list<long int> reached, unreached;
1250     for (long int partind = 0; partind < m_npartitions; partind++)
1251         unreached.push_back(partind);
1252 
1253     // Now we seize a partition at random (0) to see if it's Rome.
1254     long int testRome = 0;
1255 
1256     // Now we loop until we return either true or false.
1257     while (true)
1258     {
1259         //First, we don't have to worry about getting to testRome.  We also
1260         // don't need to add testRome to 'reached', since that list is only
1261         // used to back away from testRome if need be.
1262         unreached.remove(testRome);
1263 
1264         //Check to see who we can get to in 'unreached' from Rome.  We only
1265         // test routes that go through the unreached list, since everything in
1266         // the 'reached' list has already been exhaustively searched.
1267         UpdateReachList(testRome, unreached, reached);
1268 
1269         //Check to see if we're done.
1270         if (unreached.size() == 0) return true;
1271 
1272         //Otherwise, we need a new Rome candidate.  If our system is valid, Rome
1273         // *must* be in the 'unreached' group.  (If it wasn't, our old testRome
1274         // would have to have also been a valid Rome:  If everyone can come from
1275         // Rome by definition, and people in Rome can come from testRome, testRome
1276         // is also a valid 'Rome'.)
1277         testRome = PickANewRome(testRome, unreached, reached);
1278 
1279         //If PickANewRome failed, our system is invalid--return false;
1280         if (testRome == FLAGLONG) return false;
1281 
1282         //Otherwise, we can go ahead and loop with our new Rome.  Before we do,
1283         // though, we can clear out our 'reached' list.  We can do this because
1284         // not only do we know that migrants from our new testRome can get to
1285         // everywhere in 'reached', we *also* know that nothing in 'reached' can
1286         // get to 'unreached'--testRome and the other 'unreached' entries are the
1287         // only possibilities left.
1288         //
1289         // So, we clear 'reached'.  This has the effect of making our next loop
1290         // still more efficient.
1291         reached.clear();
1292     }
1293 }
1294 
UpdateReachList(long int testRome,list<long int> & unreached,list<long int> & reached) const1295 void UIVars2DForce::UpdateReachList(long int testRome, list<long int>& unreached,
1296                                     list<long int>& reached) const
1297 {
1298     list<long int> oneStepAway;
1299     oneStepAway.push_back(testRome);
1300 
1301     while (oneStepAway.size() > 0)
1302     {
1303         list<long int> twoStepsAway;
1304         for (list<long int>::iterator partfrom = oneStepAway.begin();
1305              partfrom != oneStepAway.end(); partfrom++)
1306         {
1307             for (list<long int>::iterator partto = unreached.begin();
1308                  partto != unreached.end(); partto++)
1309             {
1310                 if (CanReach((*partfrom), (*partto)))
1311                 {
1312                     twoStepsAway.push_back((*partto));
1313                 }
1314             }
1315         }
1316         for (list<long int>::iterator stepit = oneStepAway.begin();
1317              stepit != oneStepAway.end(); stepit++ )
1318         {
1319             reached.push_back((*stepit));
1320             unreached.remove((*stepit));
1321         }
1322         oneStepAway = twoStepsAway;
1323     }
1324 }
1325 
PickANewRome(long int oldRome,list<long int> unreached,list<long int> reached) const1326 long int UIVars2DForce::PickANewRome(long int oldRome, list<long int> unreached,
1327                                      list<long int> reached) const
1328 {
1329     list<long int> intermediates;
1330     intermediates.push_back(oldRome);
1331     reached.remove(oldRome);
1332     while (intermediates.size() > 0)
1333     {
1334         list<long int> newintermediates;
1335         for (list<long int>::iterator partto = intermediates.begin();
1336              partto != intermediates.end(); partto++)
1337         {
1338             //Check to see if we can get to anything in the 'unreached' list.
1339             // If so, that's our new Rome candidate, and we're done.
1340             for (list<long int>::iterator partfrom = unreached.begin();
1341                  partfrom != unreached.end(); partfrom++)
1342             {
1343                 if (CanReach((*partfrom), (*partto)))
1344                 {
1345                     return (*partfrom);
1346                 }
1347             }
1348             //We didn't get to 'unreached' directly; try going through the 'reached'
1349             // list.  If we find anything, we can remove it from 'reached'.
1350             for (list<long int>::iterator partfrom = reached.begin();
1351                  partfrom != reached.end();)
1352             {
1353                 if (CanReach((*partfrom), (*partto)))
1354                 {
1355                     newintermediates.push_back(*partfrom);
1356                     reached.erase(partfrom++);
1357                 }
1358                 else
1359                 {
1360                     partfrom++;
1361                 }
1362             }
1363         }
1364         intermediates = newintermediates;
1365     }
1366 
1367     //We never found any way to get to oldRome from anything in unreached.
1368     // Hence, our network is invalid.
1369     return FLAGLONG;
1370 }
1371 
CanReach(long int partfrom,long int partto) const1372 bool UIVars2DForce::CanReach(long int partfrom, long int partto) const
1373 {
1374     long int pindex = partto*m_npartitions + partfrom;
1375     if (GetParamstatus(pindex).Valid())
1376     {
1377         double pval = GetStartValue(pindex);
1378         // If the start value is zero, the populations are unconnected at least
1379         // for the first tree, and that is a problem even in a Bayesian run.
1380         if (pval == 0.0) return false;
1381         else return true;
1382     }
1383     else
1384         return false;
1385 }
1386 
1387 //------------------------------------------------------------------------------------
1388 //------------------------------------------------------------------------------------
1389 
UIVarsCoalForce(UIVars * myUIVars,long int numCrossPartitions)1390 UIVarsCoalForce::UIVarsCoalForce(UIVars * myUIVars, long int numCrossPartitions)
1391     :   UIVarsSingleForce(
1392         myUIVars,
1393         force_COAL,
1394         numCrossPartitions,
1395         defaults::theta,        //
1396         defaults::thetaMethod,
1397         false,                  // Coal force can't be turned off ever
1398         true,                   // Coal force always ON
1399         defaults::coalEvents,
1400         UIVarsPrior(myUIVars->GetUI(),
1401                     force_COAL,
1402                     defaults::priortypeTheta,
1403 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
1404                     defaults::samplingRate,
1405 #endif
1406                     defaults::lowerboundTheta,
1407                     defaults::upperboundTheta)
1408         )
1409 {
1410 }
1411 
UIVarsCoalForce(UIVars * myUIVars,const UIVarsCoalForce & coalForce)1412 UIVarsCoalForce::UIVarsCoalForce(UIVars * myUIVars, const UIVarsCoalForce& coalForce)
1413     :
1414     UIVarsSingleForce(myUIVars,coalForce)
1415 {
1416 }
1417 
AssertOnIllegalStartMethod(method_type method)1418 void UIVarsCoalForce::AssertOnIllegalStartMethod(method_type method)
1419 {
1420     assert( (method == method_FST)          ||
1421             (method == method_WATTERSON)    ||
1422             (method == method_PROGRAMDEFAULT));
1423     if ((method==method_FST) && !(GetConstUIVars().forces.GetForceLegal(force_MIG)))
1424     {
1425         throw data_error("The FST method is only available for data sets with more than one population.");
1426     }
1427 }
1428 
1429 void
FillCalculatedStartValues()1430 UIVarsCoalForce::FillCalculatedStartValues()
1431 {
1432     // do FST values
1433     if(GetConstUIVars().datapackplus.GetNCrossPartitions() > 1)
1434     {
1435         DoubleVec1d estimates;
1436         std::deque<bool> isCalculated;
1437         const UIVars& vars = GetConstUIVars();
1438         DoubleVec1d regionalthetascalars(vars.datapackplus.GetEffectivePopSizes());
1439         DoubleVec2d regionalmurates(vars.datamodel.GetRelativeMuRates());
1440         ThetaFSTMultiregion(registry.GetDataPack(), regionalthetascalars, regionalmurates, estimates, isCalculated);
1441         m_calculatedStartValues.erase(method_FST);
1442         m_calculatedStartValues.insert(make_pair(method_FST,estimates));
1443 
1444         std::set<string> defaultedEstimates;
1445         for (long int pindex = 0; pindex < static_cast<long int>(isCalculated.size()); pindex++)
1446         {
1447             if (!isCalculated[pindex])
1448             {
1449                 string name = GetParamName(pindex);
1450                 defaultedEstimates.insert(name);
1451             }
1452         }
1453         if (defaultedEstimates.size())
1454         {
1455             std::set<string>::iterator onename;
1456             string warning = "Warning:  calculating FST estimates for ";
1457             for (onename = defaultedEstimates.begin(); onename != defaultedEstimates.end(); onename++)
1458             {
1459                 warning += "\"" + *onename + "\", ";
1460             }
1461             warning += "is impossible due to the data for the populations involved.  If the FST method is invoked to obtain starting values for those parameters, defaults will be used instead.";
1462             GetConstUIVars().GetUI()->AddWarning(warning);
1463         }
1464     }
1465     // do Watterson values
1466     {
1467         DoubleVec1d estimates;
1468         std::deque<bool> isCalculated;
1469         const UIVars& vars = GetConstUIVars();
1470         DoubleVec1d regionalthetascalars(vars.datapackplus.GetEffectivePopSizes());
1471         DoubleVec2d regionalmurates(vars.datamodel.GetRelativeMuRates());
1472         ThetaWattersonMultiregion(registry.GetDataPack(), regionalthetascalars,
1473                                   regionalmurates, estimates, isCalculated);
1474         m_calculatedStartValues.erase(method_WATTERSON);
1475         m_calculatedStartValues.insert(make_pair(method_WATTERSON,estimates));
1476 
1477         std::set<string> defaultedEstimates;
1478         for (long int pindex = 0; pindex < static_cast<long int>(isCalculated.size()); pindex++)
1479         {
1480             if (!isCalculated[pindex])
1481             {
1482                 string name = GetParamName(pindex);
1483                 defaultedEstimates.insert(name);
1484             }
1485         }
1486         if (defaultedEstimates.size())
1487         {
1488             std::set<string>::iterator onename;
1489             string warning = "Warning:  calculating Watterson estimates for ";
1490             for (onename = defaultedEstimates.begin();
1491                  onename != defaultedEstimates.end(); onename++)
1492             {
1493                 warning += "\"" + *onename + "\", ";
1494             }
1495             warning += "is impossible because one or more genetic regions have no data or only one data point in the corresponding population(s).  If the Watterson method is invoked to obtain starting values for theta, defaults will be used in that calculation.";
1496             GetConstUIVars().GetUI()->AddWarning(warning);
1497         }
1498     }
1499 }
1500 
1501 bool
AreZeroesValid() const1502 UIVarsCoalForce::AreZeroesValid() const
1503 {
1504     //No force can be invalid or zero for coalescence.  It can't even start at
1505     // zero, regardless of whether it's held there.
1506     for (long int pindex = 0; pindex<GetNumParameters(); pindex++)
1507     {
1508         if (!GetParamstatus(pindex).Valid())
1509         {
1510             return false;
1511         }
1512         if (GetStartValue(pindex) == 0.0)
1513         {
1514             return false;
1515         }
1516     }
1517     return true;
1518 }
1519 
1520 //------------------------------------------------------------------------------------
1521 
UIVarsMigForce(UIVars * myUIVars,long int numPopulations,bool onOrOff)1522 UIVarsMigForce::UIVarsMigForce (UIVars * myUIVars, long int numPopulations, bool onOrOff)
1523     :
1524     UIVars2DForce(
1525         myUIVars,
1526         force_MIG,
1527         numPopulations,
1528         defaults::migration,
1529         defaults::migMethod,
1530         false,                  // can't change original on/off setting
1531         onOrOff,
1532         defaults::migEvents,
1533         UIVarsPrior(myUIVars->GetUI(),
1534                     force_MIG,
1535                     defaults::priortypeMig,
1536 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
1537                     defaults::samplingRate,
1538 #endif
1539                     defaults::lowerboundMig,
1540                     defaults::upperboundMig)
1541         )
1542 {
1543 }
1544 
UIVarsMigForce(UIVars * myUIVars,const UIVarsMigForce & migForce)1545 UIVarsMigForce::UIVarsMigForce
1546 (   UIVars * myUIVars, const UIVarsMigForce & migForce)
1547     :
1548     UIVars2DForce(myUIVars,migForce)
1549 {
1550 }
1551 
1552 void
FillCalculatedStartValues()1553 UIVarsMigForce::FillCalculatedStartValues()
1554 {
1555     DoubleVec1d estimates;
1556     std::deque<bool> isCalculated;
1557     const UIVars& vars = GetConstUIVars();
1558     DoubleVec2d regionalmurates(vars.datamodel.GetRelativeMuRates());
1559     MigFSTMultiregion(registry.GetDataPack(), regionalmurates,
1560                       estimates, isCalculated);
1561     m_calculatedStartValues.erase(method_FST);
1562     m_calculatedStartValues.insert(make_pair(method_FST,estimates));
1563 
1564     std::set<string> defaultedEstimates;
1565     for (long int pindex = 0; pindex < static_cast<long int>(isCalculated.size()); pindex++)
1566     {
1567         if (!isCalculated[pindex])
1568         {
1569             string name = GetParamName(pindex);
1570             defaultedEstimates.insert(name);
1571         }
1572     }
1573     if (defaultedEstimates.size())
1574     {
1575         std::set<string>::iterator onename;
1576         string warning = uiwarn::calcFST_0;
1577         for (onename = defaultedEstimates.begin(); onename != defaultedEstimates.end(); onename++)
1578         {
1579             warning += "\"" + *onename + "\", ";
1580         }
1581         warning += uiwarn::calcFST_1;
1582         GetConstUIVars().GetUI()->AddWarning(warning);
1583         //LS DEBUG:  This warning is always printed out when the user
1584         // first fires up LAMARC, and never afterwards, due to the fact
1585         // that FST is the default starting method for Migration.  If
1586         // this changes, the text of this method should probably change,
1587         // too.
1588     }
1589 }
1590 
1591 //-------------------------------------------------------------------------------------
1592 
UIVarsDivMigForce(UIVars * myUIVars,long int numPopulations,bool onOrOff)1593 UIVarsDivMigForce::UIVarsDivMigForce (UIVars * myUIVars, long int numPopulations, bool onOrOff)
1594     :
1595     UIVars2DForce(
1596         myUIVars,
1597         force_DIVMIG,
1598         numPopulations,
1599         defaults::divMigration,
1600         defaults::divMigMethod,
1601         false,                  // can't change original on/off setting
1602         onOrOff,
1603         defaults::migEvents,
1604         UIVarsPrior(myUIVars->GetUI(),
1605                     force_DIVMIG,
1606                     defaults::priortypeDivMig,
1607 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
1608                     defaults::samplingRate,
1609 #endif
1610                     defaults::lowerboundDivMig,
1611                     defaults::upperboundDivMig)
1612         )
1613 {
1614 }
1615 
UIVarsDivMigForce(UIVars * myUIVars,const UIVarsDivMigForce & divmigForce)1616 UIVarsDivMigForce::UIVarsDivMigForce
1617 (   UIVars * myUIVars, const UIVarsDivMigForce & divmigForce)
1618     :
1619     UIVars2DForce(myUIVars,divmigForce)
1620 {
1621 }
1622 
AssertOnIllegalStartMethod(method_type method)1623 void UIVarsDivMigForce::AssertOnIllegalStartMethod(method_type method)
1624 {
1625     assert(method == method_PROGRAMDEFAULT); // can't use FST here
1626 }
1627 
1628 //------------------------------------------------------------------------------------
1629 //------------------------------------------------------------------------------------
1630 
UIVarsDivergenceForce(UIVars * myUIVars,long int nDivPopulations)1631 UIVarsDivergenceForce::UIVarsDivergenceForce(UIVars * myUIVars, long int nDivPopulations)
1632     :   UIVarsSingleForce(
1633         myUIVars,
1634         force_DIVERGENCE,
1635         (nDivPopulations-1)/2, // truncation deliberate
1636         defaults::epochtime,
1637         defaults::divMethod,
1638         // MDEBUG not sure about the values of these two bools
1639         true,                   // Divergence force can't be turned off ever
1640         false,                   // Divergence force always ON
1641         defaults::epochEvents,
1642         UIVarsPrior(myUIVars->GetUI(),
1643                     force_DIVERGENCE,
1644                     defaults::priortypeEpoch,
1645 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
1646                     defaults::samplingRate,
1647 #endif
1648                     defaults::lowerboundEpoch,
1649                     defaults::upperboundEpoch)
1650         )
1651 {
1652     // the Divergence parameters, which are epoch times, must be specially marked
1653     long i;
1654     for (i = 0; i < (nDivPopulations-1)/2; ++i)
1655     {
1656         // JDEBUG, need to do something here? MakeParamAnEpochTime(i);
1657     }
1658 }
1659 
UIVarsDivergenceForce(UIVars * myUIVars,const UIVarsDivergenceForce & divForce)1660 UIVarsDivergenceForce::UIVarsDivergenceForce(UIVars * myUIVars, const UIVarsDivergenceForce& divForce)
1661     :
1662     UIVarsSingleForce(myUIVars,divForce)
1663 {
1664     // copy epoch info
1665     newpops = divForce.newpops;
1666     ancestors = divForce.ancestors;
1667 }
1668 
AssertOnIllegalStartMethod(method_type method)1669 void UIVarsDivergenceForce::AssertOnIllegalStartMethod(method_type method)
1670 {
1671     assert (method == method_PROGRAMDEFAULT);
1672 }
1673 
1674 bool
AreZeroesValid() const1675 UIVarsDivergenceForce::AreZeroesValid() const
1676 {
1677     //No parameter can be invalid or zero for divergence.  It can't even start at
1678     // zero, regardless of whether it's held there.
1679     for (long int pindex = 0; pindex<GetNumParameters(); pindex++)
1680     {
1681         if (!GetParamstatus(pindex).Valid())
1682         {
1683             return false;
1684         }
1685         if (GetStartValue(pindex) == 0.0)
1686         {
1687             return false;
1688         }
1689     }
1690     return true;
1691 }
1692 
1693 void
AddNewPops(const vector<string> & newp)1694 UIVarsDivergenceForce::AddNewPops(const vector<string>& newp)
1695 {
1696     newpops.push_back(newp);
1697 }
1698 
1699 void
AddAncestor(const string & anc)1700 UIVarsDivergenceForce::AddAncestor(const string& anc)
1701 {
1702     ancestors.push_back(anc);
1703 }
1704 
1705 vector<vector<string> >
GetNewPops() const1706 UIVarsDivergenceForce::GetNewPops() const
1707 {
1708     return newpops;
1709 }
1710 
1711 vector<string>
GetAncestors() const1712 UIVarsDivergenceForce::GetAncestors () const
1713 {
1714     return ancestors;
1715 }
1716 
1717 string
GetAncestor(long index) const1718 UIVarsDivergenceForce::GetAncestor (long index) const
1719 {
1720     return ancestors[index];
1721 }
1722 
1723 //------------------------------------------------------------------------------------
1724 
UIVarsDiseaseForce(UIVars * myUIVars,long int numDiseaseStates,bool isLegal)1725 UIVarsDiseaseForce::UIVarsDiseaseForce(
1726     UIVars * myUIVars,
1727     long int numDiseaseStates,
1728     bool isLegal)
1729     :
1730     UIVars2DForce(
1731         myUIVars,
1732         force_DISEASE,
1733         numDiseaseStates,
1734         defaults::disease,
1735         defaults::diseaseMethod,
1736         false,              // EWFIX.P5 DISEASE change false => isLegal later
1737         // when we figure out how to accomodate
1738         // change in number of theta and growth
1739         // params when disease forces are turned
1740         // on and off in the menu
1741         isLegal,
1742         defaults::diseaseEvents,
1743         UIVarsPrior(myUIVars->GetUI(),
1744                     force_DISEASE,
1745                     defaults::priortypeDisease,
1746 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
1747                     defaults::samplingRate,
1748 #endif
1749                     defaults::lowerboundDisease,
1750                     defaults::upperboundDisease)
1751         ),
1752     location(defaults::diseaseLocation)
1753 {
1754     //LS NOTE:  When we get multiple diseases states in, this is the place to
1755     // set up the invalid and identical parameters (re: the tic-tac-toe setup
1756     // we talked about on Joe's blackboard)
1757     //
1758     /* For example:  say we have two traits, Aa, and XYZ.  You can set things up:
1759 
1760        AX  AY  AZ    aX  aY  aZ
1761        AX --  ++  ++    ++  --  --
1762        AY ++  --  ++    --  ++  --
1763        AZ ++  ++  --    --  --  ++
1764 
1765        aX ++  --  --    --  ++  ++
1766        aY --  ++  --    ++  --  ++
1767        aZ --  --  ++    ++  ++  --
1768 
1769        So all the ++'s are possible, and all the --'s are set 'invalid', like the
1770        diagonal.  Additionally, if A->a is constant, and not influenced by
1771        the current XYZ, you can set AX->aX, AY->aY, and AZ->aZ to be equal to
1772        each other, and likewise for the other sets of rates.
1773     */
1774 }
1775 
UIVarsDiseaseForce(UIVars * myUIVars,const UIVarsDiseaseForce & diseaseForce)1776 UIVarsDiseaseForce::UIVarsDiseaseForce
1777 (   UIVars * myUIVars, const UIVarsDiseaseForce & diseaseForce)
1778     :
1779     UIVars2DForce(myUIVars,diseaseForce),
1780     location(diseaseForce.location)
1781 {
1782 }
1783 
1784 //------------------------------------------------------------------------------------
1785 
UIVarsRecForce(UIVars * myUIVars,bool canTurnOn)1786 UIVarsRecForce::UIVarsRecForce(UIVars * myUIVars, bool canTurnOn)
1787     :
1788     UIVarsSingleForce(
1789         myUIVars,
1790         force_REC,
1791         1L,                     // only one param value for recombine
1792         defaults::recombinationRate,
1793         defaults::recMethod,
1794         canTurnOn,              // recombine illegal for unlinked data
1795         false,                  // recombine force not required when possible
1796         defaults::recEvents,
1797         UIVarsPrior(myUIVars->GetUI(),
1798                     force_REC,
1799                     defaults::priortypeRec,
1800 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
1801                     defaults::samplingRate,
1802 #endif
1803                     defaults::lowerboundRec,
1804                     defaults::upperboundRec)
1805         )
1806 {
1807 }
1808 
UIVarsRecForce(UIVars * myUIVars,const UIVarsRecForce & recForce)1809 UIVarsRecForce::UIVarsRecForce(UIVars * myUIVars, const UIVarsRecForce& recForce)
1810     :
1811     UIVarsSingleForce(myUIVars,recForce)
1812 {
1813 }
1814 
1815 bool
AreZeroesValid() const1816 UIVarsRecForce::AreZeroesValid() const
1817 {
1818     //Recombination can be zero.  You might as well not have it on if so,
1819     // but who are we to quibble?  Also, if we allow different populations to
1820     // have different rec values at some point, any of them could be zero.
1821     return true;
1822 }
1823 
GetOnOff() const1824 bool UIVarsRecForce::GetOnOff() const
1825 {
1826     if (GetConstUIVars().traitmodels.AnyMappingAnalyses()) return true;
1827     return UIVarsSingleForce::GetOnOff();
1828 }
1829 
SetOnOff(bool onOffVal)1830 void UIVarsRecForce::SetOnOff(bool onOffVal)
1831 {
1832     if (GetConstUIVars().traitmodels.AnyMappingAnalyses() && !onOffVal)
1833     {
1834         throw data_error("Cannot turn off recombination when there are traits to be mapped.");
1835     }
1836     if (GetConstUIVars().datapackplus.AnySNPDataWithDefaultLocations() && onOffVal)
1837     {
1838         throw data_error("We cannot accurately estimate recombination as there is SNP data whose locations are unknown.  "
1839                          "If you want to estimate recombination, go back to the converter and use a map file to tell it where the sequenced SNPs are.  "
1840                          "See the documentation: the \"Length and Spacing Information with Segment Coordinates\" section in "
1841                          "genetic_map.html for how to do this within the GUI converter, or the \"Segments\" section "
1842                          "of converter_cmd.html for how to do this using the converter command file.");
1843     }
1844     UIVarsSingleForce::SetOnOff(onOffVal);
1845 }
1846 
1847 //------------------------------------------------------------------------------------
1848 
UIVarsRegionGammaForce(UIVars * myUIVars)1849 UIVarsRegionGammaForce::UIVarsRegionGammaForce(UIVars * myUIVars)
1850     :
1851     UIVarsSingleForce(
1852         myUIVars,
1853         force_REGION_GAMMA,
1854         1L,                     // only one param value for region gamma
1855         defaults::gammaOverRegions,
1856         defaults::recMethod,
1857         true,              // legal to turn on--ONLY for multi-region data
1858         false,             // this "force" is not required
1859         0,                 // no such thing as region gamma "events"
1860         UIVarsPrior(myUIVars->GetUI(),
1861                     force_REC,               //BUGBUG!!! no prior allowed!
1862                     defaults::priortypeRec,  //what to do???
1863 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
1864                     defaults::samplingRate,
1865 #endif
1866                     defaults::lowerboundRec,
1867                     defaults::upperboundRec)
1868         )
1869 {
1870     if (GetConstUIVars().datapackplus.GetNumRegions() == 1)
1871     {
1872         m_canSetOnOff = false;
1873     }
1874 }
1875 
UIVarsRegionGammaForce(UIVars * myUIVars,const UIVarsRegionGammaForce & regionGammaForce)1876 UIVarsRegionGammaForce::UIVarsRegionGammaForce(UIVars * myUIVars, const UIVarsRegionGammaForce& regionGammaForce)
1877     :
1878     UIVarsSingleForce(myUIVars,regionGammaForce)
1879 {
1880 }
1881 
GetOnOff() const1882 bool UIVarsRegionGammaForce::GetOnOff() const
1883 {
1884     if (GetConstUIVars().datapackplus.GetNumRegions() == 1) return false;
1885     if (GetConstUIVars().chains.GetDoBayesianAnalysis()) return false;
1886     if (GetConstUIVars().forces.GetForceOnOff(force_GROW)) return false;
1887     return UIVarsSingleForce::GetOnOff();
1888 }
1889 
1890 void
SetOnOff(bool onOffVal)1891 UIVarsRegionGammaForce::SetOnOff(bool onOffVal)
1892 {
1893     if (GetConstUIVars().datapackplus.GetNumRegions() == 1 && onOffVal)
1894     {
1895         throw data_error("Cannot analyze the region gamma when there is only one region to analyze.");
1896     }
1897     if (GetConstUIVars().chains.GetDoBayesianAnalysis() && onOffVal)
1898     {
1899         throw data_error("Cannot analyze the region gamma during a Bayesian analysis.");
1900     }
1901     if (GetConstUIVars().forces.GetForceOnOff(force_GROW) && onOffVal)
1902     {
1903         throw data_error("Cannot analyze the region gamma if you are simultaneously estimating the growth rate.");
1904         return;
1905     }
1906     UIVarsSingleForce::SetOnOff(onOffVal);
1907 }
1908 
1909 bool
AreZeroesValid() const1910 UIVarsRegionGammaForce::AreZeroesValid() const
1911 {
1912     if (!GetParamstatus(0).Valid())
1913         return false;
1914     if (GetStartValue(0) == 0.0)
1915         return false;
1916 
1917     return true;
1918 }
1919 
1920 //------------------------------------------------------------------------------------
1921 
UIVarsGrowForce(UIVars * myUIVars,long int numCrossPartitions)1922 UIVarsGrowForce::UIVarsGrowForce(UIVars * myUIVars, long int numCrossPartitions)
1923     :
1924     UIVarsSingleForce(
1925         myUIVars,
1926         force_GROW,
1927         numCrossPartitions,
1928         defaults::growth,
1929         defaults::growMethod,
1930         true,                   // growth force always legal to turn on
1931         false,                  // growth force not required when possible
1932         defaults::growEvents,
1933         UIVarsPrior(myUIVars->GetUI(),
1934                     force_GROW,
1935                     defaults::priortypeGrowth,
1936 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
1937                     defaults::samplingRate,
1938 #endif
1939                     defaults::lowerboundGrowth,
1940                     defaults::upperboundGrowth)
1941         ),
1942     growthType(defaults::growType)
1943 {
1944 }
1945 
UIVarsGrowForce(UIVars * myUIVars,const UIVarsGrowForce & growForce)1946 UIVarsGrowForce::UIVarsGrowForce(UIVars * myUIVars, const UIVarsGrowForce& growForce)
1947     :
1948     UIVarsSingleForce(myUIVars,growForce),
1949     growthType(growForce.growthType)
1950 {
1951 }
1952 
1953 bool
AreZeroesValid() const1954 UIVarsGrowForce::AreZeroesValid() const
1955 {
1956     //Any growth can be zero; even up to all of them.
1957     return true;
1958 }
1959 
1960 // We don't currently have any STAIRSTEP models, so the case statement
1961 // is probably wrong for when we have them... Jon 2006/09/15
1962 growth_scheme
GetGrowthScheme() const1963 UIVarsGrowForce::GetGrowthScheme() const
1964 {
1965     switch(growthType)
1966     {
1967         case growth_CURVE:
1968             return growth_EXP;
1969             break;
1970         case growth_STICK:  // not sure what this case is, assuming
1971             // that we can use the same as STICKEXP for
1972             // now
1973         case growth_STICKEXP:
1974             return growth_EXP;
1975             break;
1976     }
1977     return growth_EXP;
1978 }
1979 
1980 void
SetGrowthScheme(growth_scheme g)1981 UIVarsGrowForce::SetGrowthScheme(growth_scheme g)
1982 {
1983     // this is currently a no-op, as soon as we get STAIRSTEP
1984     // we'll need something else, probably ickly complicated here
1985     // in order to account for interlocking nature with growth_type
1986     // management...refactor growth_type?  Jon 2006/09/15
1987 }
1988 
1989 force_type
GetPhase2Type(force_type f) const1990 UIVarsGrowForce::GetPhase2Type(force_type f) const
1991 {
1992     if (growthType == growth_STICKEXP) return force_EXPGROWSTICK;
1993 
1994     return f;
1995 }
1996 
1997 //LS NOTE:  Cannot have a parallel 'GetOnOff' for growth here that checks
1998 // whether gamma is on or off, because gamma checks if *growth* is on or off.
1999 // If you try it, you'll get an infinite loop.  Yes, this has been... verified.
2000 
SetOnOff(bool onOffVal)2001 void UIVarsGrowForce::SetOnOff(bool onOffVal)
2002 {
2003     if (GetConstUIVars().forces.GetForceOnOff(force_REGION_GAMMA))
2004     {
2005         throw data_error("Cannot estimate growth if you are simulataneously estimating the region gamma.");
2006         return;
2007     }
2008     UIVarsSingleForce::SetOnOff(onOffVal);
2009 }
2010 
2011 //-------------------------------------------------------------
2012 
UIVarsLogisticSelectionForce(UIVars * myUIVars,long numCrossPartitions)2013 UIVarsLogisticSelectionForce::UIVarsLogisticSelectionForce
2014 (   UIVars * myUIVars, long numCrossPartitions)
2015     :
2016     UIVarsSingleForce(
2017         myUIVars,
2018         force_LOGISTICSELECTION,
2019         1, // there's only one selection coefficient
2020         defaults::logisticSelection,
2021         defaults::lselectMethod,
2022         true,                   // always legal to turn on
2023         false,                  // but it's not required
2024         defaults::lselectEvents,
2025         UIVarsPrior(myUIVars->GetUI(),
2026                     force_LOGISTICSELECTION,
2027                     defaults::priortypeLSelect,
2028 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
2029                     defaults::samplingRate,
2030 #endif
2031                     defaults::lowerboundLSelect,
2032                     defaults::upperboundLSelect)
2033         )
2034     ,selectionType(defaults::selectionType) // MCHECK major allele freq here?
2035 {
2036     if (2 != numCrossPartitions)
2037         m_canSetOnOff = false;
2038 }
2039 
UIVarsLogisticSelectionForce(UIVars * myUIVars,const UIVarsLogisticSelectionForce & logisticSelectionForce)2040 UIVarsLogisticSelectionForce::UIVarsLogisticSelectionForce(UIVars * myUIVars,
2041                                                            const UIVarsLogisticSelectionForce& logisticSelectionForce) :
2042     UIVarsSingleForce(myUIVars, logisticSelectionForce)
2043 {
2044 }
2045 
2046 bool
AreZeroesValid() const2047 UIVarsLogisticSelectionForce::AreZeroesValid() const
2048 {
2049     // Sure; zero means selection isn't acting.
2050     return true;
2051 }
2052 
2053 force_type
GetPhase2Type(force_type f) const2054 UIVarsLogisticSelectionForce::GetPhase2Type(force_type f) const
2055 {
2056     if (selectionType == selection_STOCHASTIC) return force_LOGSELECTSTICK;
2057 
2058     return f;
2059 }
2060 
2061 //-------------------------------------------------------------
2062 
2063 bool
operator ()(force_type ft) const2064 UIVarsForces::IsInactive::operator()(force_type ft) const
2065 {
2066     const UIVarsSingleForce & theForce
2067         = m_vars_forces.getForceRegardlessOfLegality(ft);
2068     bool isInactive = !(theForce.GetOnOff());
2069     return isInactive;
2070 }
2071 
IsInactive(const UIVarsForces & vars_forces)2072 UIVarsForces::IsInactive::IsInactive(const UIVarsForces& vars_forces)
2073     : m_vars_forces(vars_forces)
2074 {
2075 }
2076 
~IsInactive()2077 UIVarsForces::IsInactive::~IsInactive()
2078 {
2079 }
2080 
2081 bool
operator ()(force_type ft) const2082 UIVarsForces::IsIllegal::operator()(force_type ft) const
2083 {
2084     const UIVarsSingleForce & theForce
2085         = m_vars_forces.getForceRegardlessOfLegality(ft);
2086     bool isIllegal = (!theForce.GetLegal());
2087     return isIllegal;
2088 }
2089 
IsIllegal(const UIVarsForces & vars_forces)2090 UIVarsForces::IsIllegal::IsIllegal(const UIVarsForces& vars_forces)
2091     : m_vars_forces(vars_forces)
2092 {
2093 }
2094 
~IsIllegal()2095 UIVarsForces::IsIllegal::~IsIllegal()
2096 {
2097 }
2098 
UIVarsForces(UIVars * myUIVars,long int nCrossPartitions,long int nMigPopulations,long int nDivPopulations,long int nDiseaseStates,bool canMeasureRecombination)2099 UIVarsForces::UIVarsForces(UIVars * myUIVars,long int nCrossPartitions, long int nMigPopulations,
2100                            long int nDivPopulations, long int nDiseaseStates,bool canMeasureRecombination)
2101     :
2102     UIVarsComponent(myUIVars),
2103     coalForce(myUIVars,nCrossPartitions),
2104     diseaseForce(myUIVars,nDiseaseStates,(nDiseaseStates >= 2)),
2105     growForce(myUIVars,nCrossPartitions),
2106     migForce(myUIVars,nMigPopulations,(nMigPopulations >= 2)),
2107     divMigForce(myUIVars,nDivPopulations,(nDivPopulations > 2)),
2108     divForce(myUIVars,nDivPopulations),   // yes, integer division with truncation is desired
2109     recForce(myUIVars,canMeasureRecombination),
2110     regionGammaForce(myUIVars),
2111     logisticSelectionForce(myUIVars,nCrossPartitions)
2112 {
2113     //requires that both datapackplus and datamodel be set up in uivars.
2114     FillCalculatedStartValues();
2115 }
2116 
UIVarsForces(UIVars * myUIVars,const UIVarsForces & forcesRef)2117 UIVarsForces::UIVarsForces(UIVars * myUIVars, const UIVarsForces& forcesRef)
2118     :
2119     UIVarsComponent(myUIVars),
2120     coalForce(myUIVars,forcesRef.coalForce),
2121     diseaseForce(myUIVars,forcesRef.diseaseForce),
2122     growForce(myUIVars,forcesRef.growForce),
2123     migForce(myUIVars,forcesRef.migForce),
2124     divMigForce(myUIVars,forcesRef.divMigForce),
2125     divForce(myUIVars,forcesRef.divForce),
2126     recForce(myUIVars,forcesRef.recForce),
2127     regionGammaForce(myUIVars,forcesRef.regionGammaForce),
2128     logisticSelectionForce(myUIVars,forcesRef.logisticSelectionForce)
2129 {
2130 }
2131 
~UIVarsForces()2132 UIVarsForces::~UIVarsForces()
2133 {
2134 }
2135 
2136 void
FillCalculatedStartValues()2137 UIVarsForces::FillCalculatedStartValues()
2138 {
2139     coalForce.FillCalculatedStartValues();
2140     migForce.FillCalculatedStartValues();
2141 }
2142 
GetForceSizes() const2143 LongVec1d UIVarsForces::GetForceSizes() const
2144 {
2145     LongVec1d retVec;
2146     vector<force_type> forces = GetActiveForces();
2147     for (unsigned long int fnum = 0; fnum < forces.size(); fnum++)
2148     {
2149         retVec.push_back(getLegalForce(forces[fnum]).GetNumParameters());
2150     }
2151     return retVec;
2152 }
2153 
2154 ForceTypeVec1d
GetActiveForces() const2155 UIVarsForces::GetActiveForces() const
2156 {
2157     ForceTypeVec1d returnVec = GetLegalForces();
2158     returnVec.erase(
2159         std::remove_if(returnVec.begin(),returnVec.end(),IsInactive(*this)),
2160         returnVec.end());
2161     return returnVec;
2162 }
2163 
2164 ForceTypeVec1d
GetPhase2ActiveForces() const2165 UIVarsForces::GetPhase2ActiveForces() const
2166 {
2167     ForceTypeVec1d tempVec = GetActiveForces();
2168     ForceTypeVec1d returnVec;
2169     for (unsigned long fnum=0; fnum<tempVec.size(); fnum++)
2170     {
2171         returnVec.push_back(getLegalForce(tempVec[fnum]).GetPhase2Type(tempVec[fnum]));
2172     }
2173     return returnVec;
2174 }
2175 
2176 ForceTypeVec1d
GetLegalForces() const2177 UIVarsForces::GetLegalForces() const
2178 {
2179     ForceTypeVec1d returnVec = GetPossibleForces();
2180     returnVec.erase(
2181         std::remove_if(returnVec.begin(),returnVec.end(),IsIllegal(*this)),
2182         returnVec.end());
2183     return returnVec;
2184 }
2185 
2186 ForceTypeVec1d
GetPossibleForces() const2187 UIVarsForces::GetPossibleForces() const
2188 {
2189     //This is where the so-called 'canonical order' of forces in LAMARC
2190     // gets set up.  If we add a new force, add it here appropriately.
2191     ForceTypeVec1d returnVec;
2192     returnVec.push_back(force_COAL);
2193     returnVec.push_back(force_MIG);
2194     returnVec.push_back(force_DIVMIG);
2195     returnVec.push_back(force_DISEASE);
2196     returnVec.push_back(force_REC);
2197     returnVec.push_back(force_GROW);
2198     returnVec.push_back(force_DIVERGENCE);
2199     returnVec.push_back(force_LOGISTICSELECTION);
2200     returnVec.push_back(force_REGION_GAMMA);
2201     return returnVec;
2202 }
2203 
GetNumGroups(force_type ftype) const2204 long int UIVarsForces::GetNumGroups(force_type ftype) const
2205 {
2206     return getLegalForce(ftype).GetNumGroups();
2207 }
2208 
ParamInGroup(force_type ftype,long int pindex) const2209 long int UIVarsForces::ParamInGroup(force_type ftype, long int pindex) const
2210 {
2211     return getLegalForce(ftype).ParamInGroup(pindex);
2212 }
2213 
2214 bool
GetForceCanTurnOnOff(force_type ftype) const2215 UIVarsForces::GetForceCanTurnOnOff(force_type ftype) const
2216 {
2217     const UIVarsSingleForce & thisForce = getForceRegardlessOfLegality(ftype);
2218     return thisForce.GetCanSetOnOff();
2219 }
2220 
2221 bool
GetForceLegal(force_type ftype) const2222 UIVarsForces::GetForceLegal(force_type ftype) const
2223 {
2224     const UIVarsSingleForce & thisForce = getForceRegardlessOfLegality(ftype);
2225     return thisForce.GetLegal();
2226 }
2227 
2228 bool
GetForceZeroesValidity(force_type ftype) const2229 UIVarsForces::GetForceZeroesValidity(force_type ftype) const
2230 {
2231     const UIVarsSingleForce & thisForce = getForceRegardlessOfLegality(ftype);
2232     return thisForce.AreZeroesValid();
2233 }
2234 
2235 void
FixGroups(force_type ftype)2236 UIVarsForces::FixGroups(force_type ftype)
2237 {
2238     UIVarsSingleForce & thisForce = getLegalForce(ftype);
2239     thisForce.FixGroups();
2240 }
2241 
2242 const UIVarsSingleForce &
getLegalForce(force_type ftype) const2243 UIVarsForces::getLegalForce(force_type ftype) const
2244 {
2245     // if you change this method, make sure you change the
2246     // non-const version and getForceRegardlessOfLegality too!!
2247     switch(ftype)
2248     {
2249         case force_COAL:
2250             assert(coalForce.GetLegal());
2251             return coalForce;
2252             break;
2253         case force_MIG:
2254             assert(migForce.GetLegal());
2255             return migForce;
2256             break;
2257         case force_DIVMIG:
2258             assert(divMigForce.GetLegal());
2259             return divMigForce;
2260             break;
2261         case force_EXPGROWSTICK:
2262         case force_GROW:
2263             assert(growForce.GetLegal());
2264             return growForce;
2265             break;
2266         case force_REC:
2267             assert(recForce.GetLegal());
2268             return recForce;
2269             break;
2270         case force_DISEASE:
2271             assert(diseaseForce.GetLegal());
2272             return diseaseForce;
2273             break;
2274         case force_LOGSELECTSTICK:
2275         case force_LOGISTICSELECTION:
2276             assert(logisticSelectionForce.GetLegal());
2277             return logisticSelectionForce;
2278             break;
2279         case force_REGION_GAMMA:
2280             assert(regionGammaForce.GetLegal());
2281             return regionGammaForce;
2282             break;
2283         case force_DIVERGENCE:
2284             assert(divForce.GetLegal());
2285             return divForce;
2286             break;
2287         default:
2288             assert(false);              //Uncaught force type.
2289     }
2290     throw implementation_error("UIVarsForces::getLegalForce(force_type) given an unknown force type.");
2291 }
2292 
2293 UIVarsSingleForce &
getLegalForce(force_type ftype)2294 UIVarsForces::getLegalForce(force_type ftype)
2295 {
2296     // if you change this method, make sure you change the
2297     // const version and getForceRegardlessOfLegality too!!
2298     switch(ftype)
2299     {
2300         case force_COAL:
2301             assert(coalForce.GetLegal());
2302             return coalForce;
2303             break;
2304         case force_MIG:
2305             assert(migForce.GetLegal());
2306             return migForce;
2307             break;
2308         case force_DIVMIG:
2309             assert(divMigForce.GetLegal());
2310             return divMigForce;
2311             break;
2312         case force_EXPGROWSTICK:
2313         case force_GROW:
2314             assert(growForce.GetLegal());
2315             return growForce;
2316             break;
2317         case force_REC:
2318             assert(recForce.GetLegal());
2319             return recForce;
2320             break;
2321         case force_DISEASE:
2322             assert(diseaseForce.GetLegal());
2323             return diseaseForce;
2324             break;
2325         case force_LOGSELECTSTICK:
2326         case force_LOGISTICSELECTION:
2327             assert(logisticSelectionForce.GetLegal());
2328             return logisticSelectionForce;
2329             break;
2330         case force_REGION_GAMMA:
2331             assert(regionGammaForce.GetLegal());
2332             return regionGammaForce;
2333             break;
2334         case force_DIVERGENCE:
2335             assert(divForce.GetLegal());
2336             return divForce;
2337             break;
2338         default:
2339             assert(false);              //Uncaught force type.
2340     }
2341     throw implementation_error("UIVarsForces::getLegalForce(force_type) given an unknown force type.");
2342 }
2343 
2344 const UIVarsSingleForce &
getForceRegardlessOfLegality(force_type ftype) const2345 UIVarsForces::getForceRegardlessOfLegality(force_type ftype) const
2346 {
2347     // if you change this method, make sure you change the
2348     // const and non-const versions of getLegalForce
2349     switch(ftype)
2350     {
2351         case force_COAL:
2352             return coalForce;
2353             break;
2354         case force_MIG:
2355             return migForce;
2356             break;
2357         case force_DIVMIG:
2358             return divMigForce;
2359             break;
2360         case force_EXPGROWSTICK:
2361         case force_GROW:
2362             return growForce;
2363             break;
2364         case force_REC:
2365             return recForce;
2366             break;
2367         case force_DISEASE:
2368             return diseaseForce;
2369             break;
2370         case force_LOGSELECTSTICK:
2371         case force_LOGISTICSELECTION:
2372             return logisticSelectionForce;
2373             break;
2374         case force_REGION_GAMMA:
2375             return regionGammaForce;
2376             break;
2377         case force_DIVERGENCE:
2378             return divForce;
2379             break;
2380         default:
2381             assert(false);              //Uncaught force type.
2382     }
2383     throw implementation_error("UIVarsForces::getForceRegardlessOfLegality(force_type) given an unknown force type.");
2384 }
2385 
2386 long int
GetNumParameters(force_type force) const2387 UIVarsForces::GetNumParameters(force_type force) const
2388 {
2389     return getLegalForce(force).GetNumParameters();
2390 }
2391 
2392 bool
GetForceOnOff(force_type force) const2393 UIVarsForces::GetForceOnOff   (force_type force) const
2394 {
2395     const UIVarsSingleForce & thisForce = getForceRegardlessOfLegality(force);
2396     return thisForce.GetOnOff();
2397 }
2398 
2399 long int
GetMaxEvents(force_type force) const2400 UIVarsForces::GetMaxEvents    (force_type force) const
2401 {
2402     return getLegalForce(force).GetMaxEvents();
2403 }
2404 
2405 proftype
GetProfileType(force_type force) const2406 UIVarsForces::GetProfileType  (force_type force) const
2407 {
2408     return getLegalForce(force).GetProfileType();
2409 }
2410 
2411 proftype
GetProfileType(force_type force,long int id) const2412 UIVarsForces::GetProfileType    (force_type force, long int id) const
2413 {
2414     return getLegalForce(force).GetProfileType(id);
2415 }
2416 
2417 string
GetProfileTypeSummaryDescription(force_type force) const2418 UIVarsForces::GetProfileTypeSummaryDescription(force_type force)  const
2419 {
2420     return getLegalForce(force).GetProfileTypeSummaryDescription();
2421 }
2422 
2423 ParamStatus
GetParamstatus(force_type force,long int id) const2424 UIVarsForces::GetParamstatus  (force_type force, long int id) const
2425 {
2426     if (id == uiconst::GLOBAL_ID)
2427     {
2428         //LS NOTE:  This is called this way from uiParameter::Min and ::Max in force_interface.cpp
2429         return ParamStatus(pstat_unconstrained);
2430     }
2431     return getLegalForce(force).GetParamstatus(id);
2432 }
2433 
2434 ParamStatus
GetGroupParamstatus(force_type force,long int id) const2435 UIVarsForces::GetGroupParamstatus (force_type force, long int id) const
2436 {
2437     return getLegalForce(force).GetGroupParamstatus(id);
2438 }
2439 
2440 LongVec1d
GetGroupParamList(force_type force,long int id) const2441 UIVarsForces::GetGroupParamList (force_type force, long int id) const
2442 {
2443     return getLegalForce(force).GetGroupParamList(id);
2444 }
2445 
2446 // MFIX This looked bad in merge; functions GetIdentGroups and GetMultGroups may
2447 // not be functional or correct.
2448 // JDEBUG -- this is a short term kludge to get something/anything in,
2449 // it is wrong WRONG wrong!
2450 vector<ParamGroup>
GetIdentGroups(force_type force) const2451 UIVarsForces::GetIdentGroups (force_type force) const
2452 {
2453     return getLegalForce(force).GetGroups();
2454 }
2455 
2456 // JDEBUG -- this is a short term kludge to get something/anything in,
2457 // it is wrong WRONG wrong!
2458 vector<ParamGroup>
GetMultGroups(force_type force) const2459 UIVarsForces::GetMultGroups (force_type force) const
2460 {
2461     return getLegalForce(force).GetGroups();
2462 }
2463 
2464 double
GetStartValue(force_type force,long int id) const2465 UIVarsForces::GetStartValue   (force_type force, long int id) const
2466 {
2467     return getLegalForce(force).GetStartValue(id);
2468 }
2469 
2470 double
GetTrueValue(force_type force,long int id) const2471 UIVarsForces::GetTrueValue   (force_type force, long int id) const
2472 {
2473     return getLegalForce(force).GetTrueValue(id);
2474 }
2475 
2476 force_type
GetPhase2Type(force_type force) const2477 UIVarsForces::GetPhase2Type   (force_type force) const
2478 {
2479     return getLegalForce(force).GetPhase2Type(force);
2480 }
2481 
2482 method_type
GetStartMethod(force_type force,long int id) const2483 UIVarsForces::GetStartMethod  (force_type force, long int id) const
2484 {
2485     return getLegalForce(force).GetStartMethod(id);
2486 }
2487 
2488 DoubleVec1d
GetStartValues(force_type force) const2489 UIVarsForces::GetStartValues (force_type force) const
2490 {
2491     return getLegalForce(force).GetStartValues();
2492 }
2493 
2494 long int
GetDiseaseLocation() const2495 UIVarsForces::GetDiseaseLocation() const
2496 {
2497     assert(diseaseForce.GetLegal());
2498     return diseaseForce.GetLocation();
2499 }
2500 
2501 growth_type
GetGrowthType() const2502 UIVarsForces::GetGrowthType() const
2503 {
2504     return growForce.GetGrowthType();
2505 }
2506 
2507 growth_scheme
GetGrowthScheme() const2508 UIVarsForces::GetGrowthScheme() const
2509 {
2510     return growForce.GetGrowthScheme();
2511 }
2512 
2513 bool
GetDoProfile(force_type force,long int id) const2514 UIVarsForces::GetDoProfile(force_type force, long int id) const
2515 {
2516     return getLegalForce(force).GetDoProfile(id);
2517 }
2518 
2519 bool
GetParamValid(force_type force,long int id) const2520 UIVarsForces::GetParamValid(force_type force, long int id) const
2521 {
2522     return getLegalForce(force).GetParamValid(id);
2523 }
2524 
2525 bool
GetParamUnique(force_type force,long int id) const2526 UIVarsForces::GetParamUnique(force_type force, long int id) const
2527 {
2528     return getLegalForce(force).GetParamUnique(id);
2529 }
2530 
2531 //Getters/setters for Bayesian information
GetPrior(force_type force,long int pindex) const2532 const UIVarsPrior& UIVarsForces::GetPrior(force_type force, long int pindex) const
2533 {
2534     if (pindex == uiconst::GLOBAL_ID)
2535     {
2536         return getLegalForce(force).GetDefaultPrior();
2537     }
2538     return getLegalForce(force).GetPrior(pindex);
2539 }
2540 
GetDefaultPrior(force_type force) const2541 const UIVarsPrior& UIVarsForces::GetDefaultPrior(force_type force) const
2542 {
2543     return getLegalForce(force).GetDefaultPrior();
2544 }
2545 
GetUseDefaultPrior(force_type force,long int pindex) const2546 bool UIVarsForces::GetUseDefaultPrior(force_type force, long int pindex) const
2547 {
2548     return getLegalForce(force).GetUseDefaultPrior(pindex);
2549 }
2550 
GetPriorType(force_type force,long int pindex) const2551 priortype UIVarsForces::GetPriorType(force_type force, long int pindex) const
2552 {
2553     if (pindex == uiconst::GLOBAL_ID)
2554     {
2555         return getLegalForce(force).GetDefaultPriorType();
2556     }
2557     return getLegalForce(force).GetPriorType(pindex);
2558 }
2559 
GetLowerBound(force_type force,long int pindex) const2560 double    UIVarsForces::GetLowerBound(force_type force, long int pindex) const
2561 {
2562     if (pindex == uiconst::GLOBAL_ID)
2563     {
2564         return getLegalForce(force).GetDefaultLowerBound();
2565     }
2566     return getLegalForce(force).GetLowerBound(pindex);
2567 }
2568 
2569 selection_type
GetSelectionType() const2570 UIVarsForces::GetSelectionType() const
2571 {
2572     return logisticSelectionForce.GetSelectionType();
2573 }
2574 
GetUpperBound(force_type force,long int pindex) const2575 double    UIVarsForces::GetUpperBound(force_type force, long int pindex) const
2576 {
2577     if (pindex == uiconst::GLOBAL_ID)
2578     {
2579         return getLegalForce(force).GetDefaultUpperBound();
2580     }
2581     return getLegalForce(force).GetUpperBound(pindex);
2582 }
2583 
2584 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
GetRelativeSampling(force_type force,long int pindex) const2585 long    UIVarsForces::GetRelativeSampling(force_type force, long int pindex) const
2586 {
2587     if (pindex == uiconst::GLOBAL_ID)
2588     {
2589         return getLegalForce(force).GetDefaultRelativeSampling();
2590     }
2591     return getLegalForce(force).GetRelativeSampling(pindex);
2592 }
2593 #endif
2594 
SetUseDefaultPrior(bool use,force_type force,long int pindex)2595 void UIVarsForces::SetUseDefaultPrior(bool use, force_type force, long int pindex)
2596 {
2597     getLegalForce(force).SetUseDefaultPrior(use, pindex);
2598 }
2599 
SetUseDefaultPriorsForForce(force_type force)2600 void UIVarsForces::SetUseDefaultPriorsForForce(force_type force)
2601 {
2602     getLegalForce(force).SetUseAllDefaultPriors();
2603 }
2604 
SetPriorType(priortype ptype,force_type force,long int pindex)2605 void UIVarsForces::SetPriorType(priortype ptype, force_type force, long int pindex)
2606 {
2607     if (pindex == uiconst::GLOBAL_ID)
2608     {
2609         getLegalForce(force).SetDefaultPriorType(ptype);
2610     }
2611     else getLegalForce(force).SetPriorType(ptype, pindex);
2612 }
2613 
2614 #ifdef LAMARC_NEW_FEATURE_RELATIVE_SAMPLING
SetRelativeSampling(long rate,force_type force,long int pindex)2615 void UIVarsForces::SetRelativeSampling(long rate, force_type force, long int pindex)
2616 {
2617     if (pindex == uiconst::GLOBAL_ID)
2618     {
2619         getLegalForce(force).SetDefaultRelativeSampling(rate);
2620     }
2621     else getLegalForce(force).SetRelativeSampling(rate, pindex);
2622 }
2623 #endif
2624 
2625 
SetLowerBound(double bound,force_type force,long int pindex)2626 void UIVarsForces::SetLowerBound(double bound, force_type force, long int pindex)
2627 {
2628     if (pindex == uiconst::GLOBAL_ID)
2629     {
2630         getLegalForce(force).SetDefaultLowerBound(bound);
2631     }
2632     else getLegalForce(force).SetLowerBound(bound, pindex);
2633 }
2634 
SetUpperBound(double bound,force_type force,long int pindex)2635 void UIVarsForces::SetUpperBound(double bound, force_type force, long int pindex)
2636 {
2637     if (pindex == uiconst::GLOBAL_ID)
2638     {
2639         getLegalForce(force).SetDefaultUpperBound(bound);
2640     }
2641     else getLegalForce(force).SetUpperBound(bound, pindex);
2642 }
2643 
GetPriorTypeSummaryDescription(force_type force) const2644 string UIVarsForces::GetPriorTypeSummaryDescription(force_type force) const
2645 {
2646     return getLegalForce(force).GetPriorTypeSummaryDescription();
2647 }
2648 
GetPriorTypeSummaryDescription(force_type force,long int pindex,bool sayDefault) const2649 string UIVarsForces::GetPriorTypeSummaryDescription(force_type force, long int pindex, bool sayDefault) const
2650 {
2651     if (pindex != uiconst::GLOBAL_ID)
2652     {
2653         ParamStatus mystatus = getLegalForce(force).GetParamstatus(pindex);
2654         if (!mystatus.Inferred()) return "<" + ToString(mystatus.Status()) + ">";
2655         // otherwise do the stuff below
2656     }
2657     string desc = getLegalForce(force).GetPrior(pindex).GetSummaryDescription();
2658     if (pindex != uiconst::GLOBAL_ID)
2659     {
2660         if (sayDefault)
2661         {
2662             if (getLegalForce(force).GetUseDefaultPrior(pindex))
2663             {
2664                 desc = "<default>";
2665             }
2666         }
2667     }
2668     return desc;
2669 }
2670 
2671 void
SetForceOnOff(bool onOffVal,force_type force)2672 UIVarsForces::SetForceOnOff  (bool onOffVal, force_type force)
2673 {
2674     if(GetForceCanTurnOnOff(force))
2675     {
2676         return getLegalForce(force).SetOnOff(onOffVal);
2677     }
2678     else
2679     {
2680         if (onOffVal != GetForceOnOff(force))
2681         {
2682             assert(false);
2683             string msg;
2684             msg = "Unable to turn ";
2685             if (onOffVal)
2686             {
2687                 msg += "on";
2688             }
2689             else
2690             {
2691                 msg += "off";
2692             }
2693             msg += " the force " + ToString(force)
2694                 + " for this dataset.  Try removing the force entirely from the "
2695                 "XML input file.";
2696             throw data_error(msg);
2697         }
2698     }
2699 }
2700 
2701 void
SetMaxEvents(long int maxEvents,force_type force)2702 UIVarsForces::SetMaxEvents   (long int maxEvents,    force_type force)
2703 {
2704     return getLegalForce(force).SetMaxEvents(maxEvents);
2705 }
2706 
2707 void
SetProfileType(proftype ptype,force_type force)2708 UIVarsForces::SetProfileType (proftype ptype,    force_type force)
2709 {
2710     return getLegalForce(force).SetProfileType(ptype);
2711 }
2712 
2713 void
SetProfileType(proftype ptype)2714 UIVarsForces::SetProfileType (proftype ptype)
2715 {
2716     // OK, so it's pretty weird to do this for all of the
2717     // forces, since some of them will not be legal, but
2718     // hey, if we're never accessing them, we can certainly
2719     // write to them, huh?
2720     coalForce.SetProfileType(ptype);
2721     diseaseForce.SetProfileType(ptype);
2722     growForce.SetProfileType(ptype);
2723     migForce.SetProfileType(ptype);
2724     recForce.SetProfileType(ptype);
2725     logisticSelectionForce.SetProfileType(ptype);
2726     regionGammaForce.SetProfileType(ptype);
2727 }
2728 
2729 void
SetDoProfile(bool doProfile,force_type force,long int id)2730 UIVarsForces::SetDoProfile   (bool doProfile,    force_type force, long int id)
2731 {
2732     getLegalForce(force).SetDoProfile(doProfile,id);
2733 }
2734 
2735 void
SetDoProfile(bool doProfile,force_type force)2736 UIVarsForces::SetDoProfile   (bool doProfile,    force_type force)
2737 {
2738     getLegalForce(force).SetDoProfile(doProfile);
2739 }
2740 
2741 void
SetDoProfile(bool doProfile)2742 UIVarsForces::SetDoProfile   (bool doProfile)
2743 {
2744     // OK, so it's pretty wierd to do this for all of the
2745     // forces, since some of them will not be legal, but
2746     // hey, if we're never accessing them, we can certainly
2747     // write to them, huh?
2748     coalForce.SetDoProfile(doProfile);
2749     diseaseForce.SetDoProfile(doProfile);
2750     growForce.SetDoProfile(doProfile);
2751     migForce.SetDoProfile(doProfile);
2752     recForce.SetDoProfile(doProfile);
2753     logisticSelectionForce.SetDoProfile(doProfile);
2754     regionGammaForce.SetDoProfile(doProfile);
2755 }
2756 
2757 void
SetStartMethod(method_type meth,force_type ftype,long int id)2758 UIVarsForces::SetStartMethod(method_type meth, force_type ftype, long int id)
2759 {
2760     getLegalForce(ftype).SetStartMethod(meth,id);
2761 }
2762 
2763 void
SetParamstatus(const ParamStatus & mystatus,force_type ftype,long int id)2764 UIVarsForces::SetParamstatus (const ParamStatus& mystatus, force_type ftype, long int id)
2765 {
2766     getLegalForce(ftype).SetParamstatus(mystatus,id);
2767 }
2768 
2769 void
SetGroupParamstatus(ParamStatus pstat,force_type ftype,long int id)2770 UIVarsForces::SetGroupParamstatus (ParamStatus pstat, force_type ftype, long int id)
2771 {
2772     getLegalForce(ftype).SetGroupParamstatus(pstat,id);
2773 }
2774 
2775 void
AddGroup(LongVec1d params,force_type ftype,long int id)2776 UIVarsForces::AddGroup (LongVec1d params, force_type ftype, long int id)
2777 {
2778     getLegalForce(ftype).AddGroup(defaults::groupPstat, params);
2779 }
2780 
2781 void
RemoveParamFromGroup(force_type ftype,long int id)2782 UIVarsForces::RemoveParamFromGroup(force_type ftype, long int id)
2783 {
2784     getLegalForce(ftype).RemoveParamIfInAGroup(id);
2785 }
2786 
2787 void
AddParamToGroup(force_type ftype,long int pindex,long int gindex)2788 UIVarsForces::AddParamToGroup(force_type ftype, long int pindex, long int gindex)
2789 {
2790     getLegalForce(ftype).AddParamToGroup(pindex, gindex);
2791 }
2792 
2793 void
AddParamToNewGroup(force_type ftype,long int pindex)2794 UIVarsForces::AddParamToNewGroup(force_type ftype, long int pindex)
2795 {
2796     getLegalForce(ftype).AddParamToNewGroup(pindex);
2797 }
2798 
2799 void
SetUserStartValue(double startValue,force_type ftype,long int id)2800 UIVarsForces::SetUserStartValue(double startValue, force_type ftype, long int id)
2801 {
2802     getLegalForce(ftype).SetUserStartValue(startValue,id);
2803 }
2804 
2805 void
SetTrueValue(double startValue,force_type ftype,long int id)2806 UIVarsForces::SetTrueValue(double startValue, force_type ftype, long int id)
2807 {
2808     getLegalForce(ftype).SetTrueValue(startValue,id);
2809 }
2810 
2811 void
SetAllThetaStartValues(double startValue)2812 UIVarsForces::SetAllThetaStartValues(double startValue)
2813 {
2814     getLegalForce(force_COAL).SetUserStartValues(startValue);
2815 }
2816 
2817 void
SetAllThetaStartValuesFST()2818 UIVarsForces::SetAllThetaStartValuesFST()
2819 {
2820     getLegalForce(force_COAL).SetStartMethods(method_FST);
2821 }
2822 
2823 void
SetAllThetaStartValuesWatterson()2824 UIVarsForces::SetAllThetaStartValuesWatterson()
2825 {
2826     getLegalForce(force_COAL).SetStartMethods(method_WATTERSON);
2827 }
2828 
2829 void
SetThetaStartValue(double startValue,long int id)2830 UIVarsForces::SetThetaStartValue  (double startValue, long int id)
2831 {
2832     getLegalForce(force_COAL).SetUserStartValue(startValue,id);
2833 }
2834 
2835 void
SetAllMigrationStartValues(double startValue)2836 UIVarsForces::SetAllMigrationStartValues(double startValue)
2837 {
2838     getLegalForce(force_MIG).SetUserStartValues(startValue);
2839 }
2840 
2841 void
SetAllMigrationStartValuesFST()2842 UIVarsForces::SetAllMigrationStartValuesFST()
2843 {
2844     getLegalForce(force_MIG).SetStartMethods(method_FST);
2845 }
2846 
2847 void
SetMigrationStartValue(double startValue,long int id)2848 UIVarsForces::SetMigrationStartValue  (double startValue, long int id)
2849 {
2850     getLegalForce(force_MIG).SetUserStartValue(startValue,id);
2851 }
2852 
2853 void
SetDivergenceEpochStartTime(double startValue,long int id)2854 UIVarsForces::SetDivergenceEpochStartTime  (double startValue, long int id)
2855 {
2856     getLegalForce(force_DIVERGENCE).SetUserStartValue(startValue,id);
2857 }
2858 
2859 void
SetAllDivMigrationStartValues(double startValue)2860 UIVarsForces::SetAllDivMigrationStartValues(double startValue)
2861 {
2862     getLegalForce(force_DIVMIG).SetUserStartValues(startValue);
2863 }
2864 
2865 #if 0 // JREMOVE, JDEBUG, passes testing then remove this function
2866 void
2867 UIVarsForces::SetAllDivMigrationStartValuesFST()
2868 {
2869     assert(false);
2870     getLegalForce(force_DIVMIG).SetStartMethods(method_FST);
2871 }
2872 #endif
2873 
2874 void
SetDivMigrationStartValue(double startValue,long int id)2875 UIVarsForces::SetDivMigrationStartValue  (double startValue, long int id)
2876 {
2877     getLegalForce(force_DIVMIG).SetUserStartValue(startValue,id);
2878 }
2879 
2880 void
SetAllDiseaseStartValues(double startValue)2881 UIVarsForces::SetAllDiseaseStartValues(double startValue)
2882 {
2883     getLegalForce(force_DISEASE).SetUserStartValues(startValue);
2884 }
2885 
2886 void
SetDiseaseStartValue(double startValue,long int id)2887 UIVarsForces::SetDiseaseStartValue(double startValue, long int id)
2888 {
2889     getLegalForce(force_DISEASE).SetUserStartValue(startValue,id);
2890 }
2891 
2892 void
SetAllGrowthStartValues(double startValue)2893 UIVarsForces::SetAllGrowthStartValues(double startValue)
2894 {
2895     getLegalForce(force_GROW).SetUserStartValues(startValue);
2896 }
2897 
2898 void
SetGrowthStartValue(double startValue,long int id)2899 UIVarsForces::SetGrowthStartValue(double startValue, long int id)
2900 {
2901     getLegalForce(force_GROW).SetUserStartValue(startValue,id);
2902 }
2903 
2904 void
SetGrowthType(growth_type gType)2905 UIVarsForces::SetGrowthType(growth_type gType)
2906 {
2907     growForce.SetGrowthType(gType);
2908 }
2909 
2910 void
SetGrowthScheme(growth_scheme gScheme)2911 UIVarsForces::SetGrowthScheme(growth_scheme gScheme)
2912 {
2913     growForce.SetGrowthScheme(gScheme);
2914 }
2915 
2916 void
SetRecombinationStartValue(double startValue)2917 UIVarsForces::SetRecombinationStartValue(double startValue)
2918 {
2919     getLegalForce(force_REC).SetUserStartValues(startValue);
2920 }
2921 
2922 void
SetLogisticSelectionCoefficientStartValue(double startValue)2923 UIVarsForces::SetLogisticSelectionCoefficientStartValue(double startValue)
2924 {
2925     getLegalForce(force_LOGISTICSELECTION).SetUserStartValues(startValue);
2926 }
2927 
2928 void
SetRegionGammaStartValue(double startValue)2929 UIVarsForces::SetRegionGammaStartValue(double startValue)
2930 {
2931     getLegalForce(force_REGION_GAMMA).SetUserStartValues(startValue);
2932 }
2933 
2934 void
SetSelectionType(selection_type sType)2935 UIVarsForces::SetSelectionType(selection_type sType)
2936 {
2937     logisticSelectionForce.SetSelectionType(sType);
2938 }
2939 
2940 void
SetDiseaseLocation(long int location)2941 UIVarsForces::SetDiseaseLocation(long int location)
2942 {
2943     assert(diseaseForce.GetLegal());
2944     diseaseForce.SetLocation(location);
2945 }
2946 
AreZeroesValid(force_type forceId)2947 bool UIVarsForces::AreZeroesValid(force_type forceId)
2948 {
2949     return getLegalForce(forceId).AreZeroesValid();
2950 }
2951 
SomeVariableParams() const2952 bool UIVarsForces::SomeVariableParams() const
2953 {
2954     vector<force_type> forces = GetActiveForces();
2955     for (unsigned long int fnum = 0; fnum < forces.size(); fnum++)
2956     {
2957         if (getLegalForce(forces[fnum]).SomeVariableParams())
2958         {
2959             return true;
2960         }
2961     }
2962     return false;
2963 }
2964 
GetEpochAncestorName(long id) const2965 std::string UIVarsForces::GetEpochAncestorName(long id) const
2966 {
2967     assert(divForce.GetLegal());
2968     std::vector<string>  names = divForce.GetAncestors();
2969     //std::vector<string> mine = names[id];
2970     std::string retval = names[id];
2971     return retval;
2972 }
2973 
GetEpochDescendentNames(long id) const2974 std::string UIVarsForces::GetEpochDescendentNames(long id) const
2975 {
2976     assert(divForce.GetLegal());
2977     std::vector< std::vector <string> > names = divForce.GetNewPops();
2978     std::vector<string> mine = names[id];
2979     std::string retval = mine[0] + " " + mine[1];
2980     return retval;
2981 }
2982 
2983 //____________________________________________________________________________________
2984