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