1 |
|
2 |
/* needs to be first so that <Python.h> gets included before <iostream> */ |
3 |
#include "library.h" |
4 |
|
5 |
#include "instance.h" |
6 |
#include "variable.h" |
7 |
#include "name.h" |
8 |
#include "set.h" |
9 |
#include "plot.h" |
10 |
#include "instanceinterfacedata.h" |
11 |
|
12 |
extern "C"{ |
13 |
#include <utilities/ascConfig.h> |
14 |
#include <compiler/instance_types.h> |
15 |
#include <utilities/ascSignal.h> |
16 |
#include <utilities/ascMalloc.h> |
17 |
#include <general/dstring.h> |
18 |
|
19 |
#include <compiler/symtab.h> |
20 |
#include <compiler/instance_io.h> |
21 |
#include <compiler/instantiate.h> |
22 |
#include <compiler/bintoken.h> |
23 |
#include <compiler/instquery.h> |
24 |
#include <compiler/check.h> |
25 |
#include <compiler/name.h> |
26 |
#include <compiler/parentchild.h> |
27 |
#include <compiler/instance_name.h> |
28 |
#include <compiler/atomvalue.h> |
29 |
#include <utilities/readln.h> |
30 |
#include <compiler/plot.h> |
31 |
#include <compiler/expr_types.h> |
32 |
#include <compiler/find.h> |
33 |
#include <compiler/exprs.h> |
34 |
#include <compiler/relation.h> |
35 |
#include <compiler/relation_io.h> |
36 |
#include <compiler/functype.h> |
37 |
#include <compiler/relation_util.h> |
38 |
} |
39 |
|
40 |
#include <iostream> |
41 |
#include <stdexcept> |
42 |
#include <sstream> |
43 |
|
44 |
using namespace std; |
45 |
|
46 |
/** |
47 |
Create an instance of a type. @see Simulation for instantiation. |
48 |
*/ |
49 |
Instanc::Instanc(Instance *i) : i(i), name("unnamed1"){ |
50 |
if(i==NULL){ |
51 |
stringstream ss; |
52 |
ss << "Attempted to create Instance object will null 'Instance *', name " << name; |
53 |
throw runtime_error(ss.str()); |
54 |
} |
55 |
//throw runtime_error("Created unnamed instance"); |
56 |
// nothing else; |
57 |
} |
58 |
|
59 |
Instanc::Instanc(Instance *i, const SymChar &name) : i(i), name(name){ |
60 |
/*if(i==NULL){ |
61 |
stringstream ss; |
62 |
ss << "Attempted to create Instance object will null 'Instance *', name " << name; |
63 |
throw runtime_error(ss.str()); |
64 |
}*/ |
65 |
//cerr << "A NEW INSTANCE " << name << endl; |
66 |
} |
67 |
|
68 |
Instanc::Instanc(const Instanc&old) : i(old.i), name(old.name){ |
69 |
// nothing else |
70 |
} |
71 |
|
72 |
Instanc::Instanc() : i(NULL), name("unnamed0"){ |
73 |
// nothing else |
74 |
} |
75 |
|
76 |
/* |
77 |
Create a child instance given the parent |
78 |
*/ |
79 |
Instanc::Instanc(const Instanc &parent, const unsigned long &childnum) |
80 |
: i( InstanceChild(parent.i,childnum) ), name( ChildName(parent.i,childnum) ){ |
81 |
// cerr << "CREATED CHILD #" << childnum << ", named '" << getName() << "' OF " << parent.getName() << endl; |
82 |
} |
83 |
|
84 |
/** |
85 |
Destructor |
86 |
|
87 |
There's no data owned by this object, so nothing to be done here. |
88 |
*/ |
89 |
Instanc::~Instanc(){ |
90 |
/* we seriously need a way to free 'interface pointer' data. this doesn't work |
91 |
though, because Python gets messed up |
92 |
InstanceInterfaceData *d = (InstanceInterfaceData *)GetInterfacePtr(i); |
93 |
if(d){ |
94 |
cerr << "Destroying interface pointer data" << endl; |
95 |
delete d; |
96 |
} |
97 |
*/ |
98 |
//cerr << "DESTROYING INSTANC OBJECT" << endl; |
99 |
} |
100 |
|
101 |
const SymChar & |
102 |
Instanc::getName() const{ |
103 |
return name; |
104 |
} |
105 |
|
106 |
void |
107 |
Instanc::setName(SymChar name){ |
108 |
this->name=name; |
109 |
} |
110 |
|
111 |
Instance * |
112 |
Instanc::getInternalType() const{ |
113 |
return i; |
114 |
} |
115 |
|
116 |
const enum inst_t |
117 |
Instanc::getKind() const{ |
118 |
if(i==NULL){ |
119 |
return DUMMY_INST; |
120 |
} |
121 |
return InstanceKind(i); |
122 |
} |
123 |
|
124 |
/** |
125 |
Return the type of this instance as a string |
126 |
*/ |
127 |
const string |
128 |
Instanc::getKindStr() const{ |
129 |
enum inst_t k = getKind(); |
130 |
stringstream ss; |
131 |
|
132 |
switch(k){ |
133 |
case ERROR_INST: ss << "Error"; break; |
134 |
case SIM_INST: ss << "Simulation"; break; |
135 |
case MODEL_INST: ss << "Model"; break; |
136 |
case REL_INST: ss << "Numerical Relation"; break; |
137 |
case LREL_INST: ss << "Logical relation"; break; |
138 |
case WHEN_INST: ss << "WHEN"; break; |
139 |
case ARRAY_INT_INST: ss << "Indexed Array"; break; |
140 |
case ARRAY_ENUM_INST: ss << "Enumerated Array"; break; |
141 |
case REAL_INST: ss << "Real"; break; |
142 |
case INTEGER_INST: ss << "Integer"; break; |
143 |
case BOOLEAN_INST: ss << "Boolean"; break; |
144 |
case SYMBOL_INST: ss << "Symbol"; break; |
145 |
case SET_INST: ss << "Set"; break; |
146 |
case REAL_ATOM_INST: ss << "Real atom"; break; |
147 |
case INTEGER_ATOM_INST: ss << "Integer atom"; break; |
148 |
case BOOLEAN_ATOM_INST: ss << "Boolean atom"; break; |
149 |
case SYMBOL_ATOM_INST: ss << "Symbol atom"; break; |
150 |
case SET_ATOM_INST: ss << "Set atom"; break; |
151 |
case REAL_CONSTANT_INST: ss << "Real constant"; break; |
152 |
case BOOLEAN_CONSTANT_INST: ss << "Boolean constant"; break; |
153 |
case INTEGER_CONSTANT_INST: ss << "Integer constant"; break; |
154 |
case SYMBOL_CONSTANT_INST: ss << "Symbol constant"; break; |
155 |
case DUMMY_INST: ss << "Dummy"; break; |
156 |
default: |
157 |
throw runtime_error("Invalid instance type"); |
158 |
} |
159 |
|
160 |
ss << " instance"; |
161 |
return ss.str(); |
162 |
} |
163 |
|
164 |
const Type |
165 |
Instanc::getType() const{ |
166 |
if(i==NULL){ |
167 |
throw runtime_error("Invalid NULL instance (getType)"); |
168 |
} |
169 |
try{ |
170 |
const TypeDescription *t = InstanceTypeDesc(i); |
171 |
if(t==NULL)throw runtime_error("No type defined"); |
172 |
|
173 |
return Type(t); |
174 |
}catch(runtime_error &e){ |
175 |
stringstream ss; |
176 |
ss << "Instance::getType: with name=" << getName() << ":" << e.what(); |
177 |
throw runtime_error(ss.str()); |
178 |
} |
179 |
} |
180 |
|
181 |
const bool |
182 |
Instanc::isAtom() const{ |
183 |
return getKind() & IATOM; |
184 |
//return IsAtomicInstance(i); |
185 |
} |
186 |
|
187 |
const bool |
188 |
Instanc::isFixed() const{ |
189 |
if(getKind()!=REAL_ATOM_INST) throw runtime_error("Instanc::isFixed: not a REAL_ATOM_INST"); |
190 |
if(isFund()) throw runtime_error("Instanc::isFixed: not a fundamental type"); |
191 |
Type T = getType(); |
192 |
if(!T.isRefinedSolverVar()){ |
193 |
stringstream ss; |
194 |
ss << "Instanc::isFixed: type '" << T.getName() << "' is not a refined solver_var"; |
195 |
throw runtime_error(ss.str()); |
196 |
} |
197 |
return getChild("fixed").getBoolValue(); |
198 |
} |
199 |
|
200 |
/** Is the relation currently included in the simulation (ie active WHEN) */ |
201 |
const bool |
202 |
Instanc::isActive() const{ |
203 |
if(getKind()==REL_INST){ |
204 |
return getChild("included").getBoolValue(); |
205 |
} |
206 |
throw runtime_error("Instanc::isActive: Not a relation"); |
207 |
} |
208 |
|
209 |
const bool |
210 |
Instanc::isCompound() const{ |
211 |
return getKind() & ICOMP; |
212 |
} |
213 |
|
214 |
const bool |
215 |
Instanc::isRelation() const{ |
216 |
if(getKind()==REL_INST){ |
217 |
return true; |
218 |
} |
219 |
return false; |
220 |
} |
221 |
|
222 |
const bool |
223 |
Instanc::isLogicalRelation() const{ |
224 |
if(getKind()==LREL_INST){ |
225 |
return true; |
226 |
} |
227 |
return false; |
228 |
} |
229 |
|
230 |
const bool |
231 |
Instanc::isWhen() const{ |
232 |
if(getKind()==WHEN_INST)return true; |
233 |
return false; |
234 |
} |
235 |
|
236 |
const bool |
237 |
Instanc::isSet() const{ |
238 |
return (getKind() == SET_INST || getKind() == SET_ATOM_INST); |
239 |
} |
240 |
|
241 |
const bool |
242 |
Instanc::isSetInt() const{ |
243 |
return isSet() && getSetType()==integer_set; |
244 |
} |
245 |
|
246 |
const bool |
247 |
Instanc::isSetString() const{ |
248 |
return isSet() && getSetType()==string_set; |
249 |
} |
250 |
|
251 |
const bool |
252 |
Instanc::isSetEmpty() const{ |
253 |
return isSet() && getSetType()==empty_set; |
254 |
} |
255 |
|
256 |
const bool |
257 |
Instanc::isFund() const{ |
258 |
return getKind() & IFUND; |
259 |
//return IsFundamentalInstance(i); |
260 |
} |
261 |
|
262 |
const bool |
263 |
Instanc::isConst() const{ |
264 |
return getKind() & ICONS; |
265 |
//return IsConstantInstance(i); |
266 |
} |
267 |
|
268 |
const bool |
269 |
Instanc::isAssigned() const{ |
270 |
if(!isAtom()){ |
271 |
throw runtime_error("Instanc::isAssigned: not an Atom"); |
272 |
} |
273 |
return AtomAssigned(i); |
274 |
} |
275 |
|
276 |
const bool |
277 |
Instanc::isArray() const{ |
278 |
return getKind() & IARR; |
279 |
//return IsArrayInstance(i); |
280 |
} |
281 |
|
282 |
const bool |
283 |
Instanc::isChildless() const{ |
284 |
return getKind() & ICHILDLESS; |
285 |
//return IsChildlessInstance(i); |
286 |
} |
287 |
|
288 |
const bool |
289 |
Instanc::isBool() const{ |
290 |
switch(getKind()){ |
291 |
case BOOLEAN_INST: |
292 |
case BOOLEAN_ATOM_INST: |
293 |
case BOOLEAN_CONSTANT_INST: |
294 |
return true; |
295 |
default: |
296 |
return false; |
297 |
} |
298 |
} |
299 |
|
300 |
const bool |
301 |
Instanc::isInt() const{ |
302 |
switch(getKind()){ |
303 |
case INTEGER_INST: |
304 |
case INTEGER_ATOM_INST: |
305 |
case INTEGER_CONSTANT_INST: |
306 |
return true; |
307 |
default: |
308 |
return false; |
309 |
} |
310 |
} |
311 |
|
312 |
const bool |
313 |
Instanc::isReal() const{ |
314 |
switch(getKind()){ |
315 |
case REAL_INST: |
316 |
case REAL_ATOM_INST: |
317 |
case REAL_CONSTANT_INST: |
318 |
return true; |
319 |
default: |
320 |
return false; |
321 |
} |
322 |
} |
323 |
|
324 |
const bool |
325 |
Instanc::isSymbol() const{ |
326 |
switch(getKind()){ |
327 |
case SYMBOL_INST: |
328 |
case SYMBOL_ATOM_INST: |
329 |
case SYMBOL_CONSTANT_INST: |
330 |
return true; |
331 |
default: |
332 |
return false; |
333 |
} |
334 |
} |
335 |
|
336 |
const bool |
337 |
Instanc::isDefined() const{ |
338 |
if(!isAtom() && !isFund())throw runtime_error("Instanc::isDefined: not an atom/fund"); |
339 |
return AtomAssigned(i); |
340 |
} |
341 |
|
342 |
const bool |
343 |
Instanc::isModel() const{ |
344 |
cerr << "TESTING FOR MODEL TYPE" << endl; |
345 |
if(getKind()==MODEL_INST){ |
346 |
return true; |
347 |
} |
348 |
cerr << "RETURNOING FALSE" << endl; |
349 |
return false; |
350 |
} |
351 |
|
352 |
const double |
353 |
Instanc::getRealValue() const{ |
354 |
// Check that the instance has a real value: |
355 |
switch(getKind()){ |
356 |
case REAL_INST: |
357 |
case REAL_CONSTANT_INST: |
358 |
case REAL_ATOM_INST: |
359 |
//cerr << "REAL VALUE FOR " << getName() << endl; |
360 |
break; |
361 |
default: |
362 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not real-valued (%s)", \ |
363 |
getName().toString(),getKindStr().c_str()); |
364 |
return 0; |
365 |
} |
366 |
if(!isConst() && !isDefined()){ |
367 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not defined (%s)", \ |
368 |
getName().toString(),getKindStr().c_str()); |
369 |
return 0; |
370 |
} |
371 |
return RealAtomValue(i); |
372 |
} |
373 |
|
374 |
const bool |
375 |
Instanc::isDimensionless() const{ |
376 |
if(!isReal())return true; |
377 |
return Dimensions( RealAtomDims(i) ).isDimensionless(); |
378 |
} |
379 |
|
380 |
const Dimensions |
381 |
Instanc::getDimensions() const{ |
382 |
if(!isReal())throw runtime_error("Instanc::getDimensions: not a real-valued instance"); |
383 |
return Dimensions( RealAtomDims(i) ); |
384 |
} |
385 |
|
386 |
const bool |
387 |
Instanc::getBoolValue() const{ |
388 |
// Check that the instance has a bool value: |
389 |
switch(getKind()){ |
390 |
case BOOLEAN_INST: |
391 |
case BOOLEAN_ATOM_INST: |
392 |
case BOOLEAN_CONSTANT_INST: |
393 |
//cerr << "BOOL VALUE FOR " << getName() << endl; |
394 |
break; |
395 |
default: |
396 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not boolean-valued",getName().toString()); |
397 |
return false; |
398 |
} |
399 |
if(!isConst() && !isDefined()){ |
400 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not defined",getName().toString()); |
401 |
return false; |
402 |
} |
403 |
return GetBooleanAtomValue(i); |
404 |
} |
405 |
|
406 |
|
407 |
const long |
408 |
Instanc::getIntValue() const{ |
409 |
// Check that the instance has a bool value: |
410 |
switch(getKind()){ |
411 |
case INTEGER_INST: |
412 |
case INTEGER_ATOM_INST: |
413 |
case INTEGER_CONSTANT_INST: |
414 |
//cerr << "INT VALUE FOR " << getName() << endl; |
415 |
break; |
416 |
default: |
417 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not integer-valued",getName().toString()); |
418 |
return 0; |
419 |
} |
420 |
if(!isConst() && !isDefined()){ |
421 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not defined",getName().toString()); |
422 |
return 0; |
423 |
} |
424 |
return GetIntegerAtomValue(i); |
425 |
} |
426 |
|
427 |
const SymChar |
428 |
Instanc::getSymbolValue() const{ |
429 |
if(!isSymbol()){ |
430 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not symbol-valued",getName().toString()); |
431 |
return SymChar("ERROR"); |
432 |
} |
433 |
if(!isConst() && !isDefined()){ |
434 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not defined",getName().toString()); |
435 |
return SymChar("UNDEFINED"); |
436 |
} |
437 |
return SCP(GetSymbolAtomValue(i)); |
438 |
} |
439 |
|
440 |
void |
441 |
Instanc::setSymbolValue(const SymChar &sym){ |
442 |
stringstream ss; |
443 |
if(!isSymbol()){ |
444 |
ss << "Variable '" << getName().toString() << "' is not symbol-valued."; |
445 |
throw runtime_error(ss.str()); |
446 |
} |
447 |
if(isConst() && isDefined()){ |
448 |
ss << "Variable '" << getName().toString() << "' has already been defined."; |
449 |
throw runtime_error(ss.str()); |
450 |
} |
451 |
|
452 |
SetSymbolAtomValue(i,sym.getInternalType()); |
453 |
} |
454 |
|
455 |
const string |
456 |
Instanc::getRelationAsString(const Instanc &relative_to) const{ |
457 |
stringstream ss; |
458 |
if(isRelation()){ |
459 |
int len; |
460 |
char *str = WriteRelationString(i,relative_to.getInternalType() |
461 |
,NULL,NULL,relio_ascend,&len); |
462 |
ss << str; |
463 |
ascfree(str); |
464 |
}else{ |
465 |
throw runtime_error("getRelationString: Instance is not a relation"); |
466 |
} |
467 |
return ss.str(); |
468 |
} |
469 |
|
470 |
const double |
471 |
Instanc::getResidual() const{ |
472 |
if(!isRelation()){ |
473 |
throw runtime_error("getResidual: not a relation"); |
474 |
} |
475 |
struct RelationInstance * const ri = (struct RelationInstance * const) i; |
476 |
if(NULL == ri->ptr){ |
477 |
throw runtime_error("getResidual: ri->ptr is NULL"); |
478 |
} |
479 |
return RelationResidual( ri->ptr ); |
480 |
} |
481 |
|
482 |
/** |
483 |
Return the numerical value of an instance if it is an assigned atom. |
484 |
If it is a relation, return the string form of the relation (ie the equation) |
485 |
Else return the string 'undefined'. |
486 |
*/ |
487 |
const string |
488 |
Instanc::getValueAsString() const{ |
489 |
stringstream ss; |
490 |
|
491 |
if(isAssigned()){ |
492 |
if(isReal()){ |
493 |
ss << getRealValue(); |
494 |
}else if(isInt()){ |
495 |
ss << getIntValue(); |
496 |
}else if(isSymbol()){ |
497 |
ss << getSymbolValue(); |
498 |
}else if(isBool()){ |
499 |
ss << getBoolValue(); |
500 |
}else{ |
501 |
throw runtime_error("Invalid type in Instanc::getValueAsString"); |
502 |
} |
503 |
}else{ |
504 |
ss << "undefined"; |
505 |
} |
506 |
return ss.str(); |
507 |
} |
508 |
|
509 |
const bool |
510 |
Instanc::isPlottable() const{ |
511 |
if(plot_allowed(i)){ |
512 |
return true; |
513 |
} |
514 |
return false; |
515 |
} |
516 |
|
517 |
const enum set_kind |
518 |
Instanc::getSetType() const{ |
519 |
if(!isSet() || (!isConst() && !isDefined())){ |
520 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Variable '%s' is not set-valued or not defined",getName().toString()); |
521 |
} |
522 |
return SetKind(SetAtomList(i)); |
523 |
} |
524 |
|
525 |
/// Get the child instances :) |
526 |
vector<Instanc> & |
527 |
Instanc::getChildren() |
528 |
{ |
529 |
Type t = getType(); |
530 |
|
531 |
children = vector<Instanc>(); |
532 |
|
533 |
if(i==NULL)throw runtime_error("NULL 'i' in Instanc::getChildren"); |
534 |
|
535 |
unsigned long len = NumberChildren(i); |
536 |
if(!len)return children; |
537 |
//cerr << "FOUND " << len << " CHILDREN" << endl; |
538 |
|
539 |
if(isArray()){ |
540 |
for(unsigned long ci=1; ci<=len; ++ci){ |
541 |
Instanc c(*this, ci); |
542 |
if(!TypeShow(c.getType().getInternalType()))continue; |
543 |
if(c.i==NULL)continue; |
544 |
children.push_back(c); |
545 |
} |
546 |
return children; |
547 |
/* stringstream ss; |
548 |
ss << "Instance '" << getName() << "' is an array, type '" << t.getName() << "'"; |
549 |
ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,ss.str().c_str()); */ |
550 |
} |
551 |
|
552 |
|
553 |
ChildListPtr clist = GetChildList(t.getInternalType()); |
554 |
if(!clist){ |
555 |
stringstream ss; |
556 |
ss << "Child list of instance '" << getName() << "' of type '" << t.getName() << "' (" << getKindStr() << ") is NULL"; |
557 |
ss << " (isChildless=" << isChildless() << ")"; |
558 |
ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,ss.str().c_str()); |
559 |
return children; |
560 |
//throw runtime_error(ss.str()); |
561 |
} |
562 |
|
563 |
/// FIXME 1-based array: |
564 |
for(unsigned long ci=1; ci<=len; ++ci){ |
565 |
if(!ChildVisible(clist,ci))continue; |
566 |
|
567 |
Instanc c( *this, ci ); |
568 |
if(c.i==NULL)continue; |
569 |
//cerr << "FOUND CHILD #" << ci << ": " << c.getName() << endl; |
570 |
|
571 |
children.push_back(c); |
572 |
} |
573 |
return children; |
574 |
} |
575 |
|
576 |
Instanc |
577 |
Instanc::getChild(const SymChar &name) const{ |
578 |
struct Instance *c = ChildByChar(i,name.getInternalType()); |
579 |
stringstream ss; |
580 |
if(c==NULL){ |
581 |
ss << "Child '" << name << "' not found in " << getName(); |
582 |
throw runtime_error(ss.str()); |
583 |
} |
584 |
return Instanc(c,name); |
585 |
} |
586 |
|
587 |
Instanc |
588 |
Instanc::getChild(const long &index) const{ |
589 |
if(!isArray()){ |
590 |
stringstream ss; |
591 |
ss << "Instance '" << getName() << "' is not an array; can't retrieve child index " << index; |
592 |
throw runtime_error(ss.str()); |
593 |
} |
594 |
struct InstanceName n; |
595 |
InstanceNameType(n) = IntArrayIndex; |
596 |
InstanceIntIndex(n) = index; |
597 |
long childindex = ChildSearch(i,&n); |
598 |
if(childindex){ |
599 |
return Instanc(InstanceChild(i,childindex)); |
600 |
} |
601 |
stringstream ss; |
602 |
ss << "Invalid child index '" << index << "' for instance '" << getName() << "'"; |
603 |
throw runtime_error(ss.str()); |
604 |
|
605 |
} |
606 |
|
607 |
Plot |
608 |
Instanc::getPlot() const{ |
609 |
if(isPlottable()){ |
610 |
return Plot(*this); |
611 |
} |
612 |
throw runtime_error("Not a plottable instance"); |
613 |
} |
614 |
|
615 |
void |
616 |
Instanc::write(){ |
617 |
WriteInstance(stderr,i); |
618 |
} |
619 |
|
620 |
//---------------------------- |
621 |
// SETTING VALUES of stuff |
622 |
|
623 |
void |
624 |
Instanc::setFixed(const bool &val){ |
625 |
if(isFixed()==val)return; |
626 |
CONSOLE_DEBUG("Fixing solver_var at %p",i); |
627 |
getChild("fixed").setBoolValue(val); |
628 |
} |
629 |
|
630 |
void |
631 |
Instanc::setBoolValue(const bool &val, const unsigned &depth){ |
632 |
SetBooleanAtomValue(i, val, depth); |
633 |
} |
634 |
|
635 |
void |
636 |
Instanc::setRealValue(const double &val, const unsigned &depth){ |
637 |
SetRealAtomValue(i,val, depth); |
638 |
//ERROR_REPORTER_HERE(ASC_USER_NOTE,"Set %s to %f",getName().toString(),val); |
639 |
} |
640 |
|
641 |
/** |
642 |
Borrow the workings of this from tcltk UnitsProc.c |
643 |
*/ |
644 |
void |
645 |
Instanc::setRealValueWithUnits(double val, const char *units, const unsigned &depth){ |
646 |
|
647 |
if(isConst()){ |
648 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Can't change the value of a constant"); |
649 |
return; |
650 |
} |
651 |
|
652 |
if(!isReal() || !isAtom()){ |
653 |
throw runtime_error("Instanc::setRealValueWithUnits: not a real-valued instance"); |
654 |
} |
655 |
|
656 |
if(units == NULL || strlen(units)==0 || strcmp(units,"*")==0){ |
657 |
// No units were specified, so the base (SI) units are implied. |
658 |
}else{ |
659 |
// We need to parse the units string |
660 |
UnitsM u = UnitsM(units); |
661 |
Dimensions d = u.getDimensions(); |
662 |
|
663 |
// If no dimensions yet assigned, assign them. Otheriwse check for consistency. |
664 |
if(getDimensions().isWild()){ |
665 |
// Set the dimensions for a wildcard atom: |
666 |
SetRealAtomDims(i, d.getInternalType()); |
667 |
}else if(d != getDimensions()){ |
668 |
throw runtime_error("Dimensionally incompatible units"); |
669 |
} |
670 |
|
671 |
// Not going to worry about FPEs here, let the program crash if it must. |
672 |
val = val * u.getConversion(); |
673 |
} |
674 |
|
675 |
SetRealAtomValue(i,val,depth); |
676 |
} |
677 |
|
678 |
/** |
679 |
Set the instance variable status. See @getVarStatus |
680 |
*/ |
681 |
void |
682 |
Instanc::setVarStatus(const VarStatus &s){ |
683 |
InstanceInterfaceData *d; |
684 |
d = (InstanceInterfaceData *)GetInterfacePtr(i); |
685 |
if(d==NULL && s!=ASCXX_VAR_STATUS_UNKNOWN){ |
686 |
d = new InstanceInterfaceData(); |
687 |
SetInterfacePtr(i,d); |
688 |
} |
689 |
if(d!=NULL){ |
690 |
d->status = s; |
691 |
} |
692 |
} |
693 |
|
694 |
/** |
695 |
Return the instance variable status. |
696 |
This data is stored in the 'interface_ptr' of the instance, so |
697 |
that we can be sure we'll get it, regardless of which |
698 |
instance of an Instanc we have in our hands :-) |
699 |
*/ |
700 |
const VarStatus |
701 |
Instanc::getVarStatus() const{ |
702 |
InstanceInterfaceData *d; |
703 |
d = (InstanceInterfaceData *)GetInterfacePtr(i); |
704 |
if(d==NULL){ |
705 |
return ASCXX_VAR_STATUS_UNKNOWN; |
706 |
} |
707 |
return d->status; |
708 |
} |
709 |
|
710 |
|
711 |
|
712 |
/*------------------------------------------------------ |
713 |
Macros to declare |
714 |
setUpperBound |
715 |
setLowerBound |
716 |
setNominal |
717 |
and their 'get' equivalents |
718 |
*/ |
719 |
|
720 |
#define DEFINE_GET_REAL_CHILD(METHOD,CHILD) \ |
721 |
const double \ |
722 |
Instanc::get##METHOD() const{ \ |
723 |
Instanc c = getChild(CHILD); \ |
724 |
return c.getRealValue(); \ |
725 |
} |
726 |
|
727 |
#define DEFINE_SET_REAL_CHILD(METHOD,CHILD) \ |
728 |
void \ |
729 |
Instanc::set##METHOD(const double &v){ \ |
730 |
Instanc c = getChild(CHILD); \ |
731 |
c.setRealValue(v); \ |
732 |
} |
733 |
|
734 |
#define DEFINE_CHILD_METHODS(D) \ |
735 |
D(LowerBound,"lower_bound") \ |
736 |
D(UpperBound,"upper_bound") \ |
737 |
D(Nominal,"nominal") |
738 |
|
739 |
DEFINE_CHILD_METHODS(DEFINE_SET_REAL_CHILD) |
740 |
DEFINE_CHILD_METHODS(DEFINE_GET_REAL_CHILD) |
741 |
|
742 |
//------------------------------------------------------ |
743 |
|
744 |
const vector<Instanc> |
745 |
Instanc::getClique() const{ |
746 |
vector<Instanc> v; |
747 |
struct Instance *i1 = i; |
748 |
do{ |
749 |
v.push_back(Instanc(i1)); |
750 |
i1=NextCliqueMember(i1); |
751 |
}while(i1 != i); // ie we've gone around the circuit |
752 |
return v; |
753 |
} |
754 |
|
755 |
//------------------------------------------------------ |
756 |
// static properties |
757 |
SymChar |
758 |
Instanc::fixedsym = SymChar("fixed"); |
759 |
|
760 |
SymChar |
761 |
Instanc::solvervarsym = SymChar("solver_var"); |