1 /*
2
3 HyPhy - Hypothesis Testing Using Phylogenies.
4
5 Copyright (C) 1997-now
6 Core Developers:
7 Sergei L Kosakovsky Pond (sergeilkp@icloud.com)
8 Art FY Poon (apoon42@uwo.ca)
9 Steven Weaver (sweaver@temple.edu)
10
11 Module Developers:
12 Lance Hepler (nlhepler@gmail.com)
13 Martin Smith (martin.audacis@gmail.com)
14
15 Significant contributions from:
16 Spencer V Muse (muse@stat.ncsu.edu)
17 Simon DW Frost (sdf22@cam.ac.uk)
18
19 Permission is hereby granted, free of charge, to any person obtaining a
20 copy of this software and associated documentation files (the
21 "Software"), to deal in the Software without restriction, including
22 without limitation the rights to use, copy, modify, merge, publish,
23 distribute, sublicense, and/or sell copies of the Software, and to
24 permit persons to whom the Software is furnished to do so, subject to
25 the following conditions:
26
27 The above copyright notice and this permission notice shall be included
28 in all copies or substantial portions of the Software.
29
30 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
31 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
33 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
34 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
35 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
36 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37
38 */
39
40 #include "defines.h"
41 #include "variablecontainer.h"
42 #include "operation.h"
43
44 #include "likefunc.h"
45 #include "parser.h"
46 #include "polynoml.h"
47 #include "batchlan.h"
48
49 #include "global_object_lists.h"
50 #include "global_things.h"
51
52 #include "function_templates.h"
53
54
55 using namespace hy_global;
56 using namespace hyphy_global_objects;
57
58
59 //__________________________________________________________________________________
60
_VariableContainer(void)61 _VariableContainer::_VariableContainer (void) : theParent(nil), theModel (-1L), iVariables(nil), dVariables(nil), gVariables(nil){
62 }
63
64 //__________________________________________________________________________________
65
Duplicate(BaseRefConst theO)66 void _VariableContainer::Duplicate (BaseRefConst theO) {
67 _Variable::Duplicate (theO);
68 _VariableContainer const *theVC = (_VariableContainer const*)theO;
69 theParent= theVC->theParent;
70 theModel = theVC->theModel;
71 if (theVC->iVariables) {
72 if (iVariables) {
73 iVariables->Clear();
74 } else {
75 iVariables = new _SimpleList;
76 }
77 iVariables->Duplicate (theVC->iVariables);
78 } else {
79 if (iVariables) {
80 delete (iVariables);
81 iVariables = nil;
82 }
83 }
84 if (theVC->dVariables) {
85 if (dVariables) {
86 dVariables->Clear();
87 } else {
88 dVariables = new _SimpleList;
89 }
90 dVariables->Duplicate (theVC->dVariables);
91 } else {
92 if (dVariables) {
93 delete (dVariables);
94 dVariables = nil;
95 }
96 }
97 if (theVC->gVariables) {
98 if (gVariables) {
99 gVariables->Clear();
100 } else {
101 gVariables = new _SimpleList;
102 }
103 gVariables->Duplicate (theVC->gVariables);
104 } else {
105 if (gVariables) {
106 delete (gVariables);
107 gVariables = nil;
108 }
109 }
110 }
111
112
113 //__________________________________________________________________________________
114
TrimMemory()115 void _VariableContainer::TrimMemory () {
116 _SimpleList* var_arrays [3] = {iVariables,dVariables,gVariables};
117 for (_SimpleList* an_array : var_arrays) {
118 if (an_array) {
119 an_array->TrimMemory();
120 }
121 }
122 }
123
124 //__________________________________________________________________________________
125
makeDynamic(void) const126 BaseRef _VariableContainer::makeDynamic (void) const {
127 _VariableContainer * res = new _VariableContainer;
128 res->Duplicate(this);
129 return res;
130 }
131
132 //__________________________________________________________________________________
133
toStr(unsigned long)134 BaseRef _VariableContainer::toStr (unsigned long) {
135 _StringBuffer * res = new _StringBuffer (128L);
136
137 (*res) << "Container Class:" << theName << ":{ Independent Variables:";
138
139 if (iVariables)
140 for (long i = 0L; i<iVariables->lLength; i+=2L) {
141 res->AppendNewInstance ((_String*)variablePtrs(iVariables->list_data[i])->toStr());
142
143 if (i<iVariables->lLength-2) {
144 (*res) << ',';
145 }
146
147 }
148
149 (*res) << "; Dependent Variables:";
150
151 if (dVariables)
152 for (long i2 = 0L; i2<dVariables->lLength; i2+=2L) {
153 res->AppendNewInstance ((_String*)variablePtrs(dVariables->list_data[i2])->toStr());
154 if (i2<dVariables->lLength-2) {
155 (*res) << ',';
156 }
157 }
158
159 (*res) << '}';
160 res->TrimSpace();
161 return res;
162 }
163
164 //__________________________________________________________________________________
165
_VariableContainer(_String const & theName,_String theTmplt,_VariableContainer * theP)166 _VariableContainer::_VariableContainer (_String const & theName, _String theTmplt, _VariableContainer* theP) : iVariables(nil), dVariables(nil), gVariables(nil) {
167 _VariableContainer::InitializeVarCont (theName, theTmplt,theP);
168 }
169
170 //__________________________________________________________________________________
171
HasExplicitFormModel(void) const172 bool _VariableContainer::HasExplicitFormModel (void) const {
173 if (theModel == -1L) {
174 return false;
175 }
176 return (modelTypeList.list_data[theModel]);
177 }
178
179 //__________________________________________________________________________________
180
GetExplicitFormModel(void) const181 _Formula* _VariableContainer::GetExplicitFormModel (void) const {
182 if (theModel < 0L) {
183 return nil;
184 }
185 if (modelTypeList.list_data[theModel]) { // an explicit formula based matrix
186 return (_Formula*)modelMatrixIndices.list_data[theModel];
187 }
188 return nil;
189 }
190
191 //__________________________________________________________________________________
192
GetModelName(void) const193 _String const* _VariableContainer::GetModelName (void) const{
194 _String const * res = GetObjectNameByType (HY_BL_MODEL, theModel, false);
195 if (res) {
196 return res;
197 }
198 return &kEmptyString;
199 }
200
201 //__________________________________________________________________________________
202
GetModelMatrix(_List * queue,_SimpleList * tags) const203 _Matrix* _VariableContainer::GetModelMatrix (_List* queue, _SimpleList* tags) const {
204 if (theModel < 0L) {
205 return nil;
206 }
207
208 if (modelTypeList.list_data[theModel]) { // an explicit formula based matrix
209 if (queue && tags) {
210 long currentQueueLength = ((_Formula*)modelMatrixIndices.list_data[theModel])->ExtractMatrixExpArguments (queue);
211 if (currentQueueLength) {
212 for (unsigned long k = 0; k < currentQueueLength; k++)
213 (*tags) << currentQueueLength;
214 return nil;
215 }
216 }
217 _Matrix* result = (_Matrix *)((_Formula *)modelMatrixIndices.list_data[theModel])->Compute();
218 result->CheckIfSparseEnough(true);
219 return result;
220 }
221
222 return (_Matrix*) (LocateVar(modelMatrixIndices.list_data[theModel])->GetValue());
223 }
224
225 //__________________________________________________________________________________
226
GetModelDimension(void)227 long _VariableContainer::GetModelDimension (void) {
228 long matrixDim = 0L;
229 if (theModel >= 0L) {
230 matrixDim = modelTypeList.list_data[theModel];
231 if (matrixDim == 0L) {
232 return GetModelMatrix()->GetHDim();
233 }
234 }
235 return matrixDim;
236 }
237
238 //__________________________________________________________________________________
239
GetFreqMatrix(void) const240 _Matrix* _VariableContainer::GetFreqMatrix (void) const {
241 if (theModel>=0) {
242 long freqID = modelFrequenciesIndices.list_data[theModel];
243 if (freqID>=0) {
244 return (_Matrix*) (LocateVar(freqID)->GetValue());
245 } else {
246 return (_Matrix*) (LocateVar(-freqID-1)->GetValue());
247 }
248 }
249 return nil;
250 }
251
252 //__________________________________________________________________________________
ScanModelBasedVariables(_String const & fullName,_AVLListXL * varCache)253 void _VariableContainer::ScanModelBasedVariables (_String const & fullName, _AVLListXL* varCache) {
254 if (theModel!= HY_NO_MODEL) { // build the matrix variables
255 _SimpleList mVars;
256
257 {
258
259 long cachedID = -1;
260 bool doScan = !varCache || (cachedID = varCache->Find ((BaseRef) theModel)) < 0L ;
261
262 if (doScan) {
263
264 _AVLList ma (&mVars);
265 ScanModelForVariables (GetModelIndex(), ma,true,theModel,false);
266
267 long freqID = modelFrequenciesIndices.list_data[theModel];
268 if (freqID>=0) {
269 ((_Matrix*) (LocateVar(freqID)->GetValue()))->ScanForVariables2(ma,true,-1,false);
270 }
271
272 ma.ReorderList();
273
274 if (varCache) {
275 varCache->Insert ((BaseRef)theModel, (long)mVars.makeDynamic(),false);
276 }
277 } else if (varCache) {
278 mVars.Duplicate (varCache->GetXtra (cachedID));
279 }
280
281 }
282
283 for (long i=0L; i<mVars.lLength; i++) {
284 _Variable * aVar = (_Variable*)variablePtrs (mVars.list_data[i]);
285 if (aVar->IsGlobal()) {
286 PushGlobalVariable(aVar->get_index());
287 } else {
288 _StringBuffer var_name (fullName.length() + 1UL + aVar->GetName()->length());
289 var_name << fullName << '.';
290 aVar->ContextFreeName(var_name);
291 //_String var_name = fullName&'.'&aVar->ContextFreeName();
292 _Variable * spawnedVar = CheckReceptacle(&var_name, kEmptyString, false, false);
293 spawnedVar->SetBounds (aVar->GetLowerBound(), aVar->GetUpperBound());
294
295 if (aVar->IsIndependent()) {
296 PushIndVariable(spawnedVar->get_index(), mVars.get(i));
297 } else {
298 PushDepVariable(spawnedVar->get_index(), mVars.get(i));
299 }
300 }
301 }
302 }
303 }
304
305 //__________________________________________________________________________________
SetModel(long modelID,_AVLListXL * varCache)306 void _VariableContainer::SetModel (long modelID, _AVLListXL* varCache) {
307 theModel = modelID;
308 ScanModelBasedVariables (*theName, varCache);
309 SortVars();
310 }
311
312 //__________________________________________________________________________________
InitializeVarCont(_String const & aName,_String & theTmplt,_VariableContainer * theP,_AVLListXL * varCache)313 void _VariableContainer::InitializeVarCont (_String const& aName, _String& theTmplt, _VariableContainer* theP, _AVLListXL* varCache) {
314
315 theParent = theP;
316
317 if (aName.nonempty()) {
318 /*
319 SLKP
320 this entire section may be deprecated, and may actuall
321 */
322 theName = new _String (aName);
323
324 long f = aName.Find('.');
325
326 while (theP) {
327 if (f != -1L) {
328 f = aName.Find('.',f+1L,-1L);
329 } else {
330 break;
331 }
332 theP = theP->theParent;
333 }
334
335 if (theP) {
336 *theName = (*(theP->theName))&'.'&*theName;
337 }
338
339 InsertVar (this);
340 }
341 SetModel (FindModelName(theTmplt), varCache);
342 }
343
344 //__________________________________________________________________________________
345
ScanAndAttachVariables(void)346 void _VariableContainer::ScanAndAttachVariables (void) {
347 _Variable* var;
348 _SimpleList travcache;
349
350 long f = variableNames.Find (theName,travcache);
351
352 if (f >= 0L) {
353 _StringBuffer theNameAndADot = (_StringBuffer (theName->length() + 1L) << *theName << '.');
354
355 for (f = variableNames.Next (f, travcache); f>=0; f = variableNames.Next (f, travcache)) {
356 var = FetchVar (f);
357
358 if (var->theName->BeginsWith(theNameAndADot)) {
359 if (!var->IsContainer()) {
360 long vix = variableNames.GetXtra (f);
361
362 if (var->IsIndependent()) {
363 if ( ! (HasIndVariable(vix) || HasDepVariable(vix))) {
364 PushIndVariable(vix, -1);
365 }
366 } else {
367 if ( ! (HasIndVariable(vix) || HasDepVariable(vix))) {
368 PushDepVariable(vix, -1);
369 }
370 }
371 }
372 } else {
373 break;
374 }
375 }
376 }
377
378 }
379 //__________________________________________________________________________________
380
~_VariableContainer(void)381 _VariableContainer::~_VariableContainer(void) {
382 if (iVariables) {
383 delete iVariables;
384 }
385 if (dVariables) {
386 delete dVariables;
387 }
388 if (gVariables) {
389 delete gVariables;
390 }
391 }
392
393 //__________________________________________________________________________________
394
HasChanged(bool)395 bool _VariableContainer::HasChanged (bool) {
396
397 auto has_changed = [] (long var_index, long, unsigned long) -> bool {
398 return LocateVar (var_index) -> HasChanged ();
399 };
400 auto has_changed_global = [=] (long var_index, unsigned long) -> bool {
401 return LocateVar (var_index) -> HasChanged ();
402 };
403
404 return AnyLocalVariable (iVariables, has_changed) ||
405 gVariables && gVariables->Any(has_changed_global) ||
406 AnyLocalVariable (dVariables, has_changed);
407 }
408
409 //__________________________________________________________________________________
410
GetIthIndependent(long index) const411 _Variable* _VariableContainer::GetIthIndependent (long index) const {
412 if (iVariables && (index = index << 1)<iVariables->countitems()) {
413 return LocateVar (iVariables->get(index));
414 } else {
415 return nil;
416 }
417 }
418
419
420 //__________________________________________________________________________________
421
GetIthDependent(long index) const422 _Variable* _VariableContainer::GetIthDependent (long index) const {
423 if (dVariables && (index = index << 1) < dVariables->countitems()) {
424 return LocateVar (dVariables->get(index));
425 } else {
426 return nil;
427 }
428 }
429
430 //__________________________________________________________________________________
431
GetIthParameter(long index) const432 _Variable* _VariableContainer::GetIthParameter (long index) const {
433 if (iVariables) {
434 if ( (index = index << 1 ) <iVariables->countitems()) {
435 return LocateVar (iVariables->get(index));
436 } else {
437 if (dVariables) {
438 index-=iVariables->countitems();
439 if (index<dVariables->countitems()) {
440 return LocateVar (dVariables->get(index));
441 }
442 }
443 }
444 } else {
445 if (dVariables && (index = index << 1) <dVariables->countitems()) {
446 return LocateVar (dVariables->get(index));
447 }
448 }
449 return nil;
450 }
451
452 //__________________________________________________________________________________
453
NeedToExponentiate(bool ignoreCats) const454 bool _VariableContainer::NeedToExponentiate (bool ignoreCats) const {
455 if ((HY_VC_NO_CHECK&varFlags) == 0) {
456 auto has_changed = [=] (long var_index, long ref_index, unsigned long) -> bool {
457 if (ref_index >= 0L) {
458 return LocateVar (var_index) -> HasChanged (ignoreCats);
459 /*bool haz = LocateVar (var_index) -> HasChanged (ignoreCats);
460 if (haz) {
461 _Variable *lv = LocateVar (var_index);
462 fprintf (stderr, "==> %s HAZ changed in the context of %s (%d, %x, %d)\n", lv->GetName()->get_str(), GetName()->get_str(), lv->varFlags, LocateVar (var_index)->varValue, lv->varValue->IsVariable());
463 }
464 return haz;*/
465 }
466 return false;
467 };
468 auto has_changed_global = [=] (long var_index, unsigned long) -> bool {
469 return LocateVar (var_index) -> HasChanged (ignoreCats);
470 };
471
472
473 return AnyLocalVariable (iVariables, has_changed) ||
474 gVariables && gVariables->Any(has_changed_global) ||
475 AnyLocalVariable (dVariables, has_changed);
476 }
477 return false;
478
479 }
480
481 //__________________________________________________________________________________
SortVars(void)482 void _VariableContainer::SortVars(void) {
483 // sort independents 1st
484 // use dumb bubble sort
485
486 auto bubble_sort = [] (_SimpleList * array) -> void {
487 if (array && array->countitems ()>2) {
488 bool done = false;
489
490 _String *s1,
491 *s2;
492 while (!done) {
493 done = true;
494 s1 = LocateVar(array->list_data[0])->GetName();
495 for (long index = 2L; index<array->countitems(); index+=2L) {
496 s2 = LocateVar(array->list_data[index])->GetName();
497 if (s2->Compare(*s1) == kCompareLess) {
498 done = false;
499 array->Swap (index, index-2);
500 array->Swap (index+1, index-1);
501 }
502 }
503 }
504 }
505 };
506
507 bubble_sort (iVariables);
508 bubble_sort (dVariables);
509 }
510 //__________________________________________________________________________________
511
PushGlobalVariable(long var_ref)512 void _VariableContainer::PushGlobalVariable (long var_ref) {
513 if (gVariables) {
514 *gVariables << var_ref;
515 } else {
516 gVariables = new _SimpleList;
517 *gVariables << var_ref;
518 }
519 }
520
521 //__________________________________________________________________________________
PushIndVariable(long var_ref,long local_ref)522 void _VariableContainer::PushIndVariable (long var_ref, long local_ref) {
523 if (iVariables) {
524 *iVariables << var_ref << local_ref;
525 } else {
526 iVariables = new _SimpleList;
527 *iVariables << var_ref << local_ref;
528 }
529 }
530 //__________________________________________________________________________________
531
PushDepVariable(long var_ref,long local_ref)532 void _VariableContainer::PushDepVariable (long var_ref, long local_ref) {
533 if (dVariables) {
534 *dVariables << var_ref << local_ref;
535 } else {
536 dVariables = new _SimpleList;
537 *dVariables << var_ref << local_ref;
538 }
539 }
540 //__________________________________________________________________________________
541
HasIndVariable(long var_ref) const542 bool _VariableContainer::HasIndVariable (long var_ref) const {
543 return iVariables && iVariables->FindStepping(var_ref, 2L) >= 0;
544 }
545 //__________________________________________________________________________________
546
HasDepVariable(long var_ref) const547 bool _VariableContainer::HasDepVariable (long var_ref) const {
548 return dVariables && dVariables->FindStepping(var_ref, 2L) >= 0;
549 }
550 //__________________________________________________________________________________
551
RemoveLocalVariable(_SimpleList * & array,long array_index)552 void _VariableContainer:: RemoveLocalVariable (_SimpleList*& array, long array_index) {
553 if (array && array->countitems() > 2UL) {
554 array->Delete(array_index);
555 array->Delete(array_index);
556 array->TrimMemory();
557 } else {
558 delete array;
559 array = nil;
560 }
561 }
562
563 //__________________________________________________________________________________
564
RemoveGlobalVariable(long array_index)565 void _VariableContainer:: RemoveGlobalVariable (long array_index) {
566 if (gVariables->countitems() > 1UL) {
567 gVariables->Delete(array_index);
568 gVariables->TrimMemory();
569 } else {
570 delete gVariables;
571 gVariables = nil;
572 }
573 }
574
575
576 //__________________________________________________________________________________
RemoveDependance(long varIndex)577 bool _VariableContainer::RemoveDependance (long varIndex) {
578 if (dVariables) {
579 long array_index = dVariables->FindStepping(varIndex,2L);
580
581 if (array_index >= 0L) {
582
583 InsertVariableInSortedList(iVariables,
584 *LocateVar (dVariables->list_data[array_index])->GetName(),
585 varIndex,
586 dVariables->get(array_index+1));
587 RemoveLocalVariable (dVariables, array_index);
588 }
589 }
590 return true;
591 }
592
593 //__________________________________________________________________________________
RemoveDependance(_AVLList const & list)594 void _VariableContainer::RemoveDependance (_AVLList const & list) {
595 if (dVariables) {
596
597 _SimpleList removed;
598
599 ForEachLocalVariable(dVariables, [&list, &removed, this] (long self, long template_var, unsigned long array_idx) -> void {
600 if (list.FindLong(self) >= 0L) {
601 InsertVariableInSortedList(this->iVariables,
602 *LocateVar (self)->GetName(),
603 self,
604 template_var);
605 removed << array_idx;
606
607 }
608 });
609
610 removed.Sort();
611 removed.Flip();
612
613 removed.Each([this] (long idx, unsigned long) -> void {
614 this->RemoveLocalVariable (this->dVariables, idx);
615 });
616
617 }
618 }
619
620 //__________________________________________________________________________________
CheckAndAddUserExpression(_String & parameter_name,long start_with)621 long _VariableContainer::CheckAndAddUserExpression (_String& parameter_name, long start_with) {
622 _String localized_name = WrapInNamespace (parameter_name, theName),
623 unused_name (localized_name);
624
625 long k = MAX (start_with, 2L);
626 if (start_with>=2L) {
627 unused_name = localized_name&start_with;
628 }
629
630 while (LocateVarByName(unused_name)>=0L) {
631 unused_name = localized_name & _String (k++);
632 }
633
634 if (start_with<0L) {
635 return k>2?k-1:0;
636 }
637
638 if (start_with<2) {
639 if (k>2) {
640 parameter_name = parameter_name&_String(k-1L);
641 }
642 } else {
643 if (k>start_with) {
644 parameter_name = parameter_name & _String (k-1L);
645 } else {
646 parameter_name = parameter_name & _String (start_with);
647 }
648 }
649
650 _Variable newVar (unused_name);
651 k = newVar.get_index();
652
653 PushDepVariable(k, -1);
654 return k;
655 }
656
657 //__________________________________________________________________________________
CopyMatrixParameters(_VariableContainer * source,bool match_by_name)658 void _VariableContainer::CopyMatrixParameters (_VariableContainer* source, bool match_by_name) {
659 if (iVariables && (source->iVariables || source->dVariables)) {
660 if (match_by_name) {
661 _List source_vars, target_vars;
662
663 _SimpleList model_vars_in_source, model_vars_in_target;
664
665 ForEachLocalVariable(source->iVariables, [&] (long var_idx, long ref_idx, long array_index) {
666 if (ref_idx >= 0L) {
667 source_vars << LocateVar (ref_idx)->GetName();
668 model_vars_in_source << array_index;
669 }
670 });
671 ForEachLocalVariable(source->dVariables, [&] (long var_idx, long ref_idx, long array_index) {
672 if (ref_idx >= 0L) {
673 source_vars << LocateVar (ref_idx)->GetName();
674 model_vars_in_source << (-2L-array_index);
675 }
676 });
677 ForEachLocalVariable(iVariables, [&] (long var_idx, long ref_idx, long array_index) {
678 if (ref_idx >= 0L) {
679 target_vars << LocateVar (ref_idx)->GetName();
680 model_vars_in_target << array_index;
681 }
682 });
683
684 _SimpleList the_mapping;
685 target_vars.Map (source_vars, the_mapping);
686 the_mapping.Each ([=] (long source_var, unsigned long index) -> void {
687 if (source_var >= 0L) {
688 long which_idx = model_vars_in_source.list_data[source_var];
689 which_idx = which_idx >= 0 ? source->iVariables->get (which_idx) : source->dVariables->get (-which_idx-2L);
690 LocateVar (iVariables->get (model_vars_in_target.get(index)))->SetValue (LocateVar (which_idx)->Compute(),true,true,NULL);
691 }
692 });
693
694 } else {
695 if (source->iVariables) {
696 for (unsigned long i=0UL; i<iVariables->lLength && i< source->iVariables->lLength; i+=2UL) {
697 LocateVar (iVariables->get(i))->SetValue(LocateVar (source->iVariables->get(i))->Compute(),true,true,NULL);
698 }
699 }
700 }
701 }
702 SetValue (source->Compute(),true,true,NULL);
703 }
704
705 //__________________________________________________________________________________
KillUserExpression(long varID)706 void _VariableContainer::KillUserExpression (long varID) {
707 if (dVariables) {
708 long f = dVariables->FindStepping(varID,2);
709 if (f>=0) {
710 DeleteVariable (*LocateVar(varID)->GetName(),true);
711 RemoveLocalVariable(dVariables, f);
712 }
713 }
714 }
715
716 //__________________________________________________________________________________
717
InsertVariableInSortedList(_SimpleList * & list,_String const & var_name,long var_idx,long ref_idx)718 long _VariableContainer::InsertVariableInSortedList (_SimpleList * & list, _String const & var_name, long var_idx, long ref_idx) {
719
720 long insert_here = 0L;
721
722 if (!list) {
723 list = new _SimpleList;
724 } else {
725 unsigned long array_l = list->countitems();
726 while (insert_here< array_l) {
727 _Variable *existing_var = LocateVar (list->get(insert_here));
728 if (!existing_var) {
729 HandleApplicationError (_String("Internal error in InsertVariableInSortedList()"), false);
730 return -1;
731 }
732 if (var_name.Compare (*existing_var->GetName()) != kCompareGreater) {
733 break;
734 }
735 insert_here+=2;
736 }
737 }
738
739 list->InsertElement ((BaseRef)var_idx, insert_here, false, false);
740 list->InsertElement ((BaseRef)ref_idx, insert_here+1, false, false);
741
742 return insert_here;
743 }
744
745
746 //__________________________________________________________________________________
SetDependance(long varIndex)747 long _VariableContainer::SetDependance (long varIndex) {
748 if (iVariables) {
749 long f;
750
751 if (varIndex>=0) {
752 f = iVariables->FindStepping(varIndex,2);
753 if (f<0) {
754 return -1;
755 }
756 } else {
757 f = -varIndex-1;
758 varIndex = iVariables->list_data[f];
759 }
760
761
762 /*printf ("Moving ind->dep for %s from %s\n", LocateVar (varIndex)->GetName()->get_str(),
763 GetName()->get_str());*/
764
765 if (iVariables->list_data[f+1]>=0) {
766 //printf ("Local variable %s\n", LocateVar (iVariables->list_data[f+1])->GetName()->sData);
767 if (!LocateVar(iVariables->list_data[f+1])->IsIndependent()) {
768 return -2;
769 }
770 }
771
772 InsertVariableInSortedList (dVariables, *LocateVar (iVariables->get(f))->GetName(), varIndex,iVariables->get(f+1));
773 RemoveLocalVariable(iVariables,f);
774 return varIndex;
775 }
776 return -1;
777 }
778
779 //__________________________________________________________________________________
SetMDependance(_SimpleList const & mDep)780 bool _VariableContainer::SetMDependance (_SimpleList const & mDep) {
781 if (iVariables) {
782 if (mDep.lLength*2 > iVariables->lLength)
783 for (long k=iVariables->lLength-2; k>=0; k-=2) {
784 long f = mDep.BinaryFind (iVariables->list_data[k]);
785 if (f>=0) {
786 SetDependance (-k-1);
787 }
788 }
789 else
790 for (unsigned long k=0UL; iVariables && k<mDep.lLength; k++) {
791 SetDependance (mDep.list_data[k]);
792 }
793 }
794
795 return true;
796 }
797
798
799 //__________________________________________________________________________________
Clear(void)800 void _VariableContainer::Clear(void) {
801 theModel = HY_NO_MODEL;
802 if (iVariables) {
803 delete iVariables;
804 iVariables = nil;
805 }
806 if (dVariables) {
807 delete dVariables;
808 dVariables = nil;
809 }
810 if (gVariables) {
811 delete gVariables;
812 gVariables = nil;
813 }
814 }
815
816 //__________________________________________________________________________________
CountAll(void) const817 long _VariableContainer::CountAll(void) const {
818 return (iVariables? (iVariables->countitems() >> 1) :0L)+(dVariables?(dVariables->countitems() >> 1):0L);
819 }
820
821 //__________________________________________________________________________________
CountIndependents(void) const822 long _VariableContainer::CountIndependents(void) const {
823 return (iVariables? (iVariables->countitems() >> 1) :0L);
824 }
825
826 //__________________________________________________________________________________
CountDependents(void) const827 long _VariableContainer::CountDependents(void) const {
828 return (dVariables? (dVariables->countitems() >> 1) :0L);
829 }
830
831 //__________________________________________________________________________________
HasLocals(void)832 bool _VariableContainer::HasLocals (void) {
833 return iVariables && iVariables->countitems() > 0UL || dVariables && dVariables->countitems() > 0UL;
834 }
835
836 //__________________________________________________________________________________
837
GetSaveableListOfUserParameters(void)838 _String* _VariableContainer::GetSaveableListOfUserParameters (void) {
839 _StringBuffer * result = new _StringBuffer (64L);
840
841 ForEachLocalVariable(dVariables, [&] (long var_index, long ref_index, unsigned long array_index) -> void {
842 if (ref_index < 0) {
843 _Variable * userParm = (_Variable*) LocateVar (var_index);
844 result->AppendAnAssignmentToBuffer(userParm->GetName(),
845 (_String*)userParm->GetFormulaString(kFormulaStringConversionNormal),
846 kAppendAnAssignmentToBufferFree | kAppendAnAssignmentToBufferAssignment);
847 }
848 });
849
850 result->TrimSpace ();
851 return result;
852 }
853
854 //__________________________________________________________________________________
ClearConstraints(void)855 void _VariableContainer::ClearConstraints(void) {
856 while (dVariables) {
857 LocateVar(dVariables->list_data[0])->ClearConstraints();
858 }
859 }
860
861 //#define _UBER_VERBOSE_MX_UPDATE_DUMP
862
863 //__________________________________________________________________________________
864
CopyModelParameterValue(long var_idx,long ref_idx,unsigned long)865 void _VariableContainer::CopyModelParameterValue (long var_idx, long ref_idx, unsigned long) {
866 if (ref_idx >= 0) {
867 _Variable * model_var = LocateVar (ref_idx);
868 if (model_var -> IsIndependent()) {
869 model_var->SetValue (LocateVar (var_idx)->Compute(),true,true,NULL);
870
871 #ifdef _UBER_VERBOSE_MX_UPDATE_DUMP
872 fprintf (stderr, "[_CalcNode::RecomputeMatrix] Node %s, var %s, value = %15.12g\n", LocateVar (var_idx)->GetName()->get_str(), model_var->GetName()->get_str(), model_var->Compute()->Value());
873 #endif
874 }
875 }
876 }
877
878
879 //__________________________________________________________________________________
880
CompileListOfDependents(_SimpleList & rec)881 void _VariableContainer::CompileListOfDependents (_SimpleList& rec) {
882
883 auto push_var = [&] (long var_idx, long ref_idx, unsigned long index) -> void {
884 LocateVar (var_idx)->CompileListOfDependents(rec);
885 };
886
887 ForEachLocalVariable(iVariables, push_var);
888 if (gVariables) {
889 gVariables->Each ([&] (long var_idx, unsigned long index) -> void {
890 LocateVar (var_idx)->CompileListOfDependents(rec);
891 });
892 }
893 ForEachLocalVariable(dVariables, push_var);
894 if (dVariables) {
895 for (unsigned long i=0UL; i<dVariables->countitems(); i+=2UL) {
896 long f = rec.Find (dVariables->get (i));
897 if (f>=0L) {
898 rec.Delete (f);
899 }
900 }
901 }
902 }
903
904
905 //__________________________________________________________________________________
906
MarkDone(void)907 void _VariableContainer::MarkDone (void) {
908
909 ForEachLocalVariable(iVariables, [] (long var_idx, long ref_idx, unsigned long index) -> void {
910 LocateVar (var_idx)->MarkDone();
911 });
912 if (gVariables) {
913 gVariables->Each ([&] (long var_idx, unsigned long index) -> void {
914 LocateVar (var_idx)->MarkDone();
915 });
916 }
917 }
918
919
920 //__________________________________________________________________________________
921
MatchParametersToList(_List & suffixes,bool doAll,bool indOnly)922 void _VariableContainer::MatchParametersToList (_List& suffixes, bool doAll, bool indOnly) {
923 /** TODO SLKP 20171130; what is this for?? Likely can be deprecated */
924
925 if (doAll) {
926 for (long i=suffixes.lLength-1; i>=0; i--) {
927 long j;
928 if (!indOnly) {
929 if (dVariables) {
930 for (j=0; j<dVariables->lLength; j+=2)
931 if (LocateVar(dVariables->list_data[j])->GetName()->EndsWith (*(_String*)suffixes.list_data[i])) {
932 break;
933 }
934
935 if (j<dVariables->lLength) {
936 continue;
937 }
938 }
939 }
940 if (iVariables) {
941 for (j=0; j<iVariables->lLength; j+=2) {
942 if (LocateVar(iVariables->list_data[j])->GetName()->EndsWith (*(_String*)suffixes.list_data[i])) {
943 break;
944 }
945 }
946 if (j==iVariables->lLength) {
947 suffixes.Delete (i);
948 }
949 } else {
950 suffixes.Delete (i);
951 }
952 }
953 } else {
954 for (long i=suffixes.lLength-1; i>=0; i--) {
955 long j;
956 if (dVariables) {
957 for (j=0; j<dVariables->lLength; j+=2) {
958 if (dVariables->list_data[j+1]<0) {
959 if (LocateVar(dVariables->list_data[j])->GetName()->EndsWith (*(_String*)suffixes.list_data[i])) {
960 break;
961 }
962 }
963 }
964 if (j==dVariables->lLength) {
965 suffixes.Delete (i);
966 }
967 } else {
968 suffixes.Delete(i);
969 }
970 }
971 }
972 }
973
974 //__________________________________________________________________________________
975
IsConstant(void)976 bool _VariableContainer::IsConstant (void) {
977 if (iVariables) {
978 return false;
979 }
980
981 return ! (AnyLocalVariable(dVariables, [] (long var_idx, long ref_idx, unsigned long) -> bool {
982 return !LocateVar(var_idx)->IsConstant();
983 }) ||
984 gVariables && gVariables->Any ([] (long var_idx, unsigned long) -> bool {
985 return !LocateVar(var_idx)->IsConstant();
986 }));
987
988 }
989
990 //__________________________________________________________________________________
991
ScanContainerForVariables(_AVLList & l,_AVLList & l2,_AVLListX * tagger,long weight,_AVLListX * map_variables_to_nodes,long track_node)992 void _VariableContainer::ScanContainerForVariables (_AVLList& l,_AVLList& l2, _AVLListX * tagger, long weight, _AVLListX * map_variables_to_nodes, long track_node) {
993
994 //printf ("_VariableContainer::ScanContainerForVariable %x\n", this);
995 ForEachLocalVariable(iVariables, [&] (long var_idx, long ref_idx, unsigned long) -> void {
996 long insert_location = l.Insert((BaseRef)var_idx);
997 if (tagger) {
998 tagger->UpdateValue ((BaseRef)var_idx, weight, 0);
999 }
1000 if (map_variables_to_nodes) {
1001 //printf ("%ld (%s) -> %ld\n", var_idx, LocateVar (var_idx)->GetName()->get_str(), insert_location);
1002 if (insert_location >= 0) { // was inserted
1003 map_variables_to_nodes->Insert ((BaseRef)var_idx, track_node, false, false);
1004 } else { // was already there
1005 map_variables_to_nodes->UpdateValue((BaseRef)var_idx, -1, 1);
1006 }
1007 }
1008 });
1009
1010 if (dVariables) {
1011 _SimpleList temp;
1012 _AVLList ta (&temp);
1013
1014 ForEachLocalVariable(dVariables, [&] (long var_idx, long ref_idx, unsigned long) -> void {
1015 l2.Insert((BaseRef)var_idx);
1016 LocateVar (var_idx)->ScanForVariables(ta, true, tagger, weight);
1017 });
1018
1019 //ta.ReorderList();
1020 temp.Each([&] (long var_index, unsigned long) -> void {
1021 _Variable * v = LocateVar(var_index);
1022 if (!v->IsGlobal() && v->IsIndependent()) {
1023 long insert_location = l.Insert ((BaseRef)var_index);
1024 if (tagger) {
1025 tagger->UpdateValue ((BaseRef)var_index, weight, 0);
1026 }
1027 if (map_variables_to_nodes) {
1028 if (insert_location >= 0) { // was inserted
1029 map_variables_to_nodes->Insert ((BaseRef)var_index, track_node, false, false);
1030 } else { // was already there
1031 map_variables_to_nodes->UpdateValue((BaseRef)var_index, -1, 1);
1032 }
1033 }
1034 }
1035 });
1036 }
1037 }
1038
1039 //__________________________________________________________________________________
1040
ScanForDVariables(_AVLList & l,_AVLList &) const1041 void _VariableContainer::ScanForDVariables (_AVLList& l,_AVLList&) const {
1042 ForEachLocalVariable(dVariables, [&] (long var_idx, long ref_idx, unsigned long) -> void {
1043 l.Insert((BaseRef)var_idx);
1044 });
1045 }
1046
1047 //__________________________________________________________________________________
1048
GetListOfModelParameters(_List & rec)1049 void _VariableContainer::GetListOfModelParameters (_List& rec) {
1050 ForEachLocalVariable(iVariables, [&] (long var_idx, long ref_idx, unsigned long) -> void {
1051 if (ref_idx >= 0) {
1052 rec << LocateVar(ref_idx)->GetName();
1053 }
1054 });
1055 }
1056
1057 //__________________________________________________________________________________
1058
ScanForGVariables(_AVLList & independent,_AVLList & dependent,_AVLListX * tagger,long weight) const1059 void _VariableContainer::ScanForGVariables (_AVLList& independent,_AVLList& dependent, _AVLListX* tagger, long weight) const {
1060
1061 auto insert_g_var = [&] (_Variable *v, long var_idx) -> void {
1062 if (v->IsIndependent()) {
1063 long insert_location = independent.Insert ((BaseRef)var_idx);
1064 if (tagger) {
1065 tagger->UpdateValue((BaseRef)var_idx, weight, 0);
1066 }
1067 } else {
1068 dependent.Insert ((BaseRef)var_idx);
1069 }
1070 };
1071
1072 if (gVariables) {
1073 gVariables->Each([&] (long var_idx, unsigned long) -> void {
1074 insert_g_var (LocateVar (var_idx), var_idx);
1075 });
1076 }
1077
1078
1079 // additionally, check to see if there is any implicit dependence on the global variables yet unseen
1080 if (dVariables) {
1081 _SimpleList var_list;
1082 _AVLList al (&var_list);
1083 ForEachLocalVariable(dVariables, [&] (long var_idx, long ref_idx, unsigned long) -> void {
1084 LocateVar (var_idx)->ScanForVariables(al, true);
1085 });
1086 //al.ReorderList();
1087 var_list.Each ([&] (long var_idx, unsigned long) -> void {
1088 _Variable * v = LocateVar(var_idx);
1089 if (v->IsGlobal()) {
1090 insert_g_var (LocateVar (var_idx), var_idx);
1091 }
1092 });
1093 }
1094 }
1095