/[ascend]/trunk/pygtk/instance.cpp
ViewVC logotype

Contents of /trunk/pygtk/instance.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1347 - (show annotations) (download) (as text)
Tue Mar 13 06:40:06 2007 UTC (13 years, 2 months ago) by jpye
File MIME type: text/x-c++src
File size: 18129 byte(s)
Added routine for outputting system as a DOT graph.
Changed an 'assert' to an 'asc_assert' in logrelation.c.
Changed logical relation in sequence.a4c (was causing a crash).
Added Simulation::write(FILE,char*) for outputting *stuff* from a simulation.
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(FILE *fp){
617 if(fp==NULL)fp=stderr;
618 WriteInstance(fp,i);
619 }
620
621 //----------------------------
622 // SETTING VALUES of stuff
623
624 void
625 Instanc::setFixed(const bool &val){
626 if(isFixed()==val)return;
627 CONSOLE_DEBUG("Fixing solver_var at %p",i);
628 getChild("fixed").setBoolValue(val);
629 }
630
631 void
632 Instanc::setBoolValue(const bool &val, const unsigned &depth){
633 SetBooleanAtomValue(i, val, depth);
634 }
635
636 void
637 Instanc::setRealValue(const double &val, const unsigned &depth){
638 SetRealAtomValue(i,val, depth);
639 //ERROR_REPORTER_HERE(ASC_USER_NOTE,"Set %s to %f",getName().toString(),val);
640 }
641
642 /**
643 Borrow the workings of this from tcltk UnitsProc.c
644 */
645 void
646 Instanc::setRealValueWithUnits(double val, const char *units, const unsigned &depth){
647
648 if(isConst()){
649 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Can't change the value of a constant");
650 return;
651 }
652
653 if(!isReal() || !isAtom()){
654 throw runtime_error("Instanc::setRealValueWithUnits: not a real-valued instance");
655 }
656
657 if(units == NULL || strlen(units)==0 || strcmp(units,"*")==0){
658 // No units were specified, so the base (SI) units are implied.
659 }else{
660 // We need to parse the units string
661 UnitsM u = UnitsM(units);
662 Dimensions d = u.getDimensions();
663
664 // If no dimensions yet assigned, assign them. Otheriwse check for consistency.
665 if(getDimensions().isWild()){
666 // Set the dimensions for a wildcard atom:
667 SetRealAtomDims(i, d.getInternalType());
668 }else if(d != getDimensions()){
669 throw runtime_error("Dimensionally incompatible units");
670 }
671
672 // Not going to worry about FPEs here, let the program crash if it must.
673 val = val * u.getConversion();
674 }
675
676 SetRealAtomValue(i,val,depth);
677 }
678
679 /**
680 Set the instance variable status. See @getVarStatus
681 */
682 void
683 Instanc::setVarStatus(const VarStatus &s){
684 InstanceInterfaceData *d;
685 d = (InstanceInterfaceData *)GetInterfacePtr(i);
686 if(d==NULL && s!=ASCXX_VAR_STATUS_UNKNOWN){
687 d = new InstanceInterfaceData();
688 SetInterfacePtr(i,d);
689 }
690 if(d!=NULL){
691 d->status = s;
692 }
693 }
694
695 /**
696 Return the instance variable status.
697 This data is stored in the 'interface_ptr' of the instance, so
698 that we can be sure we'll get it, regardless of which
699 instance of an Instanc we have in our hands :-)
700 */
701 const VarStatus
702 Instanc::getVarStatus() const{
703 InstanceInterfaceData *d;
704 d = (InstanceInterfaceData *)GetInterfacePtr(i);
705 if(d==NULL){
706 return ASCXX_VAR_STATUS_UNKNOWN;
707 }
708 return d->status;
709 }
710
711
712
713 /*------------------------------------------------------
714 Macros to declare
715 setUpperBound
716 setLowerBound
717 setNominal
718 and their 'get' equivalents
719 */
720
721 #define DEFINE_GET_REAL_CHILD(METHOD,CHILD) \
722 const double \
723 Instanc::get##METHOD() const{ \
724 Instanc c = getChild(CHILD); \
725 return c.getRealValue(); \
726 }
727
728 #define DEFINE_SET_REAL_CHILD(METHOD,CHILD) \
729 void \
730 Instanc::set##METHOD(const double &v){ \
731 Instanc c = getChild(CHILD); \
732 c.setRealValue(v); \
733 }
734
735 #define DEFINE_CHILD_METHODS(D) \
736 D(LowerBound,"lower_bound") \
737 D(UpperBound,"upper_bound") \
738 D(Nominal,"nominal")
739
740 DEFINE_CHILD_METHODS(DEFINE_SET_REAL_CHILD)
741 DEFINE_CHILD_METHODS(DEFINE_GET_REAL_CHILD)
742
743 //------------------------------------------------------
744
745 const vector<Instanc>
746 Instanc::getClique() const{
747 vector<Instanc> v;
748 struct Instance *i1 = i;
749 do{
750 v.push_back(Instanc(i1));
751 i1=NextCliqueMember(i1);
752 }while(i1 != i); // ie we've gone around the circuit
753 return v;
754 }
755
756 //------------------------------------------------------
757 // static properties
758 SymChar
759 Instanc::fixedsym = SymChar("fixed");
760
761 SymChar
762 Instanc::solvervarsym = SymChar("solver_var");

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22