/[ascend]/trunk/base/generic/solver/analyze.c
ViewVC logotype

Contents of /trunk/base/generic/solver/analyze.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1247 - (show annotations) (download) (as text)
Sat Jan 27 00:11:34 2007 UTC (16 years, 4 months ago) by johnpye
File MIME type: text/x-csrc
File size: 83055 byte(s)
Added 'hires.a4c' test model.
Split slv_system_structure out of slv.c and into system_impl.h.
Changed void* diffvars pointer in slv_system_structure to a typed pointer.
Moved SolverDiffVarCollectionStruct into system_impl.h.
Renamed slv_system_structure to just system_structure (in anticipation of a 'system' module separate from the actual solvers).
1 /* ASCEND modelling environment
2 Copyright (C) 2006 Carnegie Mellon University
3 Copyright (C) 1996 Benjamin Andrew Allan
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 *//**
20 @file
21 Problem Analysis Routines
22
23 @NOTE 'ip' signifies 'interface pointer' @ENDNOTE
24
25 The intent here is to do away with the old persistent interface pointer
26 scheme by making the struct rel_relation* individually keep track of the
27 map between the ascend RelationVariable list position and the
28 solver's var list index (and hence the column in jacobian for jacobian
29 involved clients).
30 In this mapping each struct relation* has its var list and this list
31 may contain RealAtomInstances that we don't consider variables.
32 In the rel_relation we will have the variable index list
33 which is an array of int32 the same length as the RelationVariable list.
34 In the array position 0 corresponds to RelationVariable 1 since the
35 compiler uses gl_lists. If in the variable index list we encounter
36 a number < 0 we know that that RelationVariable doesn't map to what
37 we consider a solver variable.
38
39 In the near future we may also add to the struct rel_relation *an array,
40 a, of int32 pairs like so:
41 vlindex | rvindex | vlindex | rvindex
42 and a length. This array could be built of the data for vars that pass
43 a filter provided by the client. This way a client could help us avoid
44 having to do if testing while stuffing jacobians.
45 In this scheme stuffing a jacobian row (or whatever) would simply mean
46 calling the compiler's derivative function (wrt RelationVariable list)
47
48 @code
49 which returns a vector d of values and then doing a loop:
50 for( i = 0 ; i < length; i++) { coord.row fixed already
51 coord.col = a[i++];
52 mtx_fill_org_value(mtx,&coord,d[a[i]])
53 }
54 }
55 @endcode
56
57 One begins to wonder if there isn't a better way to do all this, but
58 so far nothing has occurred.
59 The best way would be to feed clients only the block of stuff they
60 are interested in (no fixed, unattached vars or unincluded rels
61 or vars/rels solved in previous partitions) so that the solver
62 had no partitioning or var classification work to do except perhaps
63 classifying things as basic/nonbasic.
64
65 @see analyze.h
66 *//*
67 by Benjamin Andrew Allan 5/19/96
68 Last in CVS: $Revision: 1.56 $ $Date: 2003/08/23 18:43:12 $ $Author: ballan $
69 */
70
71 /** @addtogroup analyse Analyse
72 @{
73 */
74
75 #include "analyze.h"
76
77 #include <stdarg.h>
78
79 #include <utilities/ascPanic.h>
80 #include <utilities/ascMalloc.h>
81 #include <utilities/error.h>
82 #include <general/list.h>
83 #include <general/dstring.h>
84 #include <general/mathmacros.h>
85
86 #include <compiler/atomvalue.h>
87 #include <compiler/parentchild.h>
88 #include <compiler/visitinst.h>
89 #include <compiler/expr_types.h>
90 #include <compiler/exprs.h>
91 #include <compiler/sets.h>
92 #include <compiler/mathinst.h>
93 #include <compiler/instquery.h>
94 #include <compiler/instance_io.h>
95 #include <compiler/find.h>
96 #include <compiler/extfunc.h>
97 #include <compiler/extcall.h>
98 #include <compiler/rel_blackbox.h>
99 #include <compiler/vlist.h>
100 #include <compiler/relation.h>
101 #include <compiler/functype.h>
102 #include <compiler/safe.h>
103 #include <compiler/relation_util.h>
104 #include <compiler/logical_relation.h>
105 #include <compiler/logrelation.h>
106 #include <compiler/logrel_util.h>
107 #include <compiler/case.h>
108 #include <compiler/when_util.h>
109
110 #include <linear/mtx.h>
111
112 #include "slv_server.h"
113 #include "cond_config.h"
114 #include "diffvars.h"
115 #include "analyse_impl.h"
116
117 /* stuff to get rid of */
118 #ifndef MAX_VAR_IN_LIST
119 #define MAX_VAR_IN_LIST 20
120 #endif /* MAX_VAR_IN_LIST */
121 #define DEBUG_ANALYSIS FALSE
122
123 /*------------------------------------------------------------------------------
124 GLOBAL VARS
125 */
126
127 static symchar *g_strings[6];
128
129 /* symbol table entries we need */
130 #define INCLUDED_A g_strings[0]
131 #define FIXED_A g_strings[1]
132 #define BASIS_A g_strings[2]
133 #define DERIV_A g_strings[3]
134 #define ODEID_A g_strings[4]
135 #define OBSID_A g_strings[5]
136
137 /*
138 Global variable. Set to true by classify if need be
139 */
140 static int g_bad_rel_in_list;
141
142
143 /* used to give an integer value to each symbol used in a when */
144 struct gl_list_t *g_symbol_values_list = NULL;
145
146 /*-----------------------------------------------------------------------------
147 FORWARD DECLARATIONS
148 */
149 static void ProcessModelsInWhens(struct Instance *, struct gl_list_t *,
150 struct gl_list_t *, struct gl_list_t *);
151
152 /*------------------------------------------------------------------------------
153 SOME STUFF WITH INTERFACE POINTERS
154 */
155 /**
156 Return a pointer to the one-size-fits-all ips we're using.
157 Always returns non-NULL because if we run out we exit
158 */
159 static
160 struct solver_ipdata *analyze_getip(void){
161 if(g_reuse.ipbuf!=NULL && g_reuse.ipused < g_reuse.ipcap) {
162 return &(g_reuse.ipbuf[g_reuse.ipused++]);
163 }else{
164 ASC_PANIC("Too many ips requested by analyze_getip");
165 }
166 }
167
168 /**
169 Reallocates to the requested size (newcap) the ipbuf.
170 If newcap = 0, frees ipbuf.
171 If newcap > 0 and reset mem != 0, initializes ipbuf to 0s.
172 Resets ipused to 0.
173
174 @return 0 on success, 1 on insufficient memory
175 */
176 static
177 int resize_ipbuf(size_t newcap, int resetmem){
178 struct solver_ipdata *tmp;
179 if(newcap ==0) {
180 if(g_reuse.ipbuf != NULL) {
181 ascfree(g_reuse.ipbuf);
182 }
183 g_reuse.ipcap = g_reuse.ipused = 0;
184 g_reuse.ipbuf = NULL;
185 return 0;
186 }
187 if(newcap > g_reuse.ipcap) {
188 if( g_reuse.ipcap >0 ) {
189 tmp = (struct solver_ipdata *)
190 ascrealloc(g_reuse.ipbuf,newcap*sizeof(struct solver_ipdata));
191 if(tmp == NULL) {
192 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Insufficient memory.");
193 return 1;
194 }
195 g_reuse.ipbuf = tmp;
196 g_reuse.ipcap = newcap;
197 }else{
198 tmp = ASC_NEW_ARRAY(struct solver_ipdata,newcap);
199 if(tmp == NULL) {
200 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Insufficient memory.");
201 return 1;
202 }
203 g_reuse.ipbuf = tmp;
204 g_reuse.ipcap = newcap;
205 }
206 }
207 if(resetmem) {
208 memset((char *)g_reuse.ipbuf,0,
209 g_reuse.ipcap*sizeof(struct solver_ipdata));
210 }
211 g_reuse.ipused = 0;
212 return 0;
213 }
214
215 /*------------------------------------------------------------------------------
216 SOME STUFF TO DO WITH INCIDENCE SPACE
217 */
218
219 /*
220 checks size of request and returns a pointer to the next available
221 chunk of incidence space. if too much requested or 0 requested returns
222 NULL. p_data->relincidence must have been allocated for this to work.
223 */
224 static
225 struct var_variable **get_incidence_space(int len, struct problem_t *p_data){
226 struct var_variable **tmp;
227 if(p_data->relincidence == NULL) {
228 ASC_PANIC("get_incidence_space called prematurely. bye.\n");
229 }
230 if(len <1) return NULL;
231 if(p_data->relincinuse + len > p_data->relincsize) {
232 ERROR_REPORTER_HERE(ASC_PROG_ERR,"get_incidence_space called excessively.");
233 return NULL;
234 }
235 tmp = &(p_data->relincidence[p_data->relincinuse]);
236 p_data->relincinuse += len;
237 return tmp;
238 }
239
240 /*
241 checks size of request and returns a pointer to the next available
242 chunk of incidence space. if too much requested or 0 requested returns
243 NULL. p_data->varincidence must have been allocated for this to work.
244 */
245 static
246 struct rel_relation **get_var_incidence_space(int len
247 ,struct problem_t *p_data
248 ){
249 struct rel_relation **tmp;
250 if(p_data->varincidence == NULL) {
251 ASC_PANIC("get_var_incidence_space called prematurely. bye.\n");
252 }
253 if(len <1) return NULL;
254 if(p_data->varincinuse + len > p_data->varincsize) {
255 ERROR_REPORTER_HERE(ASC_PROG_ERR,"get_var_incidence_space called excessively.");
256 return NULL;
257 }
258 tmp = &(p_data->varincidence[p_data->varincinuse]);
259 p_data->varincinuse += len;
260 return tmp;
261 }
262
263
264 /*
265 p_data->logrelinciden must have been allocated for this to work.
266 */
267 static
268 struct dis_discrete **get_logincidence_space(int len
269 ,struct problem_t *p_data
270 ){
271 struct dis_discrete **tmp;
272 if(p_data->logrelinciden == NULL) {
273 ASC_PANIC("get_logincidence_space called prematurely. bye.\n");
274 }
275 if(len <1) return NULL;
276 if(p_data->lrelincinuse + len > p_data->lrelincsize) {
277 ERROR_REPORTER_HERE(ASC_PROG_ERR,"get_logincidence_space called excessively.");
278 return NULL;
279 }
280 tmp = &(p_data->logrelinciden[p_data->lrelincinuse]);
281 p_data->lrelincinuse += len;
282 return tmp;
283 }
284
285 /*------------------------------------------------------------------------------
286 SOME OTHER STUFF
287 */
288
289 /*
290 InitTreeCounts(i); This resets the pointers and counters in
291 p_data to null. p_data is supposed to be a temporary structure
292 so the memory management of the pointers in p_data is the job
293 of the caller.
294 p_data->root is set to i.
295 */
296 static
297 void InitTreeCounts(struct Instance *i,struct problem_t *p_data){
298 memset((char *)p_data,0,sizeof(struct problem_t));
299 p_data->root = i;
300 }
301
302 #define AVG_PARENTS 2
303 #define AVG_CHILDREN 4
304 #define AVG_RELATIONS 15
305 #define AVG_GROWTH 2
306 #define PART_THRESHOLD 1000
307
308 /**
309 @param i atom instance in the Instance hierarchy
310 @param sc name of an supposed child instance of i, a boolean atom.
311
312 @return the value of the named boolean child instance, or NULL if i or the child doesn't exist
313 */
314 static
315 int BooleanChildValue(struct Instance *i,symchar *sc){
316 if(i == NULL || sc == NULL || (i=ChildByChar(i,sc)) == NULL) {
317 return 0;
318 }else{
319 return ( GetBooleanAtomValue(i) );
320 }
321 }
322
323 /**
324 As for BooleanChildValue but for integer child atoms (ode_type in this case)
325 */
326 static
327 int IntegerChildValue(struct Instance *i,symchar *sc){
328 if(i == NULL || sc == NULL || (i=ChildByChar(i,sc)) == NULL) {
329 return 0;
330 }else{
331 return ( GetIntegerAtomValue(i) );
332 }
333 }
334
335
336 static
337 void CollectArrayRelsAndWhens(struct Instance *i, long modindex
338 ,struct problem_t *p_data
339 ){
340 struct Instance *child;
341 struct solver_ipdata *rip;
342 unsigned long nch,c;
343
344 if(i==NULL) return;
345 nch = NumberChildren(i);
346 for (c=1;c<=nch;c++) {
347 child = InstanceChild(i,c);
348 if(child==NULL) continue;
349 switch (InstanceKind(child)) {
350 case REL_INST:
351 rip = SIP(GetInterfacePtr(child));
352 if(rip->u.r.model == 0) {
353 rip->u.r.model = modindex;
354 }else{
355 /* ah hah! found an array with two distinct MODEL parents! skip it */
356 break;
357 }
358 if(rip->u.r.cond) {
359 gl_append_ptr(p_data->cnds,(VOIDPTR)rip);
360 }
361 else {
362 if(rip->u.r.obj) {
363 gl_append_ptr(p_data->objrels,(VOIDPTR)rip);
364 }else{
365 gl_append_ptr(p_data->rels,(VOIDPTR)rip);
366 }
367 }
368 break;
369 case LREL_INST:
370 rip = SIP(GetInterfacePtr(child));
371 if(rip->u.lr.model == 0) {
372 rip->u.lr.model = modindex;
373 }else{
374 break;
375 }
376 if(rip->u.lr.cond) {
377 gl_append_ptr(p_data->logcnds,(VOIDPTR)rip);
378 }
379 else {
380 gl_append_ptr(p_data->logrels,(VOIDPTR)rip);
381 }
382 break;
383 case WHEN_INST:
384 rip = SIP(GetInterfacePtr(child));
385 if(rip->u.w.model == 0) {
386 rip->u.w.model = modindex;
387 }else{
388 break;
389 }
390 gl_append_ptr(p_data->whens,(VOIDPTR)rip);
391 break;
392 case ARRAY_ENUM_INST:
393 case ARRAY_INT_INST:
394 if(ArrayIsRelation(child) ||
395 ArrayIsLogRel(child) ||
396 ArrayIsWhen(child)
397 ){
398 CollectArrayRelsAndWhens(child,modindex,p_data);
399 }
400 break;
401 default:
402 break;
403 }
404 }
405 }
406
407
408 /*
409 Collect all the logrels/relations at the local scope of the MODEL
410 associated with ip->i. Local scope includes arrays of logrels/relations,
411 mainly because these arrays don't have interface pointers so we
412 can't treat them separately.
413 */
414 static
415 void CollectRelsAndWhens(struct solver_ipdata *ip
416 ,long modindex
417 ,struct problem_t *p_data
418 ){
419 struct Instance *child;
420 struct solver_ipdata *rip;
421 unsigned long nch,c;
422
423 if(ip->i==NULL) return;
424 nch = NumberChildren(ip->i);
425 for (c=1;c<=nch;c++) {
426 child = InstanceChild(ip->i,c);
427 if(child==NULL) continue;
428 switch (InstanceKind(child)) {
429 case REL_INST:
430 rip = SIP(GetInterfacePtr(child));
431 rip->u.r.model = modindex;
432 if(rip->u.r.cond) {
433 gl_append_ptr(p_data->cnds,(VOIDPTR)rip);
434 }
435 else {
436 if(rip->u.r.obj) {
437 gl_append_ptr(p_data->objrels,(VOIDPTR)rip);
438 }else{
439 gl_append_ptr(p_data->rels,(VOIDPTR)rip);
440 }
441 }
442 break;
443 case LREL_INST:
444 rip = SIP(GetInterfacePtr(child));
445 rip->u.lr.model = modindex;
446 if(rip->u.lr.cond) {
447 gl_append_ptr(p_data->logcnds,(VOIDPTR)rip);
448 }
449 else {
450 gl_append_ptr(p_data->logrels,(VOIDPTR)rip);
451 }
452 break;
453 case WHEN_INST:
454 rip = SIP(GetInterfacePtr(child));
455 rip->u.w.model = modindex;
456 gl_append_ptr(p_data->whens,(VOIDPTR)rip);
457 break;
458 case ARRAY_ENUM_INST:
459 case ARRAY_INT_INST:
460 if(ArrayIsRelation(child) ||
461 ArrayIsLogRel(child)||
462 ArrayIsWhen(child)
463 ){
464 CollectArrayRelsAndWhens(child,modindex,p_data);
465 }
466 break;
467 default:
468 break;
469 }
470 }
471 }
472
473 /*
474 Count the instance into the required bin.
475
476 @NOTE Call only with good relation instances.
477 */
478 static void analyze_CountRelation(struct Instance *inst
479 ,struct problem_t *p_data
480 ){
481 switch( RelationRelop(GetInstanceRelationOnly(inst)) ) {
482 case e_maximize:
483 case e_minimize:
484 p_data->no++;
485 break;
486 case e_less: case e_lesseq:
487 case e_greater: case e_greatereq:
488 case e_equal: case e_notequal:
489 if( RelationIsCond(GetInstanceRelationOnly(inst)) ) {
490 p_data->nc++;
491 }
492 else {
493 p_data->nr++;
494 if( GetInstanceRelationType(inst)==e_blackbox ) {
495 p_data->ne++;
496 }
497 }
498 break;
499 default:
500 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unknown relation type in %s",__FUNCTION__);
501 }
502 }
503
504
505 /**
506 Obtain an integer value from a symbol value
507 Used for a WHEN statement. Each symbol value is storaged in a symbol list.
508 It checks if the symval is already in the solver symbol list,
509 if it is, returns the integer corresponding to the position of symval
510 if it is not, appends the symval to the list and then returns the int
511
512 @NOTE This is terrible inefficient as the number of symbols grows.
513 I am keeping it by now, are they going to be so many symbols in
514 whens anyway ?
515 */
516 int GetIntFromSymbol(CONST char *symval
517 ,struct gl_list_t *symbol_list
518 ){
519
520 struct SymbolValues *entry,*dummy;
521 unsigned long length;
522 int len,c,value;
523 int symbol_list_count;
524
525 if(symbol_list != NULL) {
526 len = gl_length(symbol_list);
527 for (c=1; c<= len; c++) {
528 dummy = (struct SymbolValues *)(gl_fetch(symbol_list,c));
529 if(!strcmp(dummy->name,symval)) {
530 return (dummy->value);
531 }
532 }
533 symbol_list_count = len;
534 }else{
535 symbol_list_count = 0;
536 symbol_list = gl_create(2L);
537 }
538 length = (unsigned long)strlen(symval);
539 length++;
540 symbol_list_count++;
541 entry = (struct SymbolValues *)ascmalloc(sizeof(struct SymbolValues));
542 entry->name = ASC_NEW_ARRAY(char,length);
543 strcpy(entry->name,symval);
544 entry->value = symbol_list_count;
545 value = entry->value;
546 gl_append_ptr(symbol_list,entry);
547 return value;
548 }
549
550 void DestroySymbolValuesList(struct gl_list_t *symbol_list)
551 {
552 struct SymbolValues *entry;
553 int len,c;
554 if(symbol_list != NULL) {
555 len = gl_length(symbol_list);
556 for (c=1; c<= len; c++) {
557 entry = (struct SymbolValues *)(gl_fetch(symbol_list,c));
558 ascfree((char *)entry->name); /* Do I need this ? */
559 ascfree((char *)entry);
560 }
561 gl_destroy(symbol_list);
562 symbol_list = NULL;
563 }
564 }
565
566 /*------------------------------------------------------------------------------
567 CLASSIFICATION OF INSTANCES, CREATING INTERFACE POINTERS
568 */
569
570 /*
571 classify_instance : to be called by PushInterfacePtrs.
572
573 This function classifies the given instance and appends into
574 the necessary list in the p_data structure.
575 It also sets returns a pointer to the caller for insertion into
576 the interface_ptr slot.
577
578 Note, we should be passing the ipbuf info via vp so we don't
579 need the nasty global variable and can be more thread safe.
580 vp is a struct problem_t.
581 */
582 static
583 void *classify_instance(struct Instance *inst, VOIDPTR vp){
584 struct solver_ipdata *ip;
585 struct problem_t *p_data;
586 CONST char *symval;
587
588 p_data = (struct problem_t *)vp;
589 switch( InstanceKind(inst) ) {
590 case REAL_ATOM_INST: /* Variable or parameter or real */
591 ip = analyze_getip();
592 ip->i = inst;
593 ip->u.v.incident = 0;
594 ip->u.v.in_block = 0;
595 ip->u.v.index = 0;
596 ip->u.v.active = 0;
597 if(solver_var(inst)){
598 ip->u.v.solvervar = 1; /* must set this regardless of what list */
599 ip->u.v.fixed = BooleanChildValue(inst,FIXED_A);
600 ip->u.v.basis = BooleanChildValue(inst,BASIS_A);
601 ip->u.v.deriv = IntegerChildValue(inst,DERIV_A);
602 ip->u.v.odeid = IntegerChildValue(inst,ODEID_A);
603 ip->u.v.obsid = IntegerChildValue(inst,OBSID_A);
604 /* CONSOLE_DEBUG("FOUND A VAR: deriv = %d, %s = %d",ip->u.v.deriv,SCP(ODEID_A),ip->u.v.odeid); */
605
606 if(RelationsCount(inst)) {
607 asc_assert((int)ip!=0x1);
608 gl_append_ptr(p_data->vars,(POINTER)ip);
609 }else{
610 gl_append_ptr(p_data->unas,(POINTER)ip);
611 }
612
613 if(ip->u.v.obsid){
614 gl_append_ptr(p_data->obsvars,(POINTER)ip);
615 CONSOLE_DEBUG("Added to obsvars");
616 }
617 /* make the algebraic/differential/derivative cut */
618 if(ip->u.v.odeid){
619 gl_append_ptr(p_data->diffvars,(POINTER)ip);
620 CONSOLE_DEBUG("Added var to diffvars");
621 }else{
622 if(ip->u.v.deriv==-1){
623 gl_append_ptr(p_data->indepvars,(POINTER)ip);
624 CONSOLE_DEBUG("Added to indep vars");
625 }else{
626 gl_append_ptr(p_data->algebvars,(POINTER)ip);
627 CONSOLE_DEBUG("Added var to algebvars");
628 }
629 }
630 }else{
631 ip->u.v.fixed = 1;
632 ip->u.v.solvervar=0;
633 if(solver_par(inst) && RelationsCount(inst)) {
634 gl_append_ptr(p_data->pars,(POINTER)ip);
635 }else{
636 gl_append_ptr(p_data->unas,(POINTER)ip);
637 }
638 }
639 return ip;
640 case BOOLEAN_ATOM_INST:
641 ip = analyze_getip();
642 ip->i = inst;
643 ip->u.dv.isconst = 0;
644 ip->u.dv.distype = 0;
645 ip->u.dv.incident = 0;
646 ip->u.dv.index = 0;
647 ip->u.dv.active = 0;
648 ip->u.dv.value = GetBooleanAtomValue(inst);
649 if(boolean_var(inst) ) {
650 ip->u.dv.booleanvar = 1;
651 ip->u.dv.fixed = BooleanChildValue(inst,FIXED_A);
652 }else{
653 ip->u.dv.fixed = 1;
654 ip->u.dv.booleanvar=0;
655 }
656 if(LogRelationsCount(inst) || WhensCount(inst) ) {
657 gl_append_ptr(p_data->dvars,(POINTER)ip);
658 if(WhensCount(inst) ) {
659 ip->u.dv.inwhen = 1;
660 }else{
661 ip->u.dv.inwhen = 0;
662 }
663 }else{
664 gl_append_ptr(p_data->dunas,(POINTER)ip);
665 }
666 return ip;
667 case BOOLEAN_CONSTANT_INST:
668 if(!WhensCount(inst))return NULL;
669 ip = analyze_getip();
670 ip->i = inst;
671 ip->u.dv.isconst = 1;
672 ip->u.dv.distype = 0;
673 ip->u.dv.index = 0;
674 ip->u.dv.incident = 0;
675 ip->u.dv.booleanvar=0;
676 ip->u.dv.fixed = 1;
677 ip->u.dv.active = 0;
678 ip->u.dv.value = GetBooleanAtomValue(inst);
679 gl_append_ptr(p_data->dvars,(POINTER)ip);
680 return ip;
681 case INTEGER_ATOM_INST:
682 if(!WhensCount(inst))return NULL;
683 ip = analyze_getip();
684 ip->i = inst;
685 ip->u.dv.isconst = 0;
686 ip->u.dv.distype = 1;
687 ip->u.dv.index = 0;
688 ip->u.dv.incident = 0;
689 ip->u.dv.booleanvar=0;
690 ip->u.dv.fixed = 0;
691 ip->u.dv.active = 0;
692 ip->u.dv.value = GetIntegerAtomValue(inst);
693 gl_append_ptr(p_data->dvars,(POINTER)ip);
694 return ip;
695 case SYMBOL_ATOM_INST:
696 if(!WhensCount(inst))return NULL;
697 symval = SCP(GetSymbolAtomValue(inst));
698 if(symval == NULL)return NULL;
699 ip = analyze_getip();
700 ip->i = inst;
701 ip->u.dv.isconst = 0;
702 ip->u.dv.distype = -1;
703 ip->u.dv.index = 0;
704 ip->u.dv.incident = 0;
705 ip->u.dv.booleanvar=0;
706 ip->u.dv.fixed = 0;
707 ip->u.dv.active = 0;
708 if(g_symbol_values_list == NULL) {
709 g_symbol_values_list = gl_create(2L);
710 }
711 ip->u.dv.value = GetIntFromSymbol(symval,g_symbol_values_list);
712 gl_append_ptr(p_data->dvars,(POINTER)ip);
713 return ip;
714 case INTEGER_CONSTANT_INST:
715 if(!WhensCount(inst))return NULL;
716 ip = analyze_getip();
717 ip->i = inst;
718 ip->u.dv.isconst = 1;
719 ip->u.dv.distype = 1;
720 ip->u.dv.index = 0;
721 ip->u.dv.incident = 0;
722 ip->u.dv.booleanvar=0;
723 ip->u.dv.fixed = 1;
724 ip->u.dv.active = 0;
725 ip->u.dv.value = GetIntegerAtomValue(inst);
726 gl_append_ptr(p_data->dvars,(POINTER)ip);
727 return ip;
728 case SYMBOL_CONSTANT_INST:
729 if(!WhensCount(inst))return NULL;
730 symval = SCP(GetSymbolAtomValue(inst));
731 if(symval==NULL)return NULL;
732 ip = analyze_getip();
733 ip->i = inst;
734 ip->u.dv.isconst = 1;
735 ip->u.dv.distype = -1;
736 ip->u.dv.index = 0;
737 ip->u.dv.incident = 0;
738 ip->u.dv.booleanvar=0;
739 ip->u.dv.fixed = 1;
740 ip->u.dv.active = 0;
741 if(g_symbol_values_list == NULL) {
742 g_symbol_values_list = gl_create(2L);
743 }
744 ip->u.dv.value = GetIntFromSymbol(symval,g_symbol_values_list);
745 gl_append_ptr(p_data->dvars,(POINTER)ip);
746 return ip;
747 case REL_INST: /* Relation (or conditional or objective) */
748 ip = analyze_getip();
749 ip->i = inst;
750 ip->u.r.active = 1;
751 switch(RelationRelop(GetInstanceRelationOnly(inst))) {
752 case e_minimize:
753 ip->u.r.obj = 1;
754 break;
755 case e_maximize:
756 ip->u.r.obj = -1;
757 break;
758 default:
759 ip->u.r.obj = 0;
760 break;
761 }
762 if(GetInstanceRelationType(inst)==e_blackbox){
763 ip->u.r.ext = 1;
764 }else{
765 ip->u.r.ext = 0;
766 }
767 if(RelationIsCond(GetInstanceRelationOnly(inst))){
768 ip->u.r.cond = 1;
769 }else{
770 ip->u.r.cond = 0;
771 }
772 if(WhensCount(inst)){
773 ip->u.r.inwhen = 1;
774 }else{
775 ip->u.r.inwhen = 0;
776 }
777 ip->u.r.included = BooleanChildValue(inst,INCLUDED_A);
778 ip->u.r.model = 0;
779 ip->u.r.index = 0;
780 return ip;
781 /* note we do NOT append it to lists here */
782 case LREL_INST: /* LogRelation */
783 ip = analyze_getip();
784 ip->i = inst;
785 ip->u.lr.active = 1;
786 if( LogRelIsCond(GetInstanceLogRel(inst)) ) {
787 ip->u.lr.cond = 1;
788 }else{
789 ip->u.lr.cond = 0;
790 }
791 if( WhensCount(inst) ) {
792 ip->u.lr.inwhen = 1;
793 }else{
794 ip->u.lr.inwhen = 0;
795 }
796 ip->u.lr.included = BooleanChildValue(inst,INCLUDED_A);
797 ip->u.lr.model = 0;
798 ip->u.lr.index = 0;
799 return ip;
800 /* note we do NOT append it to lists here */
801 case MODEL_INST:
802 ip = analyze_getip();
803 ip->i = inst;
804 ip->u.m.index = 0;
805 if( WhensCount(inst) ) {
806 ip->u.m.inwhen = 1;
807 }else{
808 ip->u.m.inwhen = 0;
809 }
810 gl_append_ptr(p_data->models,(POINTER)ip);
811 return ip;
812 case WHEN_INST:
813 ip = analyze_getip();
814 ip->i = inst;
815 ip->u.w.index = 0;
816 if( WhensCount(inst) ) {
817 ip->u.w.inwhen = 1;
818 }else{
819 ip->u.w.inwhen = 0;
820 }
821 return ip;
822 /* note we do NOT append it to lists here */
823 default:
824 return NULL;
825 }
826 }
827
828 /*------------------------------------------------------------------------------
829 MAKE PROBLEM routines
830 */
831
832 /*
833 This function sets g_bad_rel_in_list TRUE if it finds any unhappy
834 relations. All the rest of the code depends on ALL relations being
835 good, so don't disable the g_bad_rel_in_list feature.
836 */
837 static
838 void CountStuffInTree(struct Instance *inst, struct problem_t *p_data){
839 CONST char *symval;
840 if(inst!=NULL) {
841 switch (InstanceKind(inst)) {
842 case REL_INST:
843 if( GetInstanceRelationOnly(inst) == NULL ||
844 GetInstanceRelationType(inst) == e_undefined) {
845 /* guard against null relations, unfinished ones */
846 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
847 FPRINTF(ASCERR,"Found bad (unfinished?) relation '");
848 WriteInstanceName(ASCERR,inst,p_data->root);
849 FPRINTF(ASCERR,"' (in CountStuffInTree)");
850 error_reporter_end_flush();
851 g_bad_rel_in_list = TRUE;
852 return;
853 }
854 /* increment according to classification */
855 analyze_CountRelation(inst,p_data);
856 break;
857 case REAL_ATOM_INST:
858 if( solver_var(inst) && RelationsCount(inst)) {
859 p_data->nv++;
860 }else{
861 if(solver_par(inst) && RelationsCount(inst)) {
862 /* never passes right now */
863 p_data->np++;
864 }else{
865 p_data->nu++;
866 }
867 }
868 /* The use of RelationsCount is heuristic since vars may be
869 used in relations higher in the tree than the problem is rooted.
870 */
871 break;
872 case BOOLEAN_ATOM_INST:
873 if( ( boolean_var(inst) && LogRelationsCount(inst) ) ||
874 WhensCount(inst) ) {
875 p_data->ndv++;
876 }
877 else {
878 p_data->nud++;
879 }
880 break;
881 case BOOLEAN_CONSTANT_INST:
882 case INTEGER_ATOM_INST:
883 case INTEGER_CONSTANT_INST:
884 if(WhensCount(inst)) {
885 p_data->ndv++;
886 }
887 break;
888 case SYMBOL_ATOM_INST:
889 case SYMBOL_CONSTANT_INST:
890 if(WhensCount(inst)) {
891 symval = SCP(GetSymbolAtomValue(inst));
892 if(symval == NULL) {
893 ERROR_REPORTER_START_HERE(ASC_PROG_ERR);
894 FPRINTF(ASCERR,"CountStuffInTree found undefined symbol or symbol_constant in WHEN.\n");
895 WriteInstanceName(ASCERR,inst,p_data->root);
896 error_reporter_end_flush();
897 g_bad_rel_in_list = TRUE;
898 return;
899 }
900 p_data->ndv++;
901 }
902 break;
903 case LREL_INST:
904 if( GetInstanceLogRelOnly(inst) == NULL ) {
905 ERROR_REPORTER_START_HERE(ASC_PROG_ERR);
906 FPRINTF(ASCERR,"CountStuffInTree found bad logrel.\n");
907 WriteInstanceName(ASCERR,inst,p_data->root);
908 error_reporter_end_flush();
909 g_bad_rel_in_list = TRUE;
910 return;
911 }
912 if( LogRelIsCond(GetInstanceLogRel(inst)) ) {
913 p_data->ncl++;
914 }
915 else {
916 p_data->nl++;
917 }
918 break;
919 case WHEN_INST:
920 p_data->nw++;
921 break;
922 case MODEL_INST:
923 p_data->nm++;
924 break;
925 default:
926 break;
927 }
928 }
929 }
930
931
932 /**
933 Build 'master' lists of variables, relations, etc, from the Instance
934 hierarchy assigned to the problem p_data.
935
936 This takes the already derived counts,
937 allocates all the memory we need to allocate for master,
938 and actually builds the var/rel/MODEL/etc master lists,
939 filling in p_data and interface pointers as far as possible.
940
941 In particular, after this is done we have:
942
943 - vars with correct ip values for:
944 - index
945 - incident
946 - in_block
947 - fixed (as flag)
948 - basis (as flag)
949 - solvervar (as flag)
950 - relations and conditional relations with correct ip values for:
951 - index
952 - model
953 - obj (0 constraint, -1 maximize, +1 minimize)
954 - ext
955 - inwhen
956 - cond
957 - included (as flag)
958 - discrete vars with correct ip values for:
959 - index
960 - incident
961 - isconst
962 - distype
963 - fixed (as flag)
964 - booleanvar (as flag)
965 - inwhen
966 - logrelations and conditional logrelations with correct ip values for:
967 - index
968 - model
969 - included (as flag)
970 - inwhen
971 - cond
972 - whens with correct ip values for:
973 - index
974 - model
975 - inwhen
976 - models with correct ip values for:
977 - index
978
979 Note that these are all indexed from 1, being stored in gl_list structs (groan).
980
981 @param p_data partial problem definition, include Instance pointer and master list lengths assumed already computed.
982
983 @return 0 on success, 1 on insufficient memory (user should deallocate any partial results in
984 a separate cleanup function for p_data->), 2 if nothing to do.
985 */
986 static
987 int analyze_make_master_lists(struct problem_t *p_data){
988
989 long int c, len,v,vlen;
990 CONST struct Instance *i;
991 CONST struct relation *gut;
992 CONST struct logrelation *lgut;
993 struct solver_ipdata *vip;
994 struct gl_list_t *scratch;
995 size_t reqlen;
996 int stat;
997 reqlen =
998 p_data->nr + p_data->no + p_data->nc + p_data->nl+ p_data->ncl+ /*rels*/
999 p_data->nv + p_data->ndv +
1000 p_data->np + p_data->nu + p_data->nud + /* atoms */
1001 p_data->nw + /* when */
1002 p_data->nm; /* model */
1003 if(reqlen <1) {
1004 return 2;
1005 }
1006
1007 /* CREATE memory for ips */
1008 #ifdef NDEBUG
1009 stat = resize_ipbuf(reqlen,0);
1010 #else
1011 stat = resize_ipbuf(reqlen,1);
1012 #endif /* NDEBUG */
1013 if(stat) {
1014 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Insufficient memory.");
1015 return 1;
1016 }
1017
1018 #define CL(L,N) \
1019 p_data->L = gl_create(p_data->N); \
1020 if(p_data->vars == NULL)return 1
1021
1022 CL(vars,nv); /* variables */
1023 CL(dvars,ndv);/* discrete variables */
1024 CL(pars,np); /* parameters */
1025 CL(unas,nu); /* unattached */
1026 CL(dunas,nud);/* discrete unattached */
1027 CL(cnds,nc); /* conditional relations */
1028 CL(rels,nr); /* relations */
1029 CL(logrels,nl);/* logical relations */
1030 CL(diffvars,nr); /* differential variables */
1031 CL(algebvars,nr); /* differential variables */
1032 CL(indepvars,nr); /* independent variables */ /* @TODO there's wasted memory here */
1033 CL(obsvars,nr); /* observed variables */
1034 CL(logcnds,ncl);/* conditional logrelations */
1035 CL(extrels,ne); /* extrelations */
1036 CL(objrels,no); /* objectives */
1037 CL(whens,nw); /* whens */
1038 CL(models,nm); /* models */
1039 #undef CL
1040
1041 /* decorate the instance tree with ips, collecting vars and models. */
1042 p_data->oldips = PushInterfacePtrs(p_data->root,classify_instance,
1043 g_reuse.ipcap,1,p_data);
1044 if(p_data->oldips == NULL) {
1045 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Insufficient memory.");
1046 return 1;
1047 }
1048
1049 /*
1050 collect relations, objectives, logrels and whens recording the
1051 MODEL number in each rel's ip and setting incidence.
1052 */
1053 len = gl_length(p_data->models);
1054 for (c=1; c <= len; c++) {
1055 CollectRelsAndWhens(SIP(gl_fetch(p_data->models,c)),c,p_data);
1056 SIP(gl_fetch(p_data->models,c))->u.m.index = c;
1057 }
1058 if((long)gl_length(p_data->rels) != p_data->nr ||
1059 (long)gl_length(p_data->objrels) != p_data->no ||
1060 (long)gl_length(p_data->logrels) != p_data->nl ||
1061 (long)gl_length(p_data->whens) != p_data->nw
1062 ){
1063 ERROR_REPORTER_START_HERE(ASC_PROG_WARNING);
1064 FPRINTF(ASCERR,"Warning: Mismatch in problem census and problem found\n");
1065 FPRINTF(ASCERR,"Rels: Counted %lu\t Found %ld\n",gl_length(p_data->rels), p_data->nr);
1066 FPRINTF(ASCERR,"Objs: Counted %lu\t Found %ld\n",gl_length(p_data->objrels), p_data->no);
1067 FPRINTF(ASCERR,"LogRels: Counted %lu\t Found %ld\n",gl_length(p_data->logrels),p_data->nl);
1068 FPRINTF(ASCERR,"Whens: Counted %lu\t Found %ld\n",gl_length(p_data->whens), p_data->nw);
1069 error_reporter_end_flush();
1070
1071 }
1072 /*
1073 relation list is now grouped by model, and the order will be
1074 invariant with hardware and ascend invocation so long as
1075 set FIRSTCHOICE holds in compilation.
1076 */
1077 /* mark vars in constraints incident and index rels */
1078 len = gl_length(p_data->rels);
1079 for (c=1; c <= len; c++) {
1080 SIP(gl_fetch(p_data->rels,c))->u.r.index = c;
1081 gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->rels,c))->i);
1082 vlen = NumberVariables(gut);
1083 for( v = 1; v <= vlen; v++ ) {
1084 i = RelationVariable(gut,v);
1085 SIP(GetInterfacePtr(i))->u.v.incident = 1;
1086 }
1087 }
1088 /* mark vars in objectives incident */
1089 len = gl_length(p_data->objrels);
1090 for (c=1; c <= len; c++) {
1091 gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->objrels,c))->i);
1092 vlen = NumberVariables(gut);
1093 for( v = 1; v <= vlen; v++ ) {
1094 i = RelationVariable(gut,v);
1095 SIP(GetInterfacePtr(i))->u.v.incident = 1;
1096 }
1097 }
1098
1099 /* mark vars in conditional relations incident */
1100 len = gl_length(p_data->cnds);
1101 for (c=1; c <= len; c++) {
1102 SIP(gl_fetch(p_data->cnds,c))->u.r.index = c;
1103 gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->cnds,c))->i);
1104 vlen = NumberVariables(gut);
1105 for( v = 1; v <= vlen; v++ ) {
1106 i = RelationVariable(gut,v);
1107 SIP(GetInterfacePtr(i))->u.v.incident = 1;
1108 }
1109 }
1110
1111 /* mark dvars in logrels incident and index logrels */
1112 len = gl_length(p_data->logrels);
1113 for (c=1; c <= len; c++) {
1114 SIP(gl_fetch(p_data->logrels,c))->u.lr.index = c;
1115 lgut = GetInstanceLogRelOnly(SIP(gl_fetch(p_data->logrels,c))->i);
1116 vlen = NumberBoolVars(lgut);
1117 for( v = 1; v <= vlen; v++ ) {
1118 i = LogRelBoolVar(lgut,v);
1119 SIP(GetInterfacePtr(i))->u.dv.incident = 1;
1120 }
1121 }
1122
1123
1124 /* mark dvars in conditional logrels incident */
1125 len = gl_length(p_data->logcnds);
1126 for (c=1; c <= len; c++) {
1127 SIP(gl_fetch(p_data->logcnds,c))->u.lr.index = c;
1128 lgut = GetInstanceLogRelOnly(SIP(gl_fetch(p_data->logcnds,c))->i);
1129 vlen = NumberBoolVars(lgut);
1130 for( v = 1; v <= vlen; v++ ) {
1131 i = LogRelBoolVar(lgut,v);
1132 SIP(GetInterfacePtr(i))->u.dv.incident = 1;
1133 }
1134 }
1135
1136 /* mark index whens */
1137 len = gl_length(p_data->whens);
1138 for (c=1; c <= len; c++) {
1139 SIP(gl_fetch(p_data->whens,c))->u.w.index = c;
1140 }
1141 /*
1142 now we need to move all the nonincident vars off the var list
1143 onto the unas list. It is easiest to make a new list and copy
1144 the existing var list to either it if keep or unas if punt.
1145 the same goes for parameters that aren't incident.
1146 We don't do exactly the same for discrete variables because
1147 many of them are not incident but they are used in when's
1148 */
1149 len = gl_length(p_data->vars);
1150 p_data->tmplist = gl_create(len);
1151 if(p_data->tmplist == NULL) return 1;
1152 for (c=1; c <= len; c++) {
1153 /* dispose of var */
1154 vip = SIP(gl_fetch(p_data->vars,c));
1155 if( vip->u.v.incident == 1) {
1156 gl_append_ptr(p_data->tmplist,vip);
1157 }else{
1158 gl_append_ptr(p_data->unas,vip);
1159 }
1160 }
1161 gl_destroy(p_data->vars); /* punt the old list */
1162 p_data->vars = p_data->tmplist; /* make shortened list var list */
1163 p_data->tmplist = NULL;
1164
1165 p_data->nv = gl_length(p_data->vars);
1166
1167 len = gl_length(p_data->pars);
1168 p_data->tmplist = gl_create(len);
1169 if(p_data->tmplist == NULL){
1170 return 1;
1171 }
1172 for(c=1; c <= len; c++){
1173 /* dispose of par */
1174 vip = SIP(gl_fetch(p_data->pars,c));
1175 if( vip->u.v.incident == 1) {
1176 gl_append_ptr(p_data->tmplist,vip);
1177 }else{
1178 gl_append_ptr(p_data->unas,vip);
1179 }
1180 }
1181 gl_destroy(p_data->pars); /* punt the old list */
1182 p_data->pars = p_data->tmplist; /* make shortened list par list */
1183 p_data->tmplist = NULL;
1184
1185 p_data->np = gl_length(p_data->pars);
1186 p_data->nu = gl_length(p_data->unas);
1187
1188 /*
1189 discrete variables: take the incident dis vars in logrels first,
1190 then append the dis vars which are used only in whens
1191 */
1192 p_data->lrelinc = 0;
1193 len = gl_length(p_data->dvars);
1194 if( len > 0) {
1195 p_data->tmplist = gl_create(len);
1196 scratch = gl_create(2L);
1197 if(p_data->tmplist == NULL) return 1;
1198 for (c=1; c <= len; c++) {
1199 /* dispose of incident discrete vars */
1200 vip = SIP(gl_fetch(p_data->dvars,c));
1201 if( vip->u.dv.incident == 1) {
1202 gl_append_ptr(p_data->tmplist,vip);
1203 p_data->lrelinc++; /* Number of incident dis vars */
1204 }else{
1205 gl_append_ptr(scratch,vip);
1206 }
1207 }
1208 gl_destroy(p_data->dvars);
1209 p_data->dvars = p_data->tmplist;
1210 p_data->tmplist = NULL;
1211 /* append discrete non-boolean vars at the end of the list */
1212 len = gl_length(scratch);
1213 for (c=1; c <= len; c++) {
1214 vip = SIP(gl_fetch(scratch,c));
1215 gl_append_ptr(p_data->dvars,vip);
1216 }
1217 gl_destroy(scratch);
1218 scratch = NULL;
1219 }
1220
1221 /*
1222 The following patch is to avoid the system to crash.
1223 When multiple definitions of a solver_var have introduced into the
1224 system, ASCEND may fail in identifying that a REAL_ATOM is a refinement
1225 of a solver_var. This causes the system to think that, even that there
1226 are relations into the system, there are no incidences in these relations
1227 that fall into the category of a variable. As a consequence, the length
1228 of the list of variables is zero. That of course will introduce
1229 insanities while trying to build the slv system. Some
1230 solutions to this problem are:
1231
1232 The easier for us is just to alert the user and to force him/her to
1233 reload all the type defintions again. That is the current solution
1234
1235 The correct (but time consuming) solution is the implementation of a
1236 SolverAtomInstance, which still needs parser and interpreter support
1237 */
1238
1239 if(p_data->nr != 0 && p_data->nv==0) {
1240 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
1241 FPRINTF(ASCERR,"Problem should contain at least one variable and one relation.\n");
1242 FPRINTF(ASCERR,"There are relations into the system, but the number\n");
1243 FPRINTF(ASCERR,"of variables is zero. That means that the existent\n");
1244 FPRINTF(ASCERR,"vars were not recognized as solver_vars. A possible\n");
1245 FPRINTF(ASCERR,"reason is that you have introduced conflicting\n");
1246 FPRINTF(ASCERR,"definitions of solver_var into the system. Please\n");
1247 FPRINTF(ASCERR,"delete all your types and reload your models\n");
1248 FPRINTF(ASCERR,"with the appropriate definition of solver_var\n");
1249 FPRINTF(ASCERR,"Solver system will not be built.");
1250 error_reporter_end_flush();
1251 return 2;
1252 }
1253
1254 return 0;
1255 }
1256
1257 /**
1258 This function cleans up an errant problem_t or a good one that we're
1259 done with. We should have set to null any pointers to memory we are
1260 keeping elsewhere before calling this.
1261 */
1262 static
1263 void analyze_free_lists(struct problem_t *p_data){
1264
1265 /* memory containing gl_lists of atomic structure pointers */
1266 /* if(p_data->extrels != NULL)gl_free_and_destroy(p_data->extrels); */
1267
1268 if(p_data->extrels!=NULL)gl_destroy(p_data->extrels); /* -- JP HACK */
1269
1270 #define AFUN(P) if(p_data->P!=NULL) ascfree(p_data->P); (p_data->P) = NULL
1271 #define ADUN(P) if(p_data->P!=NULL) gl_destroy(p_data->P); (p_data->P) = NULL
1272
1273 /* gl_lists without memory items use ADUN */
1274 ADUN(vars); ADUN(dvars); ADUN(pars);
1275 ADUN(unas); ADUN(dunas); ADUN(rels);
1276 ADUN(objrels); ADUN(models); ADUN(cnds);
1277 ADUN(logrels); ADUN(logcnds); ADUN(whens);
1278 ADUN(diffvars);
1279 ADUN(algebvars);
1280 ADUN(indepvars);
1281 ADUN(obsvars); /* observed variables */
1282
1283 /* blocks of memory use AFUN */
1284 AFUN(blocks); AFUN(reldata); AFUN(objdata);
1285 AFUN(condata); AFUN(lrdata); AFUN(logcondata);
1286 AFUN(vardata); AFUN(pardata); AFUN(undata);
1287 AFUN(disdata); AFUN(undisdata); AFUN(whendata);
1288 AFUN(bnddata); AFUN(relincidence); AFUN(varincidence);
1289 AFUN(logrelinciden);
1290 /* these variable names are a %*@#$ abomination */
1291 AFUN(mastervl); AFUN(masterdl); AFUN(masterrl);
1292 AFUN(masterol); AFUN(mastercl); AFUN(masterll);
1293 AFUN(mastercll); AFUN(masterpl); AFUN(masterul);
1294 AFUN(masterdul); AFUN(masterwl); AFUN(masterbl);
1295 AFUN(solvervl); AFUN(solverdl); AFUN(solverrl);
1296 AFUN(solverol); AFUN(solvercl); AFUN(solverll);
1297 AFUN(solvercll); AFUN(solverpl); AFUN(solverul);
1298 AFUN(solverdul); AFUN(solverwl); AFUN(solverbl);
1299
1300 #undef AFUN
1301 #undef ADUN
1302 }
1303
1304
1305 /*------------------------------------------------------------------------------
1306 'WHEN' PROCESSING
1307 */
1308
1309 /**
1310 This function receives as argument the list of values of each of the
1311 CASES of a WHEN statement. The values in the list can be integer values,
1312 symbol values, or boolean values. So, the goal of this function is to
1313 obtain an equivalent list of ONLY integer values for such a list. In this
1314 way, for example, the boolean value TRUE is equivalent to the integer
1315 1. The function GentIntFromSymbol is used to generate an integer value
1316 which will be equivalent to a symbol value
1317 */
1318 static
1319 void ProcessValueList(struct Set *ValueList, int *value
1320 ,struct gl_list_t *symbol_list
1321 ){
1322 CONST struct Expr *expr;
1323 struct Set *s;
1324
1325 s = ValueList;
1326 if(ValueList!=NULL) {
1327 while (s != NULL) {
1328 expr = GetSingleExpr(s);
1329 switch(ExprType(expr)) {
1330 case e_boolean:
1331 *value = ExprBValue(expr);
1332 if(*value == 2) { /* ANY */
1333 *value = -2;
1334 }
1335 break;
1336 case e_int:
1337 *value = ExprIValue(expr);
1338 break;
1339 case e_symbol:
1340 *value = GetIntFromSymbol(SCP(ExprSymValue(expr)),symbol_list);
1341 break;
1342 default:
1343 break;
1344 }
1345 s = NextSet(s);
1346 value++;
1347 }
1348 }else{
1349 *value = -1; /* OTHERWISE */
1350 }
1351 }
1352
1353
1354 /**
1355 Process arrays inside WHENs (requires a recursive analysis).
1356
1357 @see ProcessSolverWhens
1358 */
1359 static
1360 void ProcessArraysInWhens(struct Instance *cur_inst
1361 ,struct gl_list_t *rels
1362 ,struct gl_list_t *logrels
1363 ,struct gl_list_t *whens
1364 ){
1365 struct rel_relation *rel;
1366 struct logrel_relation *lrel;
1367 struct w_when *w;
1368 struct Instance *child;
1369 struct solver_ipdata *ip;
1370 unsigned long c,nch;
1371
1372 if(cur_inst==NULL) return;
1373 nch = NumberChildren(cur_inst);
1374 for (c=1;c<=nch;c++) {
1375 child = InstanceChild(cur_inst,c);
1376 if(child==NULL) continue;
1377 switch (InstanceKind(child)) {
1378 case REL_INST:
1379 ip = SIP(GetInterfacePtr(child));
1380 ip->u.r.active = 0;
1381 rel = ip->u.r.data;
1382 gl_append_ptr(rels,rel);
1383 break;
1384 case LREL_INST:
1385 ip = SIP(GetInterfacePtr(child));
1386 ip->u.lr.active = 0;
1387 lrel = ip->u.lr.data;
1388 gl_append_ptr(logrels,lrel);
1389 break;
1390 case WHEN_INST:
1391 ip = SIP(GetInterfacePtr(child));
1392 w = ip->u.w.data;
1393 gl_append_ptr(whens,w);
1394 when_set_inwhen(w,TRUE);
1395 break;
1396 case MODEL_INST:
1397 ProcessModelsInWhens(child,rels,logrels,whens);
1398 break;
1399 case ARRAY_ENUM_INST:
1400 case ARRAY_INT_INST:
1401 if(ArrayIsRelation(child) || ArrayIsWhen(child)
1402 || ArrayIsLogRel(child) || ArrayIsModel(child)) {
1403 ProcessArraysInWhens(child,rels,logrels,whens);
1404 }
1405 break;
1406 default:
1407 break;
1408 }
1409 }
1410 }
1411
1412 /**
1413 Process MODELs inside WHENs (requires a recursive analysis).
1414
1415 @see ProcessSolverWhens
1416 */
1417 static
1418 void ProcessModelsInWhens(struct Instance *cur_inst, struct gl_list_t *rels
1419 ,struct gl_list_t *logrels, struct gl_list_t *whens
1420 ){
1421 struct rel_relation *rel;
1422 struct logrel_relation *lrel;
1423 struct w_when *w;
1424 struct Instance *child;
1425 struct solver_ipdata *ip;
1426 unsigned long c,nch;
1427
1428 if(cur_inst==NULL) return;
1429 nch = NumberChildren(cur_inst);
1430 for (c=1;c<=nch;c++) {
1431 child = InstanceChild(cur_inst,c);
1432 if(child==NULL) continue;
1433 switch (InstanceKind(child)) {
1434 case REL_INST:
1435 ip = SIP(GetInterfacePtr(child));
1436 ip->u.r.active = 0;
1437 rel = ip->u.r.data;
1438 gl_append_ptr(rels,rel);
1439 break;
1440 case LREL_INST:
1441 ip = SIP(GetInterfacePtr(child));
1442 ip->u.lr.active = 0;
1443 lrel = ip->u.lr.data;
1444 gl_append_ptr(logrels,lrel);
1445 break;
1446 case WHEN_INST:
1447 ip = SIP(GetInterfacePtr(child));
1448 w = ip->u.w.data;
1449 gl_append_ptr(whens,w);
1450 when_set_inwhen(w,TRUE);
1451 break;
1452 case MODEL_INST:
1453 ProcessModelsInWhens(child,rels,logrels,whens);
1454 break;
1455 case ARRAY_ENUM_INST:
1456 case ARRAY_INT_INST:
1457 if(ArrayIsRelation(child) || ArrayIsWhen(child)
1458 || ArrayIsLogRel(child) || ArrayIsModel(child)) {
1459 ProcessArraysInWhens(child,rels,logrels,whens);
1460 }
1461 break;
1462 default:
1463 break;
1464 }
1465 }
1466 }
1467
1468
1469 /**
1470 Fill in the list of cases and variables of a w_when structure with
1471 the appropriate data.
1472
1473 The information required is provided by the corresponding when Instance
1474 generated in the compilation time. So, what we do is:
1475 1) Obtain the list of variables and the list of cases from each
1476 WHEN intance.
1477 The list of variables is actually a list of pointers to instances
1478 2) From each CASE, obtain also the list of references. This list of
1479 references contains a list of pointers to each relation,logrelation and
1480 model included inside the case.
1481 3) The pointers to the variables, relations, logrelations and models are
1482 used to obtain the solver data associated with the compiled instances.
1483 4) Arrays and models are managed recursively with the two previous
1484 functions.
1485 */
1486 static
1487 void ProcessSolverWhens(struct w_when *when,struct Instance *i){
1488 struct gl_list_t *scratch;
1489 struct gl_list_t *wvars;
1490 struct gl_list_t *ref;
1491 struct gl_list_t *rels;
1492 struct gl_list_t *logrels;
1493 struct gl_list_t *whens;
1494 struct gl_list_t *diswhens;
1495 struct Set *ValueList;
1496 struct Instance *cur_inst;
1497 struct Case *cur_case;
1498 struct solver_ipdata *ip;
1499 struct dis_discrete *dvar;
1500 struct rel_relation *rel;
1501 struct logrel_relation *lrel;
1502 struct w_when *w;
1503 struct when_case *cur_sol_case;
1504 int c,r,len,lref;
1505 int *value;
1506
1507 scratch = GetInstanceWhenVars(i);
1508 len = gl_length(scratch);
1509 wvars = gl_create(len);
1510 when->dvars = wvars;
1511 for(c=1;c<=len;c++){
1512 cur_inst = (struct Instance *)(gl_fetch(scratch,c));
1513 ip = SIP(GetInterfacePtr(cur_inst));
1514 dvar = ip->u.dv.data;
1515 if(dis_whens_list(dvar)==NULL){
1516 diswhens = gl_create(2L);
1517 dis_set_whens_list(dvar,diswhens);
1518 }else{
1519 diswhens = dis_whens_list(dvar);
1520 }
1521 gl_append_ptr(diswhens,when);
1522 gl_append_ptr(when->dvars,dvar);
1523 }
1524
1525 scratch = GetInstanceWhenCases(i);
1526 len = gl_length(scratch);
1527 when->cases = gl_create(len);
1528 for (c=1;c<=len;c++) {
1529 cur_sol_case = when_case_create(NULL);
1530 cur_case = (struct Case *)(gl_fetch(scratch,c));
1531 ValueList = GetCaseValues(cur_case);
1532 value = &(cur_sol_case->values[0]);
1533 if(g_symbol_values_list == NULL) {
1534 g_symbol_values_list = gl_create(2L);
1535 }
1536 ProcessValueList(ValueList,value,g_symbol_values_list);
1537 ref = GetCaseReferences(cur_case);
1538 lref = gl_length(ref);
1539 rels = gl_create(lref); /* maybe allocating less than needed (models) */
1540 logrels = gl_create(lref); /* maybe allocating less than needed */
1541 whens = gl_create(lref); /* maybe allocating more than needed */
1542 for(r=1;r<=lref;r++){
1543 cur_inst = (struct Instance *)(gl_fetch(ref,r));
1544 switch(InstanceKind(cur_inst)){
1545 case REL_INST:
1546 ip = SIP(GetInterfacePtr(cur_inst));
1547 ip->u.r.active = 0;
1548 rel = ip->u.r.data;
1549 gl_append_ptr(rels,rel);
1550 break;
1551 case LREL_INST:
1552 ip = SIP(GetInterfacePtr(cur_inst));
1553 ip->u.lr.active = 0;
1554 lrel = ip->u.lr.data;
1555 gl_append_ptr(logrels,lrel);
1556 break;
1557 case WHEN_INST:
1558 ip = SIP(GetInterfacePtr(cur_inst));
1559 w = ip->u.w.data;
1560 gl_append_ptr(whens,w);
1561 when_set_inwhen(w,TRUE);
1562 break;
1563 case MODEL_INST:
1564 ProcessModelsInWhens(cur_inst,rels,logrels,whens);
1565 break;
1566 default:
1567 break;
1568 }
1569 }
1570 when_case_set_rels_list(cur_sol_case,rels);
1571 when_case_set_logrels_list(cur_sol_case,logrels);
1572 when_case_set_whens_list(cur_sol_case,whens);
1573 when_case_set_active(cur_sol_case,FALSE);
1574 gl_append_ptr(when->cases,cur_sol_case);
1575 }
1576 }
1577
1578 /*------------------------------------------------------------------------------
1579 RECONFIGURATION OF CONDITIONAL MODELS
1580 */
1581
1582 /**
1583 Is this (discrete) variable inside a WHEN?
1584
1585 @return
1586 1 if discrete var is a member of the when var list,
1587 else 0
1588
1589 @DEPRECATED we want to get rid of this in order to clean up the
1590 solver interface (divorce it from dependencies on compiler)
1591 */
1592 int dis_var_in_a_when(struct Instance *var, struct w_when *when){
1593 struct Instance *winst;
1594
1595 winst = (struct Instance *)(when_instance(when));
1596 return VarFoundInWhen(var,winst);
1597 }
1598
1599
1600 /**
1601 Determine if the conditional variable inst is part of the
1602 variable list of some when in the when list.
1603
1604 @DEPRECATED we want to get rid of this in order to clean up the
1605 solver interface (divorce it from dependencies on compiler)
1606 */
1607 int varinst_found_in_whenlist(slv_system_t sys, struct Instance *inst){
1608 struct w_when **whenlist;
1609 struct w_when *when;
1610 int c;
1611
1612 whenlist = slv_get_solvers_when_list(sys);
1613 for (c=0; whenlist[c]!=NULL; c++) {
1614 when = whenlist[c];
1615 if(dis_var_in_a_when(inst,when)) {
1616 return 1;
1617 }
1618 }
1619 return 0;
1620 }
1621
1622 /*------------------------------------------------------------------------------
1623 BOUNDARY PROCESSING
1624 */
1625
1626 /**
1627 Get the list or logrelation including a boundary (by means of a
1628 SATISFIED term). This function look the structures in the compiler
1629 side and make the same link in the solver side
1630 */
1631 static
1632 void GetListOfLogRels(struct bnd_boundary *bnd, struct Instance *inst){
1633 struct gl_list_t *logrels;
1634 unsigned long c,len;
1635 struct Instance *i;
1636 struct logrel_relation *lrel;
1637 struct solver_ipdata *lrip;
1638
1639 len = LogRelationsCount(inst);
1640
1641 if(len>0) {
1642 logrels = gl_create(len);
1643 for (c=1; c<=len; c++) {
1644 i = LogRelationsForInstance(inst,c);
1645 lrip = SIP(GetInterfacePtr(i));
1646 lrel = lrip->u.lr.data;
1647 gl_append_ptr(logrels,lrel);
1648 }
1649 bnd_set_logrels(bnd,logrels);
1650 }
1651 return;
1652 }
1653
1654 /**
1655 Get the tolerance used to define the satisfaction of a boundary
1656 (Defined in the SATISFIED term)
1657 */
1658 static
1659 void GetTolerance(struct bnd_boundary *bnd){
1660 struct gl_list_t *logrels;
1661 unsigned long c,len;
1662 struct logrel_relation *lrel;
1663 struct Instance *i,*rel;
1664 double tolerance;
1665
1666 rel = (struct Instance *)(rel_instance(bnd_rel(bnd_real_cond(bnd))));
1667 logrels = bnd_logrels(bnd);
1668 len = gl_length(logrels);
1669 for (c=1; c<=len; c++) {
1670 lrel = (struct logrel_relation *)(gl_fetch(logrels,c));
1671 i = (struct Instance *)(logrel_instance(lrel));
1672 if(FindTolInSatTermOfLogRel(i,rel,&tolerance )) {
1673 bnd_set_tolerance(bnd,tolerance);
1674 return;
1675 }
1676 }
1677 }
1678
1679 /*----------------------------------------------------------------------------*/
1680
1681 /**
1682 Here we roll the master lists and bridge data into relation/var/
1683 logrelation/conditional/when etc. lists for the consumer.
1684 Includes fixing up rel caches and initing flagbits as best we can.
1685 includes setting master indices on rel/var/logrel/when etc.
1686
1687 @returns 0 on success, 1 on out-of-memory, or 2 if the problem does not
1688 contain at least one variable in one equation
1689 */
1690 static
1691 int analyze_make_solvers_lists(struct problem_t *p_data){
1692 CONST struct relation *gut;
1693 CONST struct logrelation *lgut;
1694 struct Instance *i;
1695 struct Instance *i_r;
1696 struct solver_ipdata *rip = NULL, *vip;
1697 struct solver_ipdata *lrip, *dvip, *wip;
1698 struct var_variable **incidence = NULL;
1699 struct rel_relation **varincidence = NULL;
1700 struct dis_discrete **logincidence = NULL;
1701 struct var_variable *var;
1702 struct rel_relation *rel;
1703 struct dis_discrete *dvar;
1704 struct logrel_relation *lrel;
1705 struct bnd_boundary *bnd;
1706 struct w_when *when;
1707 int order,nnzold;
1708 int logorder,lognnzold;
1709 int c,len,v,vlen,r,found;
1710 uint32 flags;
1711
1712 order = MAX(gl_length(p_data->vars),gl_length(p_data->rels));
1713 nnzold = p_data->nnz = p_data->nnztot
1714 = p_data->nnzobj = p_data->nnzcond = 0;
1715 p_data->nrow = 0; /* number of included relations */
1716 /* loop through the relations we found */
1717 for (c=1,len = gl_length(p_data->rels); c <= len; c++) {
1718 rip = SIP(gl_fetch(p_data->rels,c));
1719 gut = GetInstanceRelationOnly(rip->i);
1720 /* nnztot includes all vars in all relations */
1721 vlen = NumberVariables(gut);
1722 p_data->nnztot += vlen;
1723 if(rip->u.r.included) {
1724 p_data->nrow++;
1725 nnzold = p_data->nnz;
1726 for( v = 1 ; v <= vlen; v++ ) {
1727 i = RelationVariable(gut,v);
1728 vip = SIP(GetInterfacePtr(i));
1729 if(!(vip->u.v.fixed)) {
1730 /* nnz includes only FREE vars in INCLUDE relations */
1731 p_data->nnz++;
1732 }
1733 }
1734 if(p_data->nnz==nnzold){
1735 ERROR_REPORTER_START_NOLINE(ASC_USER_WARNING);
1736 FPRINTF(ASCERR,"No free variables found in included relation '");
1737 WriteInstanceName(ASCERR,rip->i,p_data->root);
1738 FPRINTF(ASCERR,"'");
1739 error_reporter_end_flush();
1740 }
1741 }
1742 }
1743
1744 /* count the objective relations */
1745 for (c=1,len = gl_length(p_data->objrels); c <= len; c++) {
1746 rip = SIP(gl_fetch(p_data->objrels,c));
1747 gut = GetInstanceRelationOnly(rip->i);
1748 vlen = NumberVariables(gut);
1749 p_data->nnzobj += vlen;
1750 }
1751
1752 /* count the conditional relations */
1753 for (c=1,len = gl_length(p_data->cnds); c <= len; c++) {
1754 rip = SIP(gl_fetch(p_data->cnds,c));
1755 gut = GetInstanceRelationOnly(rip->i);
1756 vlen = NumberVariables(gut);
1757 p_data->nnzcond += vlen;
1758 }
1759
1760 /* count ncol, the number of non-FIXED incident variables. note that
1761 non-incident variables are already taken out, in the unas list. */
1762 for (c=1,len = gl_length(p_data->vars); c <= len; c++) {
1763 vip = SIP(gl_fetch(p_data->vars,c));
1764 if(!(vip->u.v.fixed)) p_data->ncol++;
1765 }
1766
1767 /*
1768 now, at last we have cols jacobian in the order we want the lists to
1769 be handed to the solvers.
1770 */
1771
1772 /* count the incidences of bool vars and logrels */
1773 logorder = MAX((unsigned long)p_data->lrelinc,gl_length(p_data->logrels));
1774 lognnzold = p_data->lognnz = p_data->lrelincsize = 0;
1775 p_data->lognrow = 0; /* number of included logrelations */
1776 for (c=1,len = gl_length(p_data->logrels); c <= len; c++) {
1777 lrip = SIP(gl_fetch(p_data->logrels,c));
1778 lgut = GetInstanceLogRelOnly(lrip->i);
1779 /* lrelincsize includes all boolean vars in all logical relations */
1780 vlen = NumberBoolVars(lgut);
1781 p_data->lrelincsize += vlen;
1782 if(lrip->u.lr.included) {
1783 p_data->lognrow++;
1784 lognnzold = p_data->lognnz;
1785 for( v = 1 ; v <= vlen; v++ ) {
1786 i = LogRelBoolVar(lgut,v);
1787 dvip = SIP(GetInterfacePtr(i));
1788 if(!(dvip->u.dv.fixed)) {
1789 /* lognnz includes only FREE bools from INCLUDED logrels */
1790 p_data->lognnz++;
1791 }
1792 }
1793 if(p_data->lognnz==lognnzold) {
1794 ERROR_REPORTER_START_NOLINE(ASC_PROG_WARNING);
1795 FPRINTF(ASCERR,"No free boolean variables in included logrelation:");
1796 WriteInstanceName(ASCWAR,rip->i,p_data->root);
1797 error_reporter_end_flush();
1798 }
1799 }
1800 }
1801
1802 /* count conditional logrels */
1803 for (c=1,len = gl_length(p_data->logcnds); c <= len; c++) {
1804 lrip = SIP(gl_fetch(p_data->logcnds,c));
1805 lgut = GetInstanceLogRelOnly(lrip->i);
1806 vlen = NumberBoolVars(lgut);
1807 p_data->lrelincsize += vlen;
1808 }
1809
1810 /* ensure that we have at least one var-in-a-rel, or at least one bool var
1811 in a logrel */
1812 if(!(p_data->nnztot+p_data->nnzobj) && !(p_data->lognnz)) {
1813 ERROR_REPORTER_HERE(ASC_PROG_ERR
1814 ,"Problem should contain at least one variable and one relation."
1815 );
1816 return 2;
1817 }
1818
1819 /* calculate the number of free and incident boolean variables, logncol */
1820 for (c=1,len = p_data->lrelinc; c <= len; c++) {
1821 dvip = SIP(gl_fetch(p_data->dvars,c));
1822 if(!(dvip->u.dv.fixed)) p_data->logncol++;
1823 }
1824
1825 /* allocate space for the lists that we will eventually hand over to slv.
1826 now malloc and build things, remember to punt the matrix soon.
1827 remember we must NEVER free these things individually. */
1828
1829 #define ALLOC_OR_NULL(T,N) ((N) > 0 ? ASC_NEW_ARRAY(T,N) : (T*)NULL)
1830
1831 #define AL(P,N,T) p_data->P##data = ALLOC_OR_NULL(struct T,p_data->N)
1832 AL(var,nv,var_variable); AL(par,np,var_variable); AL(un,nu,var_variable);
1833 AL(dis,ndv,dis_discrete); AL(undis,nud,dis_discrete);
1834 AL(rel,nr,rel_relation); AL(obj,no,rel_relation); AL(con,nc,rel_relation);
1835 AL(lr,nl,logrel_relation); AL(logcon,ncl,logrel_relation);
1836 AL(when,nw,w_when);
1837 AL(bnd,nc + p_data->ncl,bnd_boundary);
1838 #undef AL
1839
1840 #define AL(P,N,T) p_data->master##P=ALLOC_OR_NULL(struct T*,p_data->N + 1)
1841 AL(vl,nv,var_variable); AL(pl,np,var_variable); AL(ul,nu,var_variable);
1842 AL(dl,ndv,dis_discrete); AL(dul,nud,dis_discrete);
1843 AL(rl,nr,rel_relation); AL(ol,no,rel_relation); AL(cl,nc,rel_relation);
1844 AL(ll,nl,logrel_relation); AL(cll,ncl,logrel_relation);
1845 AL(wl,nw,w_when);
1846 AL(bl,nc + p_data->ncl,bnd_boundary);
1847 #undef AL
1848
1849 #define AL(P,N,T) p_data->solver##P=ALLOC_OR_NULL(struct T*,p_data->N + 1)
1850 AL(vl,nv,var_variable); AL(pl,np,var_variable); AL(ul,nu,var_variable);
1851 AL(dl,ndv,dis_discrete); AL(dul,nud,dis_discrete);
1852 AL(rl,nr,rel_relation); AL(ol,no,rel_relation); AL(cl,nc,rel_relation);
1853 AL(ll,nl,logrel_relation); AL(cll,ncl,logrel_relation);
1854 AL(wl,nw,w_when);
1855 AL(bl,nc + p_data->ncl,bnd_boundary);
1856 #undef AL
1857
1858 p_data->relincidence = ALLOC_OR_NULL(struct var_variable*
1859 ,p_data->nnztot + p_data->nnzobj + p_data->nnzcond
1860 );
1861
1862 p_data->logrelinciden = ALLOC_OR_NULL(
1863 struct dis_discrete *
1864 ,p_data->lrelincsize
1865 );
1866
1867 /* check that lists have been allocated whereever number of expected elements > 0 */
1868 #define C(N,P) if((p_data->N)>0 && (p_data->P##data)==NULL)return 1
1869 C(nv,var); C(np,par); C(nu,un);
1870 C(ndv,dis); C(nud,undis);
1871 C(nr,rel); C(no,obj); C(nc,con);
1872 C(nl,lr); C(ncl,logcon);
1873 C(nw,when);
1874 C(nc + p_data->ncl,bnd);
1875 #undef C
1876
1877 /* check that all master lists were assigned */
1878 #define C(P) if((p_data->master##P)==NULL)return 1
1879 C(vl); C(pl); C(ul);
1880 C(dl); C(dul);
1881 C(rl); C(ol); C(cl);
1882 C(ll); C(cll);
1883 C(wl);
1884 C(bl);
1885 #undef C
1886
1887 /* check that all the solver's lists were assigned */
1888 #define C(P) if((p_data->solver##P)==NULL)return 1
1889 C(vl); C(pl); C(ul);
1890 C(dl); C(dul);
1891 C(rl); C(ol); C(cl);
1892 C(ll); C(cll);
1893 C(wl);
1894 C(bl);
1895 #undef C
1896
1897 if(p_data->relincidence==NULL)return 1;
1898 if(p_data->lrelincsize > 0 && p_data->logrelinciden==NULL) return 1;
1899
1900 p_data->relincsize = p_data->nnztot+p_data->nnzobj + p_data->nnzcond;
1901 p_data->relincinuse = 0;
1902 p_data->lrelincinuse = 0;
1903
1904 /*-------*/
1905 /*
1906 for c in varlist copy vardata. remember gllist # from 1 and data from 0
1907 */
1908 /*
1909 for c in varlist set mastervl, solvervl pointer to point to data
1910 */
1911 vlen = gl_length(p_data->vars);
1912 for (v = 0; v < vlen; v++) {
1913 /* CONSOLE_DEBUG("VAR %d",v); */
1914 var = &(p_data->vardata[v]);
1915 vip = SIP(gl_fetch(p_data->vars,v+1));
1916 vip->u.v.data = var;
1917 var_set_instance(var,vip->i);
1918 var_set_mindex(var,v);
1919 var_set_sindex(var,v);
1920 flags = 0; /* all init to FALSE */
1921 /* turn on appropriate ones */
1922 if(vip->u.v.incident) flags |= VAR_INCIDENT;
1923 if(vip->u.v.in_block) flags |= VAR_INBLOCK;
1924 if(vip->u.v.fixed) flags |= VAR_FIXED;
1925 if(!vip->u.v.basis) flags |= VAR_NONBASIC;
1926 if(vip->u.v.solvervar) flags |= VAR_SVAR;
1927 if(vip->u.v.deriv > 1) flags |= VAR_DERIV; /* so that we can do relman_diffs with just the ydot vars */
1928
1929 var_set_flags(var,flags);
1930 p_data->mastervl[v] = var;
1931 p_data->solvervl[v] = var;
1932 }
1933 p_data->mastervl[vlen] = NULL; /* terminator */
1934 p_data->solvervl[vlen] = NULL; /* terminator */
1935 /*
1936 for c in parlist copy pardata. remember gllist # from 1 and data from 0
1937 for c in parlist set masterpl, solverpl pointer to point to data
1938 */
1939 vlen = gl_length(p_data->pars);
1940 for (v = 0; v < vlen; v++) {
1941 var = &(p_data->pardata[v]);
1942 vip = SIP(gl_fetch(p_data->pars,v+1));
1943 vip->u.v.data = var;
1944 var_set_instance(var,vip->i);
1945 var_set_mindex(var,v);
1946 var_set_sindex(var,v);
1947 flags = 0; /* all init to FALSE */
1948 /* turn on appropriate ones */
1949 if(vip->u.v.incident) flags |= VAR_INCIDENT;
1950 if(vip->u.v.in_block) flags |= VAR_INBLOCK;
1951 if(vip->u.v.fixed) flags |= VAR_FIXED;
1952 if(vip->u.v.solvervar) flags |= VAR_SVAR; /* shouldn't this be here? */
1953 var_set_flags(var,flags);
1954 p_data->masterpl[v] = var;
1955 p_data->solverpl[v] = var;
1956 }
1957 p_data->masterpl[vlen] = NULL; /* terminator */
1958 p_data->solverpl[vlen] = NULL; /* terminator */
1959 /*
1960 for c in unalist copy undata. remember gllist # from 1 and data from 0
1961 for c in unalist set masterul, solverul pointer to point to data
1962 */
1963 vlen = gl_length(p_data->unas);
1964 for (v = 0; v < vlen; v++) {
1965 var = &(p_data->undata[v]);
1966 vip = SIP(gl_fetch(p_data->unas,v+1));
1967 vip->u.v.data = var;
1968 var_set_instance(var,vip->i);
1969 var_set_mindex(var,v);
1970 var_set_sindex(var,v);
1971 flags = 0; /* all init to FALSE */
1972 /* turn on appropriate ones */
1973 if(vip->u.v.incident) flags |= VAR_INCIDENT;
1974 if(vip->u.v.fixed) flags |= VAR_FIXED;
1975 if(vip->u.v.solvervar) flags |= VAR_SVAR;
1976 /* CONSOLE_DEBUG("VAR AT %p IS UNASSIGNED",var); */
1977 /* others may be appropriate (PVAR) */
1978 var_set_flags(var,flags);
1979 p_data->masterul[v] = var;
1980 p_data->solverul[v] = var;
1981 }
1982 p_data->masterul[vlen] = NULL; /* terminator */
1983 p_data->solverul[vlen] = NULL; /* terminator */
1984
1985 /*
1986 process the constraining relations
1987 for v in rellist copy reldata and fix extrels.
1988 */
1989 vlen = gl_length(p_data->rels);
1990 for (v = 0; v < vlen; v++) {
1991 rel = &(p_data->reldata[v]);
1992 rip = SIP(gl_fetch(p_data->rels,v+1));
1993 rel = rel_create(rip->i,rel);
1994 rip->u.r.data = rel;
1995 rel_set_mindex(rel,v);
1996 rel_set_sindex(rel,v);
1997 rel_set_model(rel,rip->u.r.model-1);
1998 /* here set up the var list */
1999 gut = GetInstanceRelationOnly(rip->i);
2000 assert(gut!=NULL);
2001 len = NumberVariables(gut);
2002 /* CONSOLE_DEBUG("FOR REL INSTANCE AT %p, NUM INCID VARS= %d",rip->i, len); */
2003 if(len > 0) {
2004 incidence = get_incidence_space(len,p_data);
2005 for( c = 0; c < len; c++ ) {
2006 i = RelationVariable(gut,c+1);
2007 /* CONSOLE_DEBUG("INCIDENCE OF REL INSTANCE %p WITH VAR %p",rip->i,i); */
2008 incidence[c] = SIP(GetInterfacePtr(i))->u.v.data;
2009 }
2010 /* CONSOLE_DEBUG("SETTING INCIDENCES FOR CONSTRAINING REL"); */
2011 rel_set_incidences(rel,len,incidence);
2012 }else{
2013 rel_set_incidences(rel,0,NULL);
2014 }
2015 flags = 0; /* all init to FALSE */
2016 /* TURN ON APPROPRIATE ONES */
2017 if(rip->u.r.included) flags |= (REL_INCLUDED | REL_INBLOCK);
2018 if(rip->u.r.ext) flags |= REL_BLACKBOX;
2019 if(rip->u.r.active) flags |= ( REL_ACTIVE | REL_INVARIANT);
2020 if(rip->u.r.inwhen) flags |= REL_INWHEN;
2021 if( RelationRelop(GetInstanceRelationOnly(rip->i)) == e_equal ) {
2022 flags |= REL_EQUALITY;
2023 }
2024 rel_set_flags(rel,flags);
2025 /* for c in rellist set masterrl, solverrl pointer to point to data */
2026 p_data->masterrl[v] = rel;
2027 p_data->solverrl[v] = rel;
2028 }
2029 p_data->masterrl[vlen] = NULL; /* terminator */
2030 p_data->solverrl[vlen] = NULL; /* terminator */
2031
2032 /*
2033 for c in objlist copy objdata.
2034 for c in objlist set masterrl, solverrl pointer to point to data.
2035 */
2036 /*
2037 process the objective relations
2038 for v in objlist copy objdata
2039 */
2040 vlen = gl_length(p_data->objrels);
2041 found = 0;
2042 for (v = 0; v < vlen; v++) {
2043 rel = &(p_data->objdata[v]);
2044 rip = SIP(gl_fetch(p_data->objrels,v+1));
2045 rel = rel_create(rip->i,rel);
2046 rip->u.r.data = rel;
2047 rel_set_mindex(rel,v);
2048 rel_set_sindex(rel,v);
2049 rel_set_model(rel,rip->u.r.model-1);
2050 /* here set up the var list */
2051 gut = GetInstanceRelationOnly(rip->i);
2052 assert(gut!=NULL);
2053 len = NumberVariables(gut);
2054 if(len > 0) {
2055 incidence = get_incidence_space(len,p_data);
2056 for( c = 0; c < len; c++ ) {
2057 i = RelationVariable(gut,c+1);
2058 incidence[c] = SIP(GetInterfacePtr(i))->u.v.data;
2059 }
2060 /* CONSOLE_DEBUG("SETTING INCIDENCES FOR OBJECTIVE FN REL"); */
2061 rel_set_incidences(rel,len,incidence);
2062 }else{
2063 rel_set_incidences(rel,0,NULL);
2064 }
2065 /* black box objectives not supported. skip it */
2066 flags = 0; /* all init to FALSE */
2067 /* TURN ON APPROPRIATE ONES */
2068 if(rip->u.r.included) {
2069 flags |= (REL_INCLUDED | REL_INBLOCK | REL_ACTIVE);
2070 }
2071 if(rip->u.r.obj < 0) flags |= REL_OBJNEGATE;
2072 rel_set_flags(rel,flags);
2073 /* for c in objrellist set masterol, solverol pointer to point to data */
2074 p_data->masterol[v] = rel;
2075 p_data->solverol[v] = rel;
2076 /* set objective to first included objective on list */
2077 if(!found && (rip->u.r.included)) {
2078 p_data->obj = rel;
2079 found = 1;
2080 }
2081 }
2082 p_data->masterol[vlen] = NULL; /* terminator */
2083 p_data->solverol[vlen] = NULL; /* terminator */
2084
2085 /*
2086 process the conditional relations
2087 for v in cndlist copy conddata .
2088 */
2089 vlen = gl_length(p_data->cnds);
2090 for (v = 0; v < vlen; v++) {
2091 rel = &(p_data->condata[v]);
2092 rip = SIP(gl_fetch(p_data->cnds,v+1));
2093 rel = rel_create(rip->i,rel);
2094 rip->u.r.data = rel;
2095 rel_set_mindex(rel,v);
2096 rel_set_sindex(rel,v);
2097 rel_set_model(rel,rip->u.r.model-1);
2098 gut = GetInstanceRelationOnly(rip->i);
2099 assert(gut!=NULL);
2100 len = NumberVariables(gut);
2101 if(len > 0) {
2102 incidence = get_incidence_space(len,p_data);
2103 for( c = 0; c < len; c++ ) {
2104 i = RelationVariable(gut,c+1);
2105 incidence[c] = SIP(GetInterfacePtr(i))->u.v.data;
2106 }
2107 /* CONSOLE_DEBUG("SETTING INCIDENCES FOR CONDITIONAL REL"); */
2108 rel_set_incidences(rel,len,incidence);
2109 }else{
2110 rel_set_incidences(rel,0,NULL);
2111 }
2112 flags = 0; /* all init to FALSE */
2113 /* TURN ON APPROPRIATE ONES */
2114 if(rip->u.r.included) {
2115 flags |= (REL_INCLUDED | REL_INBLOCK | REL_ACTIVE);
2116 }
2117 if(rip->u.r.cond) flags |= REL_CONDITIONAL;
2118 if( RelationRelop(GetInstanceRelationOnly(rip->i)) == e_equal ) {
2119 flags |= REL_EQUALITY;
2120 }
2121 rel_set_flags(rel,flags);
2122 /* for c in rellist set masterrl, solverrl pointer to point to data */
2123 p_data->mastercl[v] = rel;
2124 p_data->solvercl[v] = rel;
2125 /* initially in same order */
2126 }
2127 p_data->mastercl[vlen] = NULL; /* terminator */
2128 p_data->solvercl[vlen] = NULL; /* terminator */
2129
2130 /*-------*/
2131
2132 /*
2133 process discrete variables
2134 for c in dvarlist copy disdata. gllist # from 1 and data from 0
2135 for c in dvarlist set masterdl, solverdl pointer to point to data
2136 */
2137 vlen = gl_length(p_data->dvars);
2138 for (v = 0; v < vlen; v++) {
2139 dvar = &(p_data->disdata[v]);
2140 dvip = SIP(gl_fetch(p_data->dvars,v+1));
2141 /*
2142 dvip->u.dv.data = dvar;
2143 dis_set_instance(dvar,dvip->i); */
2144 /* from here */
2145 dis_create(dvip->i,dvar);
2146 dvip->u.dv.data = dvar;
2147 /* to here */
2148 dis_set_mindex(dvar,v);
2149 dis_set_sindex(dvar,v);
2150 dis_set_value(dvar,dvip->u.dv.value);
2151 dis_set_previous_value(dvar,dvip->u.dv.value);
2152 switch (dvip->u.dv.distype) {
2153 case 0:
2154 dis_set_kind(dvar,e_dis_boolean_t);
2155 break;
2156 case 1:
2157 dis_set_kind(dvar,e_dis_integer_t);
2158 break;
2159 case -1:
2160 dis_set_kind(dvar,e_dis_symbol_t);
2161 break;
2162 default:
2163 break;
2164 }
2165 flags = 0; /* all init to FALSE */
2166 /* turn on appropriate ones */
2167 if(dvip->u.dv.isconst) flags |= DIS_CONST;
2168 if(dvip->u.dv.incident) flags |= DIS_INCIDENT;
2169 if(dvip->u.dv.inwhen) flags |= DIS_INWHEN;
2170 if(dvip->u.dv.fixed) flags |= DIS_FIXED;
2171 if(dvip->u.dv.booleanvar) flags |= DIS_BVAR;
2172 if(dis_kind(dvar) == e_dis_boolean_t) flags |= DIS_BOOLEAN;
2173 dis_set_flags(dvar,flags);
2174 p_data->masterdl[v] = dvar;
2175 p_data->solverdl[v] = dvar;
2176 /* initially master and solver look the same */
2177 }
2178 p_data->masterdl[vlen] = NULL; /* terminator */
2179 p_data->solverdl[vlen] = NULL; /* terminator */
2180
2181 /*
2182 for c in dunalist copy undisdata. gllist # from 1 and data from 0
2183 for c in dunalist set masterdul, solverdul pointer to point to data
2184 */
2185 vlen = gl_length(p_data->dunas);
2186 for (v = 0; v < vlen; v++) {
2187 dvar = &(p_data->undisdata[v]);
2188 dvip = SIP(gl_fetch(p_data->dunas,v+1));
2189 dis_create(dvip->i,dvar);
2190 dvip->u.dv.data = dvar;
2191 dis_set_mindex(dvar,v);
2192 dis_set_sindex(dvar,v);
2193 flags = 0; /* all init to FALSE */
2194 /* turn on appropriate ones */
2195 if(dvip->u.dv.fixed) flags |= DIS_FIXED;
2196 if(dvip->u.dv.booleanvar) flags |= DIS_BVAR;
2197 dis_set_flags(dvar,flags);
2198 p_data->masterdul[v] = dvar;
2199 p_data->solverdul[v] = dvar;
2200 }
2201 p_data->masterdul[vlen] = NULL; /* terminator */
2202 p_data->solverdul[vlen] = NULL; /* terminator */
2203
2204
2205 /*
2206 for c in logrellist copy lrdata.
2207 for c in logrellist set masterll, solverll pointer to point to data.
2208 */
2209 /*
2210 process the logical relations
2211 for v in logrellist copy lrdata
2212 */
2213 vlen = gl_length(p_data->logrels);
2214 for (v = 0; v < vlen; v++) {
2215 lrel = &(p_data->lrdata[v]);
2216 lrip = SIP(gl_fetch(p_data->logrels,v+1));
2217 lrel = logrel_create(lrip->i,lrel);
2218 lrip->u.lr.data = lrel;
2219 logrel_set_mindex(lrel,v);
2220 logrel_set_sindex(lrel,v);
2221 logrel_set_model(lrel,lrip->u.lr.model-1);
2222 /* here set up the dis var list */
2223 lgut = GetInstanceLogRelOnly(lrip->i);
2224 assert(lgut!=NULL);
2225 len = NumberBoolVars(lgut);
2226 if(len > 0) {
2227 logincidence = get_logincidence_space(len,p_data);
2228 for( c = 0; c < len; c++ ) {
2229 i = LogRelBoolVar(lgut,c+1);
2230 logincidence[c] = SIP(GetInterfacePtr(i))->u.dv.data;
2231 }
2232 logrel_set_incidences(lrel,len,logincidence);
2233 }else{
2234 logrel_set_incidences(lrel,0,NULL);
2235 }
2236 flags = 0; /* all init to FALSE */
2237 /* TURN ON APPROPRIATE ONES */
2238 if(lrip->u.lr.included) flags |= LOGREL_INCLUDED;
2239 if(lrip->u.lr.active) flags |= LOGREL_ACTIVE;
2240 if(lrip->u.lr.inwhen) flags |= LOGREL_INWHEN;
2241 if( LogRelRelop(GetInstanceLogRelOnly(lrip->i)) == e_boolean_eq ) {
2242 flags |= LOGREL_EQUALITY;
2243 }
2244 logrel_set_flags(lrel,flags);
2245 /* for c in logrellist set masterll, solverll pointer to point to data */
2246 p_data->masterll[v] = lrel;
2247 p_data->solverll[v] = lrel;
2248 }
2249 p_data->masterll[vlen] = NULL; /* terminator */
2250 p_data->solverll[vlen] = NULL; /* terminator */
2251
2252
2253 /*
2254 process the conditional logrelations
2255 for v in logcndlist copy logconddata
2256 */
2257 vlen = gl_length(p_data->logcnds);
2258 for (v = 0; v < vlen; v++) {
2259 lrel = &(p_data->logcondata[v]);
2260 lrip = SIP(gl_fetch(p_data->logcnds,v+1));
2261 lrel = logrel_create(lrip->i,lrel);
2262 lrip->u.lr.data = lrel;
2263 logrel_set_mindex(lrel,v);
2264 logrel_set_sindex(lrel,v);
2265 logrel_set_model(lrel,lrip->u.lr.model-1);
2266 lgut = GetInstanceLogRelOnly(lrip->i);
2267 assert(lgut!=NULL);
2268 len = NumberBoolVars(lgut);
2269 if(len > 0) {
2270 logincidence = get_logincidence_space(len,p_data);
2271 for( c = 0; c < len; c++ ) {
2272 i = LogRelBoolVar(lgut,c+1);
2273 logincidence[c] = SIP(GetInterfacePtr(i))->u.dv.data;
2274 }
2275 logrel_set_incidences(lrel,len,logincidence);
2276 }else{
2277 logrel_set_incidences(lrel,0,NULL);
2278 }
2279 flags = 0; /* all init to FALSE */
2280 /* TURN ON APPROPRIATE ONES */
2281 if(lrip->u.lr.included) flags |= (LOGREL_INCLUDED | LOGREL_ACTIVE);
2282 if(lrip->u.lr.cond) flags |= LOGREL_CONDITIONAL;
2283 if( LogRelRelop(GetInstanceLogRelOnly(lrip->i)) == e_boolean_eq) {
2284 flags |= LOGREL_EQUALITY;
2285 }
2286 logrel_set_flags(lrel,flags);
2287 /* for c in lrellist set masterll, solverll pointer to point to data */
2288 p_data->mastercll[v] = lrel;
2289 p_data->solvercll[v] = lrel;
2290 /* initially in same order */
2291 }
2292 p_data->mastercll[vlen] = NULL; /* terminator */
2293 p_data->solvercll[vlen] = NULL; /* terminator */
2294
2295
2296 /*
2297 process the boundaries
2298 for v in cndlist and logcndlist, copy bnddata.
2299 */
2300 vlen = gl_length(p_data->cnds);
2301 len = gl_length(p_data->logcnds);
2302 /* real conditions */
2303 for (v = 0; v < vlen; v++) {
2304 bnd = &(p_data->bnddata[v]);
2305 bnd = bnd_create(bnd);
2306 bnd_set_kind(bnd,e_bnd_rel);
2307 rip = SIP(gl_fetch(p_data->cnds,v+1));
2308 bnd_real_cond(bnd) = bnd_rel(rip->u.r.data);
2309 bnd_set_mindex(bnd,v);
2310 bnd_set_sindex(bnd,v);
2311 bnd_set_model(bnd,rip->u.r.model-1);
2312 flags = 0; /* all init to FALSE */
2313 flags |= BND_REAL;
2314 bnd_set_flags(bnd,flags);
2315 /* for c in lrellist set masterbl, solverbl pointer to point to data */
2316 p_data->masterbl[v] = bnd;
2317 p_data->solverbl[v] = bnd;
2318 }
2319 /* logical conditions */
2320 for (v = vlen; v <vlen+len; v++) {
2321 bnd = &(p_data->bnddata[v]);
2322 bnd = bnd_create(bnd);
2323 bnd_set_kind(bnd,e_bnd_logrel);
2324 lrip = SIP(gl_fetch(p_data->logcnds,v-vlen+1));
2325 bnd_log_cond(bnd) = bnd_logrel(lrip->u.lr.data);
2326 bnd_set_mindex(bnd,v);
2327 bnd_set_sindex(bnd,v);
2328 bnd_set_model(bnd,lrip->u.lr.model-1);
2329 flags = 0; /* all init to FALSE */
2330 bnd_set_flags(bnd,flags);
2331 /* for c in lrellist set masterbl, solverbl pointer to point to data */
2332 p_data->masterbl[v] = bnd;
2333 p_data->solverbl[v] = bnd;
2334 }
2335 p_data->masterbl[vlen+len] = NULL; /* terminator */
2336 p_data->solverbl[vlen+len] = NULL; /* terminator */
2337
2338 /*
2339 Finding list of logical relations using the condition, and the
2340 tolerance (only for the case of real condition ). Defining some
2341 flags
2342 */
2343
2344 for (v = 0; v < vlen; v++) {
2345 bnd = p_data->masterbl[v];
2346 rel = bnd_rel(bnd_real_cond(bnd));
2347 flags = bnd_flags(bnd);
2348 if(rel_equality(rel)) {
2349 flags |= BND_EQUALITY;
2350 }
2351 i = (struct Instance *)rel_instance(rel);
2352 GetListOfLogRels(bnd,i);
2353 if(bnd_logrels(bnd)!= NULL) {
2354 flags |= BND_IN_LOGREL;
2355 GetTolerance(bnd);
2356 }
2357 bnd_set_flags(bnd,flags);
2358 }
2359 for (v = vlen; v < vlen+len; v++) {
2360 bnd = p_data->masterbl[v];
2361 lrel = bnd_logrel(bnd_log_cond(bnd));
2362 flags = bnd_flags(bnd);
2363 if(logrel_equality(lrel)) {
2364 flags |= BND_EQUALITY;
2365 }
2366 i = (struct Instance *)logrel_instance(lrel);
2367 GetListOfLogRels(bnd,i);
2368 if(bnd_logrels(bnd)!= NULL) {
2369 flags |= BND_IN_LOGREL;
2370 }
2371 bnd_set_flags(bnd,flags);
2372 }
2373
2374 /*
2375 for c in whenlist copy whendata.
2376 for c in whenllist set masterwl, solverwl pointer to point to data.
2377 */
2378 /* process whens */
2379
2380 vlen = gl_length(p_data->whens);
2381 for (v = 0; v < vlen; v++) {
2382 when = &(p_data->whendata[v]);
2383 wip = SIP(gl_fetch(p_data->whens,v+1));
2384 when = when_create(wip->i,when);
2385 wip->u.w.data = when;
2386 when_set_mindex(when,v);
2387 when_set_sindex(when,v);
2388 when_set_model(when,wip->u.w.model-1);
2389 p_data->masterwl[v] = when;
2390 p_data->solverwl[v] = when;
2391 flags = 0;
2392 if(wip->u.w.inwhen) flags |= WHEN_INWHEN;
2393 when_set_flags(when,flags);
2394 }
2395 p_data->masterwl[vlen] = NULL; /* terminator */
2396 p_data->solverwl[vlen] = NULL; /* terminator */
2397
2398 /*
2399 Get data from the when instance to fill the
2400 list in the w_when instance
2401 */
2402
2403 for (v = 0; v < vlen; v++) {
2404 when = p_data->masterwl[v];
2405 i = (struct Instance *)(when_instance(when));
2406 ProcessSolverWhens(when,i);
2407 }
2408
2409 /* configure the problem */
2410
2411 if(vlen > 0) { /* we have whens */
2412 configure_conditional_problem(vlen,p_data->masterwl,
2413 p_data->solverrl,p_data->solverll,
2414 p_data->mastervl);
2415 /* Is consistency analysis required ? */
2416 p_data->need_consistency = 0;
2417 for (v = 0; v < vlen; v++) {
2418 when = p_data->masterwl[v];
2419 if(when_changes_structure(when)) {
2420 p_data->need_consistency = 1;
2421 break;
2422 }
2423 }
2424
2425 #if DEBUG_ANALYSIS
2426 if( p_data->need_consistency == 0 ) {
2427 CONSOLE_DEBUG("All alternativeS HAVE THE SAME STRUCTURE: Consistency"
2428 " analysis is not required \n"
2429 );
2430 }else{
2431 CONSOLE_DEBUG("Consistency analysis may be required \n");
2432 }
2433 #endif /* DEBUG_ANALYSIS */
2434
2435 }else{
2436
2437 /*
2438 All variables in active relations are set as active.
2439 This is necessary because the existence of some variables
2440 in conditional relations which should not be active.
2441
2442 Before we were doing:
2443
2444 for (v = 0;p_data->solvervl[v]!=NULL ; v++) {
2445 var = p_data->solvervl[v];
2446 var_set_active(var,TRUE);
2447 }
2448
2449 for (v = 0;p_data->solverdl[v]!=NULL ; v++) {
2450 dvar = p_data->solverdl[v];
2451 dis_set_active(dvar,TRUE);
2452 }
2453
2454 which do not considerate such situation
2455 */
2456
2457 set_active_vars_in_active_rels(p_data->solverrl);
2458 set_active_vars_in_active_rels(p_data->solverol);
2459 set_active_disvars_in_active_logrels(p_data->solverll);
2460
2461 /*
2462 All the unattached are set active to keep an accurate
2463 counting in the solver side.
2464 */
2465
2466 for (v = 0;p_data->solverul[v]!=NULL ; v++) {
2467 var = p_data->solverul[v];
2468 var_set_active(var,TRUE);
2469 }
2470
2471 for (v = 0;p_data->solverdul[v]!=NULL ; v++) {
2472 dvar = p_data->solverdul[v];
2473 dis_set_active(dvar,TRUE);
2474 }
2475 }
2476
2477 /*
2478 Code to make the variables aware of the relation they are
2479 incident in. KHT
2480 */
2481 vlen = gl_length(p_data->vars);
2482 for (v = 0; v < vlen; v++) {
2483 var = &(p_data->vardata[v]);
2484 i = var_instance(var);
2485 len = RelationsCount(i);
2486 p_data->varincsize += len;
2487 }
2488
2489 p_data->varincidence = ALLOC_OR_NULL(struct rel_relation*, p_data->varincsize);
2490
2491 vlen = gl_length(p_data->vars);
2492 for (v = 0; v < vlen; v++) {
2493 var = &(p_data->vardata[v]);
2494 i = var_instance(var);
2495 len = RelationsCount(i);
2496 r = 0;
2497 if(len > 0) {
2498 varincidence = get_var_incidence_space(len,p_data);
2499 for( c = 1; c <= len; c++ ) {
2500 i_r = RelationsForAtom(i,c);
2501 if( i_r == rel_instance(GetInterfacePtr(i_r)) ) {
2502 varincidence[r] = SIP(GetInterfacePtr(i_r))->u.r.data;
2503 r++;
2504 }
2505 }
2506 }
2507 if(r > 0) {
2508 var_set_incidences(var,r,varincidence);
2509 }else{
2510 var_set_incidences(var,0,NULL);
2511 }
2512 }
2513 return 0;
2514 }
2515
2516
2517 /**
2518 Pass the array of stuff into the slv_system_t, and disown them. This is
2519 where the analyse step finishes up and the solver work starts.
2520
2521 Also makes sure all solver_var have been assigned at least once,
2522 since 0 is a really stupid starting value.
2523
2524 @TODO this code is really repetitive, can't we clean it up with some
2525 nice macros? The whole problem is that the naming isn't quite consistent
2526 enough. eg.
2527 slv_set_solvers_condlogrel_list(sys,p_data->solvercll,gl_length(p_data->logcnds));
2528 could be better written
2529 slv_set_solvers_condlogrel_list(sys,p_data->solver_condlogrel,gl_length(p_data->condlogrel_list));
2530
2531 */
2532 static
2533 int analyze_configure_system(slv_system_t sys,struct problem_t *p_data){
2534
2535 /* do the slv_set_var_buf (etc) calls... */
2536 #define SL(N,L) slv_set_##N##_buf(sys,p_data->L##data); p_data->L##data=NULL;
2537
2538 SL(var,var); SL(par,par);
2539
2540 slv_set_dvar_buf(sys,p_data->disdata,gl_length(p_data->dvars));
2541 p_data->disdata = NULL;
2542
2543 SL(rel,rel); SL(condrel,con); SL(obj,obj);
2544 SL(logrel,lr); SL(condlogrel,logcon);
2545
2546 slv_set_when_buf(sys,p_data->whendata,gl_length(p_data->whens));
2547 p_data->whendata = NULL;
2548 slv_set_bnd_buf(sys,p_data->bnddata, gl_length(p_data->cnds) + gl_length(p_data->logcnds));
2549 p_data->bnddata = NULL;
2550
2551 SL(unattached,un);
2552 SL(disunatt,undis);
2553
2554 #undef SL
2555
2556 /* set rel, var, logrel incidences... */
2557 slv_set_incidence(sys,p_data->relincidence,p_data->relincsize);
2558 p_data->relincidence = NULL;
2559 slv_set_var_incidence(sys,p_data->varincidence,p_data->varincsize);
2560 p_data->varincidence = NULL;
2561 slv_set_logincidence(sys,p_data->logrelinciden,p_data->lrelincsize);
2562 p_data->logrelinciden = NULL;
2563 slv_set_symbol_list(sys,g_symbol_values_list);
2564 g_symbol_values_list = NULL;
2565
2566 /* do the slv_set_master_var_list (etc) calls... */
2567 #define SL(N,L,L2) slv_set_master_##N##_list(sys,p_data->master##L,gl_length(p_data->L2)); p_data->master##L=NULL;
2568 SL(var,vl,vars); SL(par,pl,pars); SL(dvar,dl,dvars);
2569 SL(rel,rl,rels); SL(condrel,cl,cnds); SL(obj,ol,objrels);
2570 SL(logrel,ll,logrels); SL(condlogrel,cll,logcnds); SL(when,wl,whens);
2571
2572 slv_set_master_bnd_list(sys,p_data->masterbl, gl_length(p_data->cnds) + gl_length(p_data->logcnds));
2573 p_data->masterbl = NULL;
2574
2575 SL(unattached,ul,unas); SL(disunatt,dul,dunas);
2576 #undef SL
2577
2578 /* do the slv_set_solvers_var_list (etc) calls... */
2579 #define SL(N,L,L2) slv_set_solvers_##N##_list(sys,p_data->solver##L,gl_length(p_data->L2)); p_data->solver##L=NULL;
2580 SL(var,vl,vars); SL(par,pl,pars); SL(dvar,dl,dvars);
2581 SL(rel,rl,rels); SL(condrel,cl,cnds); SL(obj,ol,objrels);
2582 SL(logrel,ll,logrels); SL(condlogrel,cll,logcnds); SL(when,wl,whens);
2583
2584 slv_set_solvers_bnd_list(sys,p_data->solverbl, gl_length(p_data->cnds) + gl_length(p_data->logcnds));
2585 p_data->solverbl = NULL;
2586
2587 SL(unattached,ul,unas); SL(disunatt,dul,dunas);
2588 #undef SL
2589
2590 /* objective relation, if found... */
2591 slv_set_obj_relation(sys,p_data->obj);
2592 p_data->obj = NULL;
2593
2594 /* and finally... */
2595 slv_set_num_models(sys,p_data->nm);
2596 slv_set_need_consistency(sys,p_data->need_consistency);
2597
2598 PopInterfacePtrs(p_data->oldips,NULL,NULL);
2599 p_data->oldips = NULL;
2600 return 0;
2601 }
2602
2603 /*----------------------------------------------------------------------------*/
2604 /*
2605 This is the entry point for problem analysis. It takes the compiler
2606 Instance, visits it with the 'CountStuffInTree' method, then constructs
2607 lists of all the different types of variables and relations etc, then
2608 convey them to the solver using the slv_ interface (i.e. methods that act
2609 on the slv_system_t we've been given).
2610
2611 We're also establishing any any protocols needed to communicate with the
2612 instance tree, eg telling the compiler about the new values of things, etc.
2613
2614 @return 0=success, 1=memory error, 2=bad instance error (nonzero=error)
2615 3=failure with diffvars data
2616
2617 @TODO: are the following comments still relevant?
2618 Makes variable/relations/when lists and objective function by heuristic.
2619 Now also makes a list of all relations that are objectives.
2620 This does not affect the semantics of the previous objective
2621 code.
2622 Do NOTHING in this function which can lead to floating point
2623 errors -- in particular because we must leave the interface ptrs
2624 in the state they were found.
2625 */
2626 int analyze_make_problem(slv_system_t sys, struct Instance *inst){
2627 int stat;
2628
2629 struct problem_t thisproblem; /* note default zero intitialisation. note also: local var! */
2630 struct problem_t *p_data; /* need to malloc, free, or make &local */
2631
2632 INCLUDED_A = AddSymbol("included");
2633 FIXED_A = AddSymbol("fixed");
2634 BASIS_A = AddSymbol("basis");
2635 DERIV_A = AddSymbol("ode_type");
2636 ODEID_A = AddSymbol("ode_id");
2637 OBSID_A = AddSymbol("obs_id");
2638
2639 p_data = &thisproblem;
2640 g_bad_rel_in_list = FALSE;
2641 InitTreeCounts(inst,p_data);
2642 /* take the census */
2643 VisitInstanceTreeTwo(inst,(VisitTwoProc)CountStuffInTree,TRUE,FALSE,
2644 (VOIDPTR)p_data);
2645 if(g_bad_rel_in_list) {
2646 p_data->root = NULL;
2647 return 2;
2648 }
2649
2650 /* decorate instances with temporary ips, collect them and etc */
2651 stat = analyze_make_master_lists(p_data);
2652 if(stat == 2){
2653 analyze_free_lists(p_data);
2654 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Nothing to make a problem from!");
2655 return 2;
2656 }else if(stat == 1){
2657 analyze_free_lists(p_data);
2658 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Insufficient memory (master lists)");
2659 return 1;
2660 }
2661
2662 /* rearrange all the stuff we found and index things */
2663 stat = analyze_make_solvers_lists(p_data);
2664 if(stat == 2){
2665 analyze_free_lists(p_data);
2666 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Nothing to make lists from (solver's lists)");
2667 return 2;
2668 }else if(stat == 1){
2669 analyze_free_lists(p_data);
2670 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Insufficient memory (solver's lists)");
2671 return 1;
2672 }
2673
2674 #ifdef ASC_IDA_NEW_ANALYSE
2675 stat = system_generate_diffvars(sys,p_data);
2676 if(stat){
2677 analyze_free_lists(p_data);
2678 return 3;
2679 }
2680 #endif
2681
2682 /* tell the slv_system_t about it, and undecorate ips from instances */
2683 analyze_configure_system(sys,p_data);
2684 /* configure must set nulls in p_data for anything we want to keep */
2685 /* blow the temporary lists away */
2686 analyze_free_lists(p_data);
2687 return 0;
2688 }
2689
2690 extern void analyze_free_reused_mem(void){
2691 resize_ipbuf((size_t)0,0);
2692 }
2693
2694 /* @} */
2695 /* :ex: set ts=4 : */

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