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

Contents of /trunk/pygtk/instance.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

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