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

Contents of /trunk/pygtk/interface/instance.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

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