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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 710 - (hide annotations) (download) (as text)
Thu Jun 29 08:53:37 2006 UTC (16 years, 8 months ago) by johnpye
File MIME type: text/x-csrc
File size: 98645 byte(s)
Added my so-called 'quick fix' to external relation processing.
Still need to pursue corruption of efunc->etype pointer, for some
reason.
1 johnpye 669 /* 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 johnpye 219 Problem Analysis Routines
22 johnpye 220
23 johnpye 669 @NOTE 'ip' signifies 'interface pointer' @ENDNOTE
24 aw0a 1
25 johnpye 669 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 johnpye 219
39 johnpye 669 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 johnpye 219
48 johnpye 669 @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 johnpye 219
57 johnpye 669 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 johnpye 219
65 johnpye 220 @see analyze.h
66 johnpye 669 *//*
67     by Benjamin Andrew Allan 5/19/96
68     Version: $Revision: 1.56 $
69     Date last modified: $Date: 2003/08/23 18:43:12 $
70     Last modified by: $Author: ballan $
71 johnpye 219 */
72    
73 aw0a 1 #include <stdarg.h>
74 johnpye 399 #include <utilities/ascConfig.h>
75     #include <utilities/ascPanic.h>
76     #include <utilities/ascMalloc.h>
77     #include <general/list.h>
78     #include <general/dstring.h>
79     #include <compiler/compiler.h>
80     #include <compiler/symtab.h>
81     #include <compiler/instance_enum.h>
82     #include <compiler/fractions.h>
83     #include <compiler/dimen.h>
84     #include <compiler/atomvalue.h>
85     #include <compiler/parentchild.h>
86     #include <compiler/visitinst.h>
87 johnpye 669 #include <compiler/expr_types.h>
88 johnpye 399 #include <compiler/exprs.h>
89     #include <compiler/sets.h>
90     #include <compiler/mathinst.h>
91     #include <compiler/instquery.h>
92     #include <compiler/instance_io.h>
93     #include <compiler/relation_type.h>
94     #include <compiler/find.h>
95     #include <compiler/extfunc.h>
96     #include <compiler/extcall.h>
97     #include <compiler/relation.h>
98     #include <compiler/functype.h>
99     #include <compiler/safe.h>
100     #include <compiler/relation_util.h>
101     #include <compiler/logical_relation.h>
102     #include <compiler/logrelation.h>
103     #include <compiler/logrel_util.h>
104     #include <compiler/case.h>
105     #include <compiler/when_util.h>
106     #include "mtx.h"
107     #include "slv_types.h"
108     #include "var.h"
109 aw0a 1 #define _SLV_SERVER_C_SEEN_
110 johnpye 399 #include "rel.h"
111     #include "logrel.h"
112     #include "discrete.h"
113     #include "conditional.h"
114     #include "bnd.h"
115     #include "slv_server.h"
116     #include "slv_common.h"
117     #include "linsol.h"
118     #include "linsolqr.h"
119     #include "slv_client.h"
120     #include "cond_config.h"
121     #include "analyze.h"
122     #include <general/mathmacros.h>
123 aw0a 1
124     /* stuff to get rid of */
125     #ifndef MAX_VAR_IN_LIST
126     #define MAX_VAR_IN_LIST 20
127     #endif /* MAX_VAR_IN_LIST */
128     #define DEBUG_ANALYSIS FALSE
129    
130 johnpye 669 /*------------------------------------------------------------------------------
131     GLOBAL VARS
132     */
133    
134     static symchar *g_strings[3];
135    
136 aw0a 1 /* symbol table entries we need */
137     #define INCLUDED_A g_strings[0]
138     #define FIXED_A g_strings[1]
139     #define BASIS_A g_strings[2]
140    
141 johnpye 190 /*
142 johnpye 219 Global variable. Set to true by classify if need be
143 johnpye 222 */
144 aw0a 1 static int g_bad_rel_in_list;
145    
146    
147     /* used to give an integer value to each symbol used in a when */
148     struct gl_list_t *g_symbol_values_list = NULL;
149    
150 johnpye 669
151     /*-----------------------------------------------------------------------------
152     FORWARD DECLARATIONS
153     */
154     static void ProcessModelsInWhens(struct Instance *, struct gl_list_t *,
155     struct gl_list_t *, struct gl_list_t *);
156    
157     /*-----------------------------------------------------------------------------
158     DATA STRUCTURES FOR USE DURING PROBLEM ANALYSIS
159     */
160    
161 aw0a 1 struct varip {
162     struct var_variable *data; /* ptr to destination of data */
163     int index; /* master gl index */
164 johnpye 219 int incident; /* set 0 in classify_instance, 1 make_master_lists */
165 aw0a 1 int in_block; /* set 0 in classify_instance */
166     int fixed; /* set in classify_instance */
167     int solvervar; /* set in classify_instance */
168 johnpye 219 int active; /* is this var a part of my problem */
169     int basis; /* set in classify_instance */
170 aw0a 1 };
171    
172    
173     struct disvarip {
174     struct dis_discrete *data; /* ptr to destination of data */
175 johnpye 219 int index; /* master gl index */
176     int fixed; /* set in classify_instance */
177 aw0a 1 int isconst; /* is this dis var constant ? */
178     int distype; /* 0 boolean, 1 int, -1 symbol */
179     int value; /* integer value of the variable */
180     int incident; /* is it incident in a logrel */
181     int inwhen; /* is it in a when var list */
182     int booleanvar; /* Not sure if I need it */
183     int active; /* is this disvar a part of my problem */
184     };
185    
186    
187     struct relip {
188     struct rel_relation *data; /* ptr to destination of data */
189     long model; /* relation is in this model in model gllist */
190 johnpye 219 /* set in CollectRelsAndWhens. = 1.. nmodels */
191     /* rel_relation models = u.r.model-1 */
192 aw0a 1 int index; /* master gl list index */
193 johnpye 219 int obj; /* is it an objective relation. set in classify_instance */
194     int ext; /* is it e_blackbox. set in classify_instance */
195     int included; /* set in classify_instance */
196     int cond; /* is it a conditional relation. set in classify_instance */
197     int inwhen; /* is it in a when */
198     int active; /* is this rel a part of my problem */
199 aw0a 1 };
200    
201     struct logrelip {
202     struct logrel_relation *data; /* ptr to destination of data */
203 johnpye 219 long model; /* logrelation is in this model in model gllist */
204     int index; /* master gllist index */
205     int included; /* set in classify_instance */
206     int cond; /* is it a conditional logrelation. */
207 aw0a 1 int inwhen; /* is it in a when */
208     int active; /* is this logrel a part of my problem */
209     };
210    
211     struct whenip{
212 johnpye 219 struct w_when *data; /* ptr to destination of data */
213     long model; /* when is in this model in model gllist */
214     int index; /* master gllist index */
215     int inwhen; /* is it in a when */
216 aw0a 1 };
217    
218     struct modip {
219 johnpye 219 int index; /* set in make master lists. 1..nmodels */
220     int inwhen; /* is it in a when */
221 aw0a 1 };
222    
223     /* we will decorate the ascend instance tree with these in the interface
224 johnpye 219 pointers, but ONLY for the system build process and not persistently.
225     DO NOT EVER UNDER ANY CIRCUMSTANCES EXPORT THIS DATA STRUCTURE.
226     */
227 aw0a 1 struct solver_ipdata {
228     struct Instance *i; /* the kind of instance is the enum for union */
229     union {
230     struct modip m;
231     struct varip v;
232     struct disvarip dv;
233     struct relip r;
234     struct logrelip lr;
235     struct whenip w;
236     } u;
237     };
238    
239     /* a handy cast for fetching things off gllists */
240     #define SIP(x) ((struct solver_ipdata *)(x))
241    
242 johnpye 190 /*
243 johnpye 219 a bridge buffer used so much we aren't going to free it, just reuse it
244     */
245 aw0a 1 static struct reuse_t {
246     size_t ipcap; /* number of ips allocated in ipbuf */
247     size_t ipused; /* number of ips in use */
248     struct solver_ipdata *ipbuf;
249     } g_reuse = {0,0,NULL};
250    
251 johnpye 222 /**
252     a data structure for bridge-building only. hell of a scaffolding.
253 johnpye 219 all fields should be empty if construction is not in progress.
254     In particular, do no operations that can throw an exception
255     while manipulating a problem_t, as it is way too big to let leak.
256 johnpye 669
257     @TODO is this comment in the right place?
258     we are making the ANSI assumption that this will be init to 0/NULL
259    
260     @TODO what about this one?:
261     container for globals during assembly.
262     At present, the mastervl and solvervl are of the same length. This
263     is purely coincidental and the long run intent is that there is one
264     master list and that a problem coordinator would set up the
265     solver var/rel lists blockwise as we go along. We may want to put
266     block information in the rel/var structures.
267 johnpye 219 */
268 aw0a 1 struct problem_t {
269 johnpye 222
270     /* the following are established by CountStuffInTree */
271 johnpye 219 long nv; /* number of solvervar/solveratom */
272     long np; /* number of real ATOM instance parameters */
273     long nu; /* number of real ATOM instance uninteresting */
274 aw0a 1 long ndv; /* number of discrete variables */
275     long nud; /* number of uninteresting discretes */
276 johnpye 219 long nc; /* number of conditional relations */
277     long ncl; /* number of conditional logrelations */
278     long nr; /* number of algebraic relations */
279     long no; /* number of objective rels */
280     long nl; /* number of logical rels */
281 aw0a 1 long nw; /* number of whens */
282 johnpye 219 long ne; /* number of external rels subset overestimate*/
283     long nm; /* number of models */
284 johnpye 222
285     /*
286     The following gllists contain pointers to interface ptrs as
287     locally defined.
288     The lists will be in order found by a visit instance tree.
289     */
290 aw0a 1 struct gl_list_t *vars; /* solvervar/solveratom. varips */
291     struct gl_list_t *pars; /* real ATOM instance parameters */
292     struct gl_list_t *unas; /* real ATOM instance of no 'apparent' use */
293     struct gl_list_t *models; /* models in tree. modips */
294 johnpye 222
295     /*
296     The following gllists contain pointers to interface ptrs as
297     locally defined.
298     The lists will be in order found by running over the models list.
299     */
300 aw0a 1 struct gl_list_t *dvars; /* discrete variables */
301     struct gl_list_t *dunas; /* discrete variables of no use */
302     struct gl_list_t *whens; /* whens */
303     struct gl_list_t *cnds; /* conditional relations */
304     struct gl_list_t *logcnds; /* conditional logrelations */
305     struct gl_list_t *rels; /* ascend relations. relips */
306     struct gl_list_t *objrels; /* objective rels. relips */
307     struct gl_list_t *logrels; /* logical rels */
308 johnpye 222
309     /* bridge ip data */
310 aw0a 1 struct gl_list_t *oldips; /* buffer of oldip crap we're protecting */
311 johnpye 222
312     /* misc stuff */
313 aw0a 1 struct gl_list_t *tmplist; /* sort space */
314 johnpye 222
315     /* stuff that will end up in the slv_system_t */
316 aw0a 1 struct rel_relation *obj; /* DEFAULT objective relation, if any */
317     struct Instance *root; /* instance we construct system from */
318     struct gl_list_t *extrels; /* black box stub list */
319 johnpye 222
320     /* stuff that should move elsewhere, but end up in slv_system_t */
321 aw0a 1 mtx_region_t *blocks; /* array of partitions in reordered matrix */
322     int32 nblocks; /* size of array of partitions */
323 johnpye 219 int nnz; /* free nonzeros in processed jacobian */
324 aw0a 1 int nnztot; /* total nonzeros in processed relations */
325     int nnzobj; /* total nonzeros in objective gradients */
326     int nnzcond; /* total nonzeros in conditional relations */
327     int relincsize; /* total nonzeros in gradients */
328     int relincinuse; /* incidence given to relations so far */
329     int varincsize; /* total nonzeros in gradients (redundant) */
330     int varincinuse; /* incidence given to variables so far */
331 johnpye 219 int ncol; /* free and incident vars */
332     int nrow; /* included relations */
333 aw0a 1 /* conditional stuff */
334     int32 need_consistency; /* Conistency analysis is required ? */
335 johnpye 222
336     /* logical relation stuff */
337 johnpye 219 int lognnz; /* Summ of free boolean vars in inc logrels */
338     int lognrow; /* included logrelations */
339     int logncol; /* free and incident boolean vars */
340     int lrelinc; /* incident boolean vars */
341     int lrelincsize; /* Total summ of incidences (boolean vars)
342     in logrels*/
343 aw0a 1 int lrelincinuse; /* incidence given to log relations so far */
344 johnpye 222
345     /* data to go to slv_system_t */
346 aw0a 1 struct rel_relation *reldata; /* rel data space, mass allocated */
347     struct rel_relation *objdata; /* objrel data space, mass allocated */
348     struct rel_relation *condata; /* cond rel data space, mass allocated*/
349     struct logrel_relation *lrdata; /* logrel data space, mass allocated */
350     struct logrel_relation *logcondata; /* cond logrel data space, allocated */
351     struct var_variable *vardata; /* svar data space, mass allocated */
352     struct var_variable *pardata; /* par data space, mass allocated */
353     struct var_variable *undata; /* data space, mass allocated */
354     struct dis_discrete *disdata; /* dis var data space, mass allocated */
355     struct dis_discrete *undisdata; /* data space, mass allocated */
356     struct w_when *whendata; /* when data space, mass allocated */
357     struct bnd_boundary *bnddata; /* boundaries data space, allocated */
358     struct var_variable **mastervl; /* master null-terminated list */
359     struct var_variable **solvervl; /* solvers null-terminated list */
360     struct dis_discrete **masterdl; /* master null-terminated list */
361     struct dis_discrete **solverdl; /* solvers null-terminated list */
362     struct rel_relation **masterrl; /* master null-terminated list */
363     struct rel_relation **solverrl; /* solvers null-terminated list */
364     struct rel_relation **mastercl; /* master null-terminated list */
365     struct rel_relation **solvercl; /* solvers null-terminated list */
366     struct rel_relation **masterol; /* master null-terminated list */
367     struct rel_relation **solverol; /* solvers null-terminated list */
368     struct logrel_relation **masterll; /* master null-terminated list */
369     struct logrel_relation **solverll; /* solvers null-terminated list */
370     struct logrel_relation **mastercll; /* master null-terminated list */
371     struct logrel_relation **solvercll; /* solvers null-terminated list */
372     struct w_when **masterwl; /* master null-terminated list */
373     struct w_when **solverwl; /* solvers null-terminated list */
374     struct bnd_boundary **masterbl; /* master null-terminated list */
375     struct bnd_boundary **solverbl; /* solvers null-terminated list */
376     struct var_variable **masterpl; /* master null-terminated list */
377     struct var_variable **solverpl; /* solvers null-terminated list */
378     struct var_variable **masterul; /* master null-terminated list */
379     struct var_variable **solverul; /* solvers null-terminated list */
380     struct dis_discrete **masterdul; /* master null-terminated list */
381     struct dis_discrete **solverdul; /* solvers null-terminated list */
382     struct var_variable **relincidence; /* rel_relation incidence source */
383     struct rel_relation **varincidence; /* var_variable incidence source */
384     struct dis_discrete **logrelinciden; /* logrel_relation incidence source */
385    
386     struct ExtRelCache **erlist; /* external rel cache null terminated list */
387     };
388 johnpye 222
389 johnpye 669 /*------------------------------------------------------------------------------
390     SOME STUFF WITH INTERFACE POINTERS
391 johnpye 219 */
392 aw0a 1 /* return a pointer to the oncesizefitsall ips we're using.
393 johnpye 219 always returns nonnull because if we run out we exit
394     */
395 aw0a 1 static struct solver_ipdata *analyze_getip(void)
396     {
397     if (g_reuse.ipbuf!=NULL && g_reuse.ipused < g_reuse.ipcap) {
398     return &(g_reuse.ipbuf[g_reuse.ipused++]);
399     } else {
400     Asc_Panic(2, "ananlyze_getip",
401     "Too many ips requested by analyze_getip\n");
402     exit(2);/* NOT REACHED. Needed to keep gcc from whining */
403     }
404     }
405    
406 johnpye 190 /*
407 johnpye 219 reallocates to the requested size (newcap) the ipbuf.
408     if newcap = 0, frees ipbuf.
409     if insufficient memory returns 1.
410     if newcap > 0 and reset mem != 0, initializes ipbuf to 0s.
411     Resets ipused to 0.
412     */
413 aw0a 1 static
414     int resize_ipbuf(size_t newcap, int resetmem)
415     {
416     struct solver_ipdata *tmp;
417     if (newcap ==0) {
418     if (g_reuse.ipbuf != NULL) {
419     ascfree(g_reuse.ipbuf);
420     }
421     g_reuse.ipcap = g_reuse.ipused = 0;
422     g_reuse.ipbuf = NULL;
423     return 0;
424     }
425     if (newcap > g_reuse.ipcap) {
426     if ( g_reuse.ipcap >0 ) {
427     tmp = (struct solver_ipdata *)
428     ascrealloc(g_reuse.ipbuf,newcap*sizeof(struct solver_ipdata));
429     if (tmp == NULL) {
430     FPRINTF(ASCERR,"ERROR: (resize_ipbuf) Insufficient memory.\n");
431     return 1;
432     }
433     g_reuse.ipbuf = tmp;
434     g_reuse.ipcap = newcap;
435     } else {
436     tmp = (struct solver_ipdata *)
437     ascmalloc(newcap*sizeof(struct solver_ipdata));
438     if (tmp == NULL) {
439     FPRINTF(ASCERR,
440     "ERROR:(resize_ipbuf 1st call) Insufficient memory.\n");
441     return 1;
442     }
443     g_reuse.ipbuf = tmp;
444     g_reuse.ipcap = newcap;
445     }
446     }
447     if (resetmem) {
448     memset((char *)g_reuse.ipbuf,0,
449     g_reuse.ipcap*sizeof(struct solver_ipdata));
450     }
451     g_reuse.ipused = 0;
452     return 0;
453     }
454    
455 johnpye 669 /*------------------------------------------------------------------------------
456     SOME STUFF TO DO WITH INCIDENCE SPACE
457     */
458 aw0a 1
459 johnpye 190 /*
460 johnpye 219 checks size of request and returns a pointer to the next available
461     chunk of incidence space. if too much requested or 0 requested returns
462     NULL. p_data->relincidence must have been allocated for this to work.
463     */
464 aw0a 1 static
465     struct var_variable **get_incidence_space(int len, struct problem_t *p_data)
466     {
467     struct var_variable **tmp;
468     if (p_data->relincidence == NULL) {
469     Asc_Panic(2,NULL,"get_incidence_space called prematurely. bye.\n");
470     }
471     if (len <1) return NULL;
472     if (p_data->relincinuse + len > p_data->relincsize) {
473     FPRINTF(ASCERR,"get_incidence_space called excessively.\n");
474     return NULL;
475     }
476     tmp = &(p_data->relincidence[p_data->relincinuse]);
477     p_data->relincinuse += len;
478     return tmp;
479     }
480    
481 johnpye 190 /*
482 johnpye 219 checks size of request and returns a pointer to the next available
483     chunk of incidence space. if too much requested or 0 requested returns
484     NULL. p_data->varincidence must have been allocated for this to work.
485     */
486 aw0a 1 static
487     struct rel_relation **get_var_incidence_space(int len,
488     struct problem_t *p_data)
489     {
490     struct rel_relation **tmp;
491     if (p_data->varincidence == NULL) {
492     Asc_Panic(2,NULL,"get_var_incidence_space called prematurely. bye.\n");
493     }
494     if (len <1) return NULL;
495     if (p_data->varincinuse + len > p_data->varincsize) {
496     FPRINTF(ASCERR,"get_var_incidence_space called excessively.\n");
497     return NULL;
498     }
499     tmp = &(p_data->varincidence[p_data->varincinuse]);
500     p_data->varincinuse += len;
501     return tmp;
502     }
503    
504    
505     /*
506 johnpye 219 p_data->logrelinciden must have been allocated for this to work.
507     */
508 aw0a 1 static
509     struct dis_discrete **get_logincidence_space(int len,
510     struct problem_t *p_data)
511     {
512     struct dis_discrete **tmp;
513     if (p_data->logrelinciden == NULL) {
514     Asc_Panic(2,NULL,"get_logincidence_space called prematurely. bye.\n");
515     }
516     if (len <1) return NULL;
517     if (p_data->lrelincinuse + len > p_data->lrelincsize) {
518     FPRINTF(ASCERR,"get_logincidence_space called excessively.\n");
519     return NULL;
520     }
521     tmp = &(p_data->logrelinciden[p_data->lrelincinuse]);
522     p_data->lrelincinuse += len;
523     return tmp;
524     }
525    
526 johnpye 669 /*------------------------------------------------------------------------------
527     SOME OTHER STUFF
528     */
529 aw0a 1
530     /*
531 johnpye 219 InitTreeCounts(i); This resets the pointers and counters in
532     p_data to null. p_data is supposed to be a temporary structure
533     so the memory management of the pointers in p_data is the job
534     of the caller.
535     p_data->root is set to i.
536     */
537 aw0a 1 static void InitTreeCounts(struct Instance *i,struct problem_t *p_data)
538     {
539     memset((char *)p_data,0,sizeof(struct problem_t));
540     p_data->root = i;
541     }
542    
543     #define AVG_PARENTS 2
544     #define AVG_CHILDREN 4
545     #define AVG_RELATIONS 15
546     #define AVG_GROWTH 2
547     #define PART_THRESHOLD 1000
548    
549     /*
550 johnpye 219 The following function should be moved out to the compiler
551     under the guise of a supported attribute.
552     */
553 aw0a 1 static int BooleanChildValue(struct Instance *i,symchar *sc)
554     {
555 johnpye 62 /* FPRINTF(ASCERR,"GETTING BOOLEAN CHILD VALUE OF %s\n",SCP(sc)); */
556 aw0a 1 if (i == NULL || sc == NULL || (i=ChildByChar(i,sc)) == NULL) {
557     return 0;
558     } else {
559     return ( GetBooleanAtomValue(i) );
560     }
561     }
562    
563     static void CollectArrayRelsAndWhens(struct Instance *i, long modindex,
564     struct problem_t *p_data)
565     {
566     struct Instance *child;
567     struct solver_ipdata *rip;
568     unsigned long nch,c;
569    
570     if (i==NULL) return;
571     nch = NumberChildren(i);
572     for (c=1;c<=nch;c++) {
573     child = InstanceChild(i,c);
574     if (child==NULL) continue;
575     switch (InstanceKind(child)) {
576     case REL_INST:
577     rip = SIP(GetInterfacePtr(child));
578     if (rip->u.r.model == 0) {
579     rip->u.r.model = modindex;
580     } else {
581     /* ah hah! found an array with two distinct MODEL parents! skip it */
582     break;
583     }
584     if (rip->u.r.cond) {
585     gl_append_ptr(p_data->cnds,(VOIDPTR)rip);
586     }
587     else {
588     if (rip->u.r.obj) {
589     gl_append_ptr(p_data->objrels,(VOIDPTR)rip);
590     } else {
591     gl_append_ptr(p_data->rels,(VOIDPTR)rip);
592     }
593     }
594     break;
595     case LREL_INST:
596     rip = SIP(GetInterfacePtr(child));
597     if (rip->u.lr.model == 0) {
598     rip->u.lr.model = modindex;
599     } else {
600     break;
601     }
602     if (rip->u.lr.cond) {
603     gl_append_ptr(p_data->logcnds,(VOIDPTR)rip);
604     }
605     else {
606     gl_append_ptr(p_data->logrels,(VOIDPTR)rip);
607     }
608     break;
609     case WHEN_INST:
610     rip = SIP(GetInterfacePtr(child));
611     if (rip->u.w.model == 0) {
612     rip->u.w.model = modindex;
613     } else {
614     break;
615     }
616     gl_append_ptr(p_data->whens,(VOIDPTR)rip);
617     break;
618     case ARRAY_ENUM_INST:
619     case ARRAY_INT_INST:
620 johnpye 190 if (ArrayIsRelation(child) ||
621 aw0a 1 ArrayIsLogRel(child) ||
622 johnpye 669 ArrayIsWhen(child)
623     ){
624     CollectArrayRelsAndWhens(child,modindex,p_data);
625 aw0a 1 }
626     break;
627     default:
628     break;
629     }
630     }
631     }
632    
633 johnpye 222
634 aw0a 1 /*
635 johnpye 219 Collect all the logrels/relations at the local scope of the MODEL
636     associated with ip->i. Local scope includes arrays of logrels/relations,
637     mainly because these arrays don't have interface pointers so we
638     can't treat them separately.
639     */
640 aw0a 1 static void CollectRelsAndWhens(struct solver_ipdata *ip,
641     long modindex,
642     struct problem_t *p_data)
643     {
644     struct Instance *child;
645     struct solver_ipdata *rip;
646     unsigned long nch,c;
647    
648     if (ip->i==NULL) return;
649     nch = NumberChildren(ip->i);
650     for (c=1;c<=nch;c++) {
651     child = InstanceChild(ip->i,c);
652     if (child==NULL) continue;
653     switch (InstanceKind(child)) {
654     case REL_INST:
655     rip = SIP(GetInterfacePtr(child));
656     rip->u.r.model = modindex;
657     if (rip->u.r.cond) {
658     gl_append_ptr(p_data->cnds,(VOIDPTR)rip);
659     }
660     else {
661     if (rip->u.r.obj) {
662     gl_append_ptr(p_data->objrels,(VOIDPTR)rip);
663     } else {
664     gl_append_ptr(p_data->rels,(VOIDPTR)rip);
665     }
666     }
667     break;
668     case LREL_INST:
669     rip = SIP(GetInterfacePtr(child));
670     rip->u.lr.model = modindex;
671     if (rip->u.lr.cond) {
672     gl_append_ptr(p_data->logcnds,(VOIDPTR)rip);
673     }
674     else {
675     gl_append_ptr(p_data->logrels,(VOIDPTR)rip);
676     }
677     break;
678     case WHEN_INST:
679     rip = SIP(GetInterfacePtr(child));
680     rip->u.w.model = modindex;
681     gl_append_ptr(p_data->whens,(VOIDPTR)rip);
682     break;
683     case ARRAY_ENUM_INST:
684     case ARRAY_INT_INST:
685 johnpye 190 if (ArrayIsRelation(child) ||
686     ArrayIsLogRel(child)||
687 johnpye 669 ArrayIsWhen(child)
688     ){
689     CollectArrayRelsAndWhens(child,modindex,p_data);
690 aw0a 1 }
691     break;
692     default:
693     break;
694     }
695     }
696     }
697    
698     /*
699 johnpye 219 Checks the problem extrels list to see whether a cache has been
700     created for the given relation in the problem_t bridge.
701     If not will return NULL, else
702     will return the pointer to the cache. The nodestamp corresponding
703     to this relation is returned regardless.
704     */
705 aw0a 1 static struct ExtRelCache
706     *CheckIfCacheExists( struct Instance *relinst, int *nodestamp,
707     struct problem_t *p_data)
708     {
709     struct ExtCallNode *ext;
710     struct ExtRelCache *cache;
711     CONST struct relation *gut;
712     enum Expr_enum type;
713     unsigned long len,c;
714    
715     gut = GetInstanceRelation(relinst,&type);
716     assert(type==e_blackbox);
717     ext = BlackBoxExtCall(gut);
718     *nodestamp = ExternalCallNodeStamp(ext);
719     len = gl_length(p_data->extrels);
720    
721     for (c=1;c<=len;c++) {
722     cache = (struct ExtRelCache *)gl_fetch(p_data->extrels,c);
723     if (cache->nodestamp == *nodestamp) {
724     return cache;
725     }
726     }
727     return NULL;
728     }
729 johnpye 219
730 aw0a 1 /*
731 johnpye 219 Count the instance into the required bin.
732 johnpye 669
733     @NOTE Call only with good relation instances.
734 johnpye 219 */
735 aw0a 1 static void analyze_CountRelation(struct Instance *inst,
736     struct problem_t *p_data)
737     {
738     switch( RelationRelop(GetInstanceRelationOnly(inst)) ) {
739     case e_maximize:
740     case e_minimize:
741     p_data->no++;
742     break;
743     case e_less: case e_lesseq:
744     case e_greater: case e_greatereq:
745     case e_equal: case e_notequal:
746     if ( RelationIsCond(GetInstanceRelationOnly(inst)) ) {
747     p_data->nc++;
748     }
749     else {
750     p_data->nr++;
751     if ( GetInstanceRelationType(inst)==e_blackbox ) {
752     p_data->ne++;
753     }
754     }
755     break;
756     default:
757     FPRINTF(ASCERR,"ERROR: (analyze) analyze_CountRelation\n");
758     FPRINTF(ASCERR," Unknown relation type.\n");
759     }
760     }
761    
762 johnpye 219
763 aw0a 1 /*
764 johnpye 669 Obtain an integer value from a symbol value
765     Used for a WHEN statement. Each symbol value is storaged in a symbol list.
766 johnpye 219 It checks if the symval is already in the solver symbol list,
767     if it is, returns the integer corresponding to the position of symval
768     if it is not, appends the symval to the list and then returns the int
769 johnpye 669
770     @NOTE This is terrible inefficient as the number of symbols grows.
771 johnpye 219 I am keeping it by now, are they going to be so many symbols in
772     whens anyway ?
773     */
774 aw0a 1
775     int GetIntFromSymbol(CONST char *symval,
776     struct gl_list_t *symbol_list)
777     {
778     struct SymbolValues *entry,*dummy;
779     unsigned long length;
780     int len,c,value;
781     int symbol_list_count;
782    
783     if (symbol_list != NULL) {
784     len = gl_length(symbol_list);
785     for (c=1; c<= len; c++) {
786     dummy = (struct SymbolValues *)(gl_fetch(symbol_list,c));
787     if (!strcmp(dummy->name,symval)) {
788     return (dummy->value);
789     }
790     }
791     symbol_list_count = len;
792     } else {
793     symbol_list_count = 0;
794     symbol_list = gl_create(2L);
795     }
796     length = (unsigned long)strlen(symval);
797     length++;
798     symbol_list_count++;
799     entry = (struct SymbolValues *)ascmalloc(sizeof(struct SymbolValues));
800 johnpye 669 entry->name = ASC_NEW_ARRAY(char,length);
801 aw0a 1 strcpy(entry->name,symval);
802     entry->value = symbol_list_count;
803     value = entry->value;
804     gl_append_ptr(symbol_list,entry);
805     return value;
806     }
807    
808     void DestroySymbolValuesList(struct gl_list_t *symbol_list)
809     {
810     struct SymbolValues *entry;
811     int len,c;
812     if (symbol_list != NULL) {
813     len = gl_length(symbol_list);
814     for (c=1; c<= len; c++) {
815     entry = (struct SymbolValues *)(gl_fetch(symbol_list,c));
816     ascfree((char *)entry->name); /* Do I need this ? */
817     ascfree((char *)entry);
818     }
819     gl_destroy(symbol_list);
820     symbol_list = NULL;
821     }
822     }
823    
824 johnpye 669 /*------------------------------------------------------------------------------
825     CLASSIFICATION OF INSTANCES, CREATING INTERFACE POINTERS
826     */
827 aw0a 1
828 johnpye 219 /*
829     classify_instance : to be called by PushInterfacPtrs.
830 aw0a 1
831 johnpye 219 This function classifies the given instance and appends into
832     the necessary list in the p_data structure.
833     It also sets returns a pointer to the caller for insertion into
834     the interface_ptr slot.
835    
836     Note, we should be passing the ipbuf info via vp so we don't
837     need the nasty global variable and can be more thread safe.
838     vp is a struct problem_t.
839     */
840 aw0a 1 static
841     void *classify_instance(struct Instance *inst, VOIDPTR vp)
842     {
843     struct solver_ipdata *ip;
844     struct problem_t *p_data;
845     CONST char *symval;
846     p_data = (struct problem_t *)vp;
847     switch( InstanceKind(inst) ) {
848     case REAL_ATOM_INST: /* Variable or parameter or real */
849     ip = analyze_getip();
850     ip->i = inst;
851     ip->u.v.incident = 0;
852     ip->u.v.in_block = 0;
853     ip->u.v.index = 0;
854     ip->u.v.active = 0;
855     if( solver_var(inst) ) {
856     ip->u.v.solvervar = 1; /* must set this regardless of what list */
857     ip->u.v.fixed = BooleanChildValue(inst,FIXED_A);
858     ip->u.v.basis = BooleanChildValue(inst,BASIS_A);
859     if (RelationsCount(inst)) {
860     gl_append_ptr(p_data->vars,(POINTER)ip);
861     } else {
862     gl_append_ptr(p_data->unas,(POINTER)ip);
863     }
864     } else {
865     ip->u.v.fixed = 1;
866     ip->u.v.solvervar=0;
867     if (solver_par(inst) && RelationsCount(inst)) {
868     gl_append_ptr(p_data->pars,(POINTER)ip);
869     } else {
870     gl_append_ptr(p_data->unas,(POINTER)ip);
871     }
872     }
873     return ip;
874     case BOOLEAN_ATOM_INST:
875     ip = analyze_getip();
876     ip->i = inst;
877     ip->u.dv.isconst = 0;
878     ip->u.dv.distype = 0;
879     ip->u.dv.incident = 0;
880     ip->u.dv.index = 0;
881     ip->u.dv.active = 0;
882     ip->u.dv.value = GetBooleanAtomValue(inst);
883     if( boolean_var(inst) ) {
884     ip->u.dv.booleanvar = 1;
885     ip->u.dv.fixed = BooleanChildValue(inst,FIXED_A);
886     } else {
887     ip->u.dv.fixed = 1;
888     ip->u.dv.booleanvar=0;
889     }
890     if( LogRelationsCount(inst) || WhensCount(inst) ) {
891     gl_append_ptr(p_data->dvars,(POINTER)ip);
892     if ( WhensCount(inst) ) {
893     ip->u.dv.inwhen = 1;
894     } else {
895     ip->u.dv.inwhen = 0;
896     }
897     } else {
898     gl_append_ptr(p_data->dunas,(POINTER)ip);
899     }
900     return ip;
901     case BOOLEAN_CONSTANT_INST:
902     if (WhensCount(inst)) {
903     ip = analyze_getip();
904     ip->i = inst;
905     ip->u.dv.isconst = 1;
906     ip->u.dv.distype = 0;
907     ip->u.dv.index = 0;
908     ip->u.dv.incident = 0;
909     ip->u.dv.booleanvar=0;
910     ip->u.dv.fixed = 1;
911     ip->u.dv.active = 0;
912     ip->u.dv.value = GetBooleanAtomValue(inst);
913     gl_append_ptr(p_data->dvars,(POINTER)ip);
914     return ip;
915     } else {
916     return NULL;
917     }
918     case INTEGER_ATOM_INST:
919     if (WhensCount(inst)) {
920     ip = analyze_getip();
921     ip->i = inst;
922     ip->u.dv.isconst = 0;
923     ip->u.dv.distype = 1;
924     ip->u.dv.index = 0;
925     ip->u.dv.incident = 0;
926     ip->u.dv.booleanvar=0;
927     ip->u.dv.fixed = 0;
928     ip->u.dv.active = 0;
929     ip->u.dv.value = GetIntegerAtomValue(inst);
930     gl_append_ptr(p_data->dvars,(POINTER)ip);
931     return ip;
932     } else {
933     return NULL;
934     }
935     case SYMBOL_ATOM_INST:
936     if (WhensCount(inst)) {
937     symval = SCP(GetSymbolAtomValue(inst));
938     if (symval == NULL) {
939     return NULL;
940     }
941     ip = analyze_getip();
942     ip->i = inst;
943     ip->u.dv.isconst = 0;
944     ip->u.dv.distype = -1;
945     ip->u.dv.index = 0;
946     ip->u.dv.incident = 0;
947     ip->u.dv.booleanvar=0;
948     ip->u.dv.fixed = 0;
949     ip->u.dv.active = 0;
950     if (g_symbol_values_list == NULL) {
951     g_symbol_values_list = gl_create(2L);
952     }
953     ip->u.dv.value = GetIntFromSymbol(symval,g_symbol_values_list);
954     gl_append_ptr(p_data->dvars,(POINTER)ip);
955     return ip;
956     } else {
957     return NULL;
958     }
959     case INTEGER_CONSTANT_INST:
960     if (WhensCount(inst)) {
961     ip = analyze_getip();
962     ip->i = inst;
963     ip->u.dv.isconst = 1;
964     ip->u.dv.distype = 1;
965     ip->u.dv.index = 0;
966     ip->u.dv.incident = 0;
967     ip->u.dv.booleanvar=0;
968     ip->u.dv.fixed = 1;
969     ip->u.dv.active = 0;
970     ip->u.dv.value = GetIntegerAtomValue(inst);
971     gl_append_ptr(p_data->dvars,(POINTER)ip);
972     return ip;
973     } else {
974     return NULL;
975     }
976     case SYMBOL_CONSTANT_INST:
977     if (WhensCount(inst)) {
978     symval = SCP(GetSymbolAtomValue(inst));
979     if (symval == NULL) {
980     return NULL;
981     }
982     ip = analyze_getip();
983     ip->i = inst;
984     ip->u.dv.isconst = 1;
985     ip->u.dv.distype = -1;
986     ip->u.dv.index = 0;
987     ip->u.dv.incident = 0;
988     ip->u.dv.booleanvar=0;
989     ip->u.dv.fixed = 1;
990     ip->u.dv.active = 0;
991     if (g_symbol_values_list == NULL) {
992     g_symbol_values_list = gl_create(2L);
993     }
994     ip->u.dv.value = GetIntFromSymbol(symval,g_symbol_values_list);
995     gl_append_ptr(p_data->dvars,(POINTER)ip);
996     return ip;
997     } else {
998     return NULL;
999     }
1000     case REL_INST: /* Relation (or conditional or objective) */
1001     ip = analyze_getip();
1002     ip->i = inst;
1003     ip->u.r.active = 1;
1004     switch(RelationRelop(GetInstanceRelationOnly(inst))) {
1005     case e_minimize:
1006     ip->u.r.obj = 1;
1007     break;
1008     case e_maximize:
1009     ip->u.r.obj = -1;
1010     break;
1011     default:
1012     ip->u.r.obj = 0;
1013     break;
1014     }
1015     if ( GetInstanceRelationType(inst)==e_blackbox ) {
1016     ip->u.r.ext = 1;
1017     } else {
1018     ip->u.r.ext = 0;
1019     }
1020     if ( RelationIsCond(GetInstanceRelationOnly(inst)) ) {
1021     ip->u.r.cond = 1;
1022     } else {
1023     ip->u.r.cond = 0;
1024     }
1025     if ( WhensCount(inst) ) {
1026     ip->u.r.inwhen = 1;
1027     } else {
1028     ip->u.r.inwhen = 0;
1029     }
1030     ip->u.r.included = BooleanChildValue(inst,INCLUDED_A);
1031     ip->u.r.model = 0;
1032     ip->u.r.index = 0;
1033     return ip;
1034     /* note we do NOT append it to lists here */
1035     case LREL_INST: /* LogRelation */
1036     ip = analyze_getip();
1037     ip->i = inst;
1038     ip->u.lr.active = 1;
1039     if ( LogRelIsCond(GetInstanceLogRel(inst)) ) {
1040     ip->u.lr.cond = 1;
1041     } else {
1042     ip->u.lr.cond = 0;
1043     }
1044     if ( WhensCount(inst) ) {
1045     ip->u.lr.inwhen = 1;
1046     } else {
1047     ip->u.lr.inwhen = 0;
1048     }
1049     ip->u.lr.included = BooleanChildValue(inst,INCLUDED_A);
1050     ip->u.lr.model = 0;
1051     ip->u.lr.index = 0;
1052     return ip;
1053     /* note we do NOT append it to lists here */
1054     case MODEL_INST:
1055     ip = analyze_getip();
1056     ip->i = inst;
1057     ip->u.m.index = 0;
1058     if ( WhensCount(inst) ) {
1059     ip->u.m.inwhen = 1;
1060     } else {
1061     ip->u.m.inwhen = 0;
1062     }
1063     gl_append_ptr(p_data->models,(POINTER)ip);
1064     return ip;
1065     case WHEN_INST:
1066     ip = analyze_getip();
1067     ip->i = inst;
1068     ip->u.w.index = 0;
1069     if ( WhensCount(inst) ) {
1070     ip->u.w.inwhen = 1;
1071     } else {
1072     ip->u.w.inwhen = 0;
1073     }
1074     return ip;
1075     /* note we do NOT append it to lists here */
1076     default:
1077     return NULL;
1078     }
1079     }
1080 johnpye 219
1081 johnpye 669 /*------------------------------------------------------------------------------
1082     MAKE PROBLEM routines
1083     */
1084 johnpye 219
1085 aw0a 1 /*
1086 johnpye 219 This function sets g_bad_rel_in_list TRUE if it finds any unhappy
1087     relations. All the rest of the code depends on ALL relations being
1088     good, so don't disable the g_bad_rel_in_list feature.
1089     */
1090 johnpye 190 static
1091 aw0a 1 void CountStuffInTree(struct Instance *inst, struct problem_t *p_data)
1092     {
1093     CONST char *symval;
1094     if (inst!=NULL) {
1095     switch (InstanceKind(inst)) {
1096     case REL_INST:
1097     if( GetInstanceRelationOnly(inst) == NULL ||
1098     GetInstanceRelationType(inst) == e_undefined) {
1099     /* guard against null relations, unfinished ones */
1100 johnpye 222 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
1101 johnpye 76 FPRINTF(ASCERR,"Found bad (unfinished?) relation '");
1102 aw0a 1 WriteInstanceName(ASCERR,inst,p_data->root);
1103 johnpye 76 FPRINTF(ASCERR,"' (in CountStuffInTree)");
1104     error_reporter_end_flush();
1105 aw0a 1 g_bad_rel_in_list = TRUE;
1106     return;
1107     }
1108     /* increment according to classification */
1109     analyze_CountRelation(inst,p_data);
1110     break;
1111     case REAL_ATOM_INST:
1112     if( solver_var(inst) && RelationsCount(inst)) {
1113     p_data->nv++;
1114     } else {
1115     if (solver_par(inst) && RelationsCount(inst)) {
1116     /* never passes right now */
1117     p_data->np++;
1118     } else {
1119     p_data->nu++;
1120     }
1121     }
1122     /* The use of RelationsCount is heuristic since vars may be
1123 johnpye 219 used in relations higher in the tree than the problem is rooted.
1124 aw0a 1 */
1125     break;
1126     case BOOLEAN_ATOM_INST:
1127     if ( ( boolean_var(inst) && LogRelationsCount(inst) ) ||
1128     WhensCount(inst) ) {
1129     p_data->ndv++;
1130     }
1131     else {
1132     p_data->nud++;
1133     }
1134     break;
1135     case BOOLEAN_CONSTANT_INST:
1136     case INTEGER_ATOM_INST:
1137     case INTEGER_CONSTANT_INST:
1138     if (WhensCount(inst)) {
1139     p_data->ndv++;
1140     }
1141     break;
1142     case SYMBOL_ATOM_INST:
1143     case SYMBOL_CONSTANT_INST:
1144     if (WhensCount(inst)) {
1145     symval = SCP(GetSymbolAtomValue(inst));
1146     if (symval == NULL) {
1147     FPRINTF(ASCERR,"ERROR: CountStuffInTree found undefined symbol or symbol_constant in WHEN.\n");
1148     WriteInstanceName(ASCERR,inst,p_data->root);
1149     FPRINTF(ASCERR,"\n");
1150     g_bad_rel_in_list = TRUE;
1151     return;
1152     }
1153     p_data->ndv++;
1154     }
1155     break;
1156     case LREL_INST:
1157     if( GetInstanceLogRelOnly(inst) == NULL ) {
1158     FPRINTF(ASCERR,"ERROR: CountStuffInTree found bad logrel.\n");
1159     WriteInstanceName(ASCERR,inst,p_data->root);
1160     FPRINTF(ASCERR,"\n");
1161     g_bad_rel_in_list = TRUE;
1162     return;
1163     }
1164     if ( LogRelIsCond(GetInstanceLogRel(inst)) ) {
1165     p_data->ncl++;
1166     }
1167     else {
1168     p_data->nl++;
1169     }
1170     break;
1171     case WHEN_INST:
1172     p_data->nw++;
1173     break;
1174     case MODEL_INST:
1175     p_data->nm++;
1176     break;
1177     default:
1178     break;
1179     }
1180     }
1181     }
1182    
1183 johnpye 219
1184 johnpye 669 /**
1185 johnpye 219 This takes the already derived counts,
1186     allocates all the memory we need to allocate for master,
1187     and builds the var/rel/MODEL/etc master lists.
1188     filling in p_data and ips as far as possible.
1189     Returns 0 normally, or 1 if insufficient memory, 2 if nothing to do.
1190     If 1, then the user should deallocate any partial results in
1191     a separate cleanup function for p_data->
1192    
1193     In particular, after this is done we have
1194     vars with correct ip values for:
1195     index;
1196     incident;
1197     in_block;
1198     fixed; (as flag)
1199     basis; (as flag)
1200     solvervar; (as flag)
1201     relations and conditional relations with correct ip values for:
1202     index;
1203     model;
1204     obj; (0 constraint, -1 maximize, +1 minimize)
1205     ext;
1206     inwhen;
1207     cond;
1208     included; (as flag)
1209     discrete vars with correct ip values for:
1210     index;
1211     incident;
1212     isconst;
1213     distype;
1214     fixed; (as flag)
1215     booleanvar; (as flag)
1216     inwhen;
1217     logrelations and conditional logrelations with correct ip values for:
1218     index;
1219     model;
1220     included; (as flag)
1221     inwhen;
1222     cond;
1223     whens with correct ip values for:
1224     index;
1225     model;
1226     inwhen;
1227     models with correct ip values for:
1228     index;
1229    
1230     Note that these are all indexed from 1, being stored in gllists.
1231     */
1232 aw0a 1 static int analyze_make_master_lists(struct problem_t *p_data)
1233     {
1234     long int c, len,v,vlen;
1235     CONST struct Instance *i;
1236     CONST struct relation *gut;
1237     CONST struct logrelation *lgut;
1238     struct solver_ipdata *vip;
1239     struct gl_list_t *scratch;
1240     size_t reqlen;
1241     int stat;
1242 johnpye 190 reqlen =
1243 aw0a 1 p_data->nr + p_data->no + p_data->nc + p_data->nl+ p_data->ncl+ /*rels*/
1244     p_data->nv + p_data->ndv +
1245     p_data->np + p_data->nu + p_data->nud + /* atoms */
1246     p_data->nw + /* when */
1247     p_data->nm; /* model */
1248     if (reqlen <1) {
1249     return 2;
1250     }
1251    
1252     /* CREATE memory for ips */
1253     #ifdef NDEBUG
1254     stat = resize_ipbuf(reqlen,0);
1255     #else
1256     stat = resize_ipbuf(reqlen,1);
1257     #endif /* NDEBUG */
1258     if (stat) {
1259     FPRINTF(ASCERR,"Error: (analyze_make_master) Insufficient memory.\n");
1260     return 1;
1261     }
1262    
1263     p_data->vars = gl_create(p_data->nv); /* variables */
1264     if (p_data->vars == NULL) return 1;
1265    
1266     p_data->dvars = gl_create(p_data->ndv); /* discrete variables */
1267     if (p_data->dvars == NULL) return 1;
1268    
1269     p_data->pars = gl_create(p_data->np); /* parameters */
1270     if (p_data->pars == NULL) return 1;
1271    
1272     p_data->unas = gl_create(p_data->nu); /* unattached */
1273     if (p_data->unas == NULL) return 1;
1274    
1275     p_data->dunas = gl_create(p_data->nud); /* discrete unattached */
1276     if (p_data->dunas == NULL) return 1;
1277    
1278     p_data->cnds = gl_create(p_data->nc); /* conditional relations */
1279     if (p_data->cnds == NULL) return 1;
1280    
1281     p_data->rels = gl_create(p_data->nr); /* relations */
1282     if (p_data->rels == NULL) return 1;
1283    
1284     p_data->logrels = gl_create(p_data->nl); /* logical relations */
1285     if (p_data->logrels == NULL) return 1;
1286    
1287     p_data->logcnds = gl_create(p_data->ncl); /* conditional logrelations */
1288     if (p_data->logcnds == NULL) return 1;
1289    
1290     p_data->extrels = gl_create(p_data->ne); /* extrelations */
1291     if (p_data->extrels == NULL) return 1;
1292    
1293     p_data->objrels = gl_create(p_data->no); /* objectives */
1294     if (p_data->objrels == NULL) return 1;
1295    
1296     p_data->whens = gl_create(p_data->nw); /* whens */
1297     if (p_data->whens == NULL) return 1;
1298    
1299     p_data->models = gl_create(p_data->nm); /* models */
1300     if (p_data->models == NULL) return 1;
1301    
1302     /* decorate the instance tree with ips, collecting vars and models. */
1303     p_data->oldips = PushInterfacePtrs(p_data->root,classify_instance,
1304     g_reuse.ipcap,1,p_data);
1305     if (p_data->oldips == NULL) {
1306     FPRINTF(ASCERR,"Error: (analyze) Insufficient memory.\n");
1307     return 1;
1308     }
1309    
1310 johnpye 190 /*
1311 johnpye 219 collect relations, objectives, logrels and whens recording the
1312     MODEL number in each rel's ip and setting incidence.
1313     */
1314 aw0a 1 len = gl_length(p_data->models);
1315     for (c=1; c <= len; c++) {
1316     CollectRelsAndWhens(SIP(gl_fetch(p_data->models,c)),c,p_data);
1317     SIP(gl_fetch(p_data->models,c))->u.m.index = c;
1318     }
1319     if ((long)gl_length(p_data->rels) != p_data->nr ||
1320     (long)gl_length(p_data->objrels) != p_data->no ||
1321     (long)gl_length(p_data->logrels) != p_data->nl ||
1322     (long)gl_length(p_data->whens) != p_data->nw) {
1323     FPRINTF(ASCERR,
1324     "Warning: Mismatch in problem census and problem found\n");
1325     FPRINTF(ASCERR,"Rels: Counted %lu\t Found %ld\n",
1326     gl_length(p_data->rels), p_data->nr);
1327     FPRINTF(ASCERR,"Objs: Counted %lu\t Found %ld\n",
1328     gl_length(p_data->objrels), p_data->no);
1329     FPRINTF(ASCERR,"LogRels: Counted %lu\t Found %ld\n",
1330     gl_length(p_data->logrels),p_data->nl);
1331     FPRINTF(ASCERR,"Whens: Counted %lu\t Found %ld\n",
1332     gl_length(p_data->whens), p_data->nw);
1333     }
1334 johnpye 190 /*
1335 johnpye 219 relation list is now grouped by model, and the order will be
1336     invariant with hardware and ascend invocation so long as
1337     set FIRSTCHOICE holds in compilation.
1338     */
1339 aw0a 1 /* mark vars in constraints incident and index rels */
1340     len = gl_length(p_data->rels);
1341     for (c=1; c <= len; c++) {
1342     SIP(gl_fetch(p_data->rels,c))->u.r.index = c;
1343     gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->rels,c))->i);
1344     vlen = NumberVariables(gut);
1345     for( v = 1; v <= vlen; v++ ) {
1346     i = RelationVariable(gut,v);
1347     SIP(GetInterfacePtr(i))->u.v.incident = 1;
1348     }
1349     }
1350     /* mark vars in objectives incident */
1351     len = gl_length(p_data->objrels);
1352     for (c=1; c <= len; c++) {
1353     gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->objrels,c))->i);
1354     vlen = NumberVariables(gut);
1355     for( v = 1; v <= vlen; v++ ) {
1356     i = RelationVariable(gut,v);
1357     SIP(GetInterfacePtr(i))->u.v.incident = 1;
1358     }
1359     }
1360    
1361     /* mark vars in conditional relations incident */
1362     len = gl_length(p_data->cnds);
1363     for (c=1; c <= len; c++) {
1364     SIP(gl_fetch(p_data->cnds,c))->u.r.index = c;
1365     gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->cnds,c))->i);
1366     vlen = NumberVariables(gut);
1367     for( v = 1; v <= vlen; v++ ) {
1368     i = RelationVariable(gut,v);
1369     SIP(GetInterfacePtr(i))->u.v.incident = 1;
1370     }
1371     }
1372    
1373     /* mark dvars in logrels incident and index logrels */
1374     len = gl_length(p_data->logrels);
1375     for (c=1; c <= len; c++) {
1376     SIP(gl_fetch(p_data->logrels,c))->u.lr.index = c;
1377     lgut = GetInstanceLogRelOnly(SIP(gl_fetch(p_data->logrels,c))->i);
1378     vlen = NumberBoolVars(lgut);
1379     for( v = 1; v <= vlen; v++ ) {
1380     i = LogRelBoolVar(lgut,v);
1381     SIP(GetInterfacePtr(i))->u.dv.incident = 1;
1382     }
1383     }
1384    
1385    
1386     /* mark dvars in conditional logrels incident */
1387     len = gl_length(p_data->logcnds);
1388     for (c=1; c <= len; c++) {
1389     SIP(gl_fetch(p_data->logcnds,c))->u.lr.index = c;
1390     lgut = GetInstanceLogRelOnly(SIP(gl_fetch(p_data->logcnds,c))->i);
1391     vlen = NumberBoolVars(lgut);
1392     for( v = 1; v <= vlen; v++ ) {
1393     i = LogRelBoolVar(lgut,v);
1394     SIP(GetInterfacePtr(i))->u.dv.incident = 1;
1395     }
1396     }
1397    
1398     /* mark index whens */
1399     len = gl_length(p_data->whens);
1400     for (c=1; c <= len; c++) {
1401     SIP(gl_fetch(p_data->whens,c))->u.w.index = c;
1402     }
1403 johnpye 190 /*
1404 johnpye 219 now we need to move all the nonincident vars off the var list
1405     onto the unas list. It is easiest to make a new list and copy
1406     the existing var list to either it if keep or unas if punt.
1407     the same goes for parameters that aren't incident.
1408     We don't do exactly the same for discrete variables because
1409     many of them are not incident but they are used in when's
1410     */
1411 aw0a 1 len = gl_length(p_data->vars);
1412     p_data->tmplist = gl_create(len);
1413     if (p_data->tmplist == NULL) return 1;
1414     for (c=1; c <= len; c++) {
1415     /* dispose of var */
1416     vip = SIP(gl_fetch(p_data->vars,c));
1417     if ( vip->u.v.incident == 1) {
1418     gl_append_ptr(p_data->tmplist,vip);
1419     } else {
1420     gl_append_ptr(p_data->unas,vip);
1421     }
1422     }
1423     gl_destroy(p_data->vars); /* punt the old list */
1424     p_data->vars = p_data->tmplist; /* make shortened list var list */
1425     p_data->tmplist = NULL;
1426    
1427     p_data->nv = gl_length(p_data->vars);
1428    
1429     len = gl_length(p_data->pars);
1430     p_data->tmplist = gl_create(len);
1431     if (p_data->tmplist == NULL) {
1432     return 1;
1433     }
1434     for (c=1; c <= len; c++) {
1435     /* dispose of par */
1436     vip = SIP(gl_fetch(p_data->pars,c));
1437     if ( vip->u.v.incident == 1) {
1438     gl_append_ptr(p_data->tmplist,vip);
1439     } else {
1440     gl_append_ptr(p_data->unas,vip);
1441     }
1442     }
1443     gl_destroy(p_data->pars); /* punt the old list */
1444     p_data->pars = p_data->tmplist; /* make shortened list par list */
1445     p_data->tmplist = NULL;
1446    
1447     p_data->np = gl_length(p_data->pars);
1448 johnpye 190 p_data->nu = gl_length(p_data->unas);
1449    
1450 aw0a 1 /*
1451 johnpye 219 discrete variables: take the incident dis vars in logrels first,
1452     then append the dis vars which are used only in whens
1453     */
1454 aw0a 1 p_data->lrelinc = 0;
1455     len = gl_length(p_data->dvars);
1456     if ( len > 0) {
1457     p_data->tmplist = gl_create(len);
1458     scratch = gl_create(2L);
1459     if (p_data->tmplist == NULL) return 1;
1460     for (c=1; c <= len; c++) {
1461     /* dispose of incident discrete vars */
1462     vip = SIP(gl_fetch(p_data->dvars,c));
1463     if ( vip->u.dv.incident == 1) {
1464     gl_append_ptr(p_data->tmplist,vip);
1465     p_data->lrelinc++; /* Number of incident dis vars */
1466     } else {
1467     gl_append_ptr(scratch,vip);
1468     }
1469     }
1470     gl_destroy(p_data->dvars);
1471     p_data->dvars = p_data->tmplist;
1472     p_data->tmplist = NULL;
1473     /* append discrete non-boolean vars at the end of the list */
1474     len = gl_length(scratch);
1475     for (c=1; c <= len; c++) {
1476     vip = SIP(gl_fetch(scratch,c));
1477     gl_append_ptr(p_data->dvars,vip);
1478     }
1479     gl_destroy(scratch);
1480     scratch = NULL;
1481     }
1482    
1483     /*
1484 johnpye 219 The following patch is to avoid the system to crash.
1485     When multiple definitions of a solver_var have introduced into the
1486     system, ASCEND may fail in identifying that a REAL_ATOM is a refinement
1487     of a solver_var. This causes the system to think that, even that there
1488     are relations into the system, there are no incidences in these relations
1489     that fall into the category of a variable. As a consequence, the length
1490     of the list of variables is zero. That of course will introduce
1491     insanities while trying to build the slv system. Some
1492     solutions to this problem are:
1493 johnpye 190
1494 johnpye 219 The easier for us is just to alert the user and to force him/her to
1495     reload all the type defintions again. That is the current solution
1496    
1497     The correct (but time consuming) solution is the implementation of a
1498     SolverAtomInstance, which still needs parser and interpreter support
1499     */
1500    
1501 aw0a 1 if (p_data->nr != 0 && p_data->nv==0) {
1502     FPRINTF(ASCERR, "\n");
1503     FPRINTF(ASCERR, "A L E R T\n");
1504 johnpye 190 FPRINTF(ASCERR, "\n");
1505 aw0a 1 FPRINTF(ASCERR, "Problem should contain at least one variable %s",
1506     "and one relation\n");
1507 johnpye 190 FPRINTF(ASCERR, "\n");
1508 aw0a 1 FPRINTF(ASCERR, "There are relations into the system, but the number \n");
1509     FPRINTF(ASCERR, "of variables is zero. That means that the existent \n");
1510     FPRINTF(ASCERR, "vars were not recognized as solver_vars. A possible \n");
1511     FPRINTF(ASCERR, "reason is that you have introduced conflicting \n");
1512     FPRINTF(ASCERR, "definitions of solver_var into the system. Please \n");
1513     FPRINTF(ASCERR, "delete all your types and reload your models \n");
1514     FPRINTF(ASCERR, "with the appropriate definition of solver_var\n");
1515     FPRINTF(ASCERR, "\n");
1516     FPRINTF(ASCERR, "Solver system will not be built.\n");
1517     FPRINTF(ASCERR, "\n");
1518     return 2;
1519     }
1520 johnpye 190
1521 aw0a 1 return 0;
1522     }
1523    
1524 johnpye 669 /**
1525 johnpye 219 This function cleans up an errant problem_t or a good one that we're
1526     done with. We should have set to null any pointers to memory we are
1527     keeping elsewhere before calling this.
1528     */
1529 johnpye 669 static void analyze_free_lists(struct problem_t *p_data)
1530     {
1531     /* memory containing gl_lists of atomic structure pointers */
1532     if(p_data->extrels != NULL)gl_free_and_destroy(p_data->extrels);
1533    
1534 aw0a 1 #define AFUN(ptr) if (ptr!=NULL) ascfree(ptr); (ptr) = NULL
1535     #define ADUN(ptr) if (ptr!=NULL) gl_destroy(ptr); (ptr) = NULL
1536 johnpye 669
1537     /* gl_lists without memory items use ADUN */
1538 aw0a 1 ADUN(p_data->vars);
1539     ADUN(p_data->dvars);
1540     ADUN(p_data->pars);
1541     ADUN(p_data->unas);
1542     ADUN(p_data->dunas);
1543     ADUN(p_data->rels);
1544     ADUN(p_data->objrels);
1545     ADUN(p_data->models);
1546     ADUN(p_data->cnds);
1547     ADUN(p_data->logrels);
1548     ADUN(p_data->logcnds);
1549     ADUN(p_data->whens);
1550 johnpye 669
1551     /* blocks of memory use AFUN */
1552 aw0a 1 AFUN(p_data->blocks);
1553     AFUN(p_data->reldata);
1554     AFUN(p_data->objdata);
1555     AFUN(p_data->condata);
1556     AFUN(p_data->lrdata);
1557     AFUN(p_data->logcondata);
1558     AFUN(p_data->vardata);
1559     AFUN(p_data->pardata);
1560     AFUN(p_data->undata);
1561     AFUN(p_data->disdata);
1562     AFUN(p_data->undisdata);
1563     AFUN(p_data->whendata);
1564     AFUN(p_data->bnddata);
1565     AFUN(p_data->relincidence);
1566     AFUN(p_data->varincidence);
1567     AFUN(p_data->logrelinciden);
1568     AFUN(p_data->mastervl);
1569     AFUN(p_data->masterdl);
1570     AFUN(p_data->masterrl);
1571     AFUN(p_data->masterol);
1572     AFUN(p_data->mastercl);
1573     AFUN(p_data->masterll);
1574     AFUN(p_data->mastercll);
1575     AFUN(p_data->masterpl);
1576     AFUN(p_data->masterul);
1577     AFUN(p_data->masterdul);
1578     AFUN(p_data->masterwl);
1579     AFUN(p_data->masterbl);
1580     AFUN(p_data->solvervl);
1581     AFUN(p_data->solverdl);
1582     AFUN(p_data->solverrl);
1583     AFUN(p_data->solverol);
1584     AFUN(p_data->solvercl);
1585     AFUN(p_data->solverll);
1586     AFUN(p_data->solvercll);
1587     AFUN(p_data->solverpl);
1588     AFUN(p_data->solverul);
1589     AFUN(p_data->solverdul);
1590     AFUN(p_data->solverwl);
1591     AFUN(p_data->solverbl);
1592     AFUN(p_data->erlist);
1593 johnpye 669
1594     #undef AFUN
1595     #undef ADUN
1596 aw0a 1 }
1597    
1598    
1599 johnpye 669 /*------------------------------------------------------------------------------
1600     'WHEN' PROCESSING
1601 johnpye 219 */
1602 aw0a 1
1603 johnpye 669 /**
1604 johnpye 219 This function receives as argument the list of values of each of the
1605     CASES of a WHEN statement. The values in the list can be integer values,
1606     symbol values, or boolean values. So, the goal of this function is to
1607     obtain an equivalent list of ONLY integer values for such a list. In this
1608     way, for example, the boolean value TRUE is equivalent to the integer
1609     1. The function GentIntFromSymbol is used to generate an integer value
1610     which will be equivalent to a symbol value
1611     */
1612 aw0a 1 static
1613     void ProcessValueList(struct Set *ValueList, int *value,
1614     struct gl_list_t *symbol_list)
1615     {
1616     CONST struct Expr *expr;
1617     struct Set *s;
1618    
1619     s = ValueList;
1620     if (ValueList!=NULL) {
1621     while (s != NULL) {
1622     expr = GetSingleExpr(s);
1623     switch(ExprType(expr)) {
1624     case e_boolean:
1625     *value = ExprBValue(expr);
1626     if (*value == 2) { /* ANY */
1627     *value = -2;
1628     }
1629     break;
1630     case e_int:
1631     *value = ExprIValue(expr);
1632     break;
1633     case e_symbol:
1634     *value = GetIntFromSymbol(SCP(ExprSymValue(expr)),symbol_list);
1635     break;
1636     default:
1637     break;
1638     }
1639     s = NextSet(s);
1640     value++;
1641     }
1642     } else {
1643     *value = -1; /* OTHERWISE */
1644     }
1645     }
1646    
1647    
1648 johnpye 669 /**
1649     Process arrays inside WHENs (requires a recursive analysis).
1650    
1651     @see ProcessSolverWhens
1652 johnpye 219 */
1653 aw0a 1 static
1654     void ProcessArraysInWhens(struct Instance *cur_inst,
1655     struct gl_list_t *rels,
1656     struct gl_list_t *logrels,
1657     struct gl_list_t *whens)
1658     {
1659     struct rel_relation *rel;
1660     struct logrel_relation *lrel;
1661     struct w_when *w;
1662     struct Instance *child;
1663     struct solver_ipdata *ip;
1664     unsigned long c,nch;
1665    
1666     if (cur_inst==NULL) return;
1667     nch = NumberChildren(cur_inst);
1668     for (c=1;c<=nch;c++) {
1669     child = InstanceChild(cur_inst,c);
1670     if (child==NULL) continue;
1671     switch (InstanceKind(child)) {
1672     case REL_INST:
1673     ip = SIP(GetInterfacePtr(child));
1674     ip->u.r.active = 0;
1675     rel = ip->u.r.data;
1676     gl_append_ptr(rels,rel);
1677     break;
1678     case LREL_INST:
1679     ip = SIP(GetInterfacePtr(child));
1680     ip->u.lr.active = 0;
1681     lrel = ip->u.lr.data;
1682     gl_append_ptr(logrels,lrel);
1683     break;
1684     case WHEN_INST:
1685     ip = SIP(GetInterfacePtr(child));
1686     w = ip->u.w.data;
1687     gl_append_ptr(whens,w);
1688     when_set_inwhen(w,TRUE);
1689     break;
1690     case MODEL_INST:
1691     ProcessModelsInWhens(child,rels,logrels,whens);
1692     break;
1693     case ARRAY_ENUM_INST:
1694     case ARRAY_INT_INST:
1695     if (ArrayIsRelation(child) || ArrayIsWhen(child)
1696     || ArrayIsLogRel(child) || ArrayIsModel(child)) {
1697     ProcessArraysInWhens(child,rels,logrels,whens);
1698     }
1699     break;
1700     default:
1701     break;
1702     }
1703     }
1704     }
1705    
1706 johnpye 669 /**
1707     Process MODELs inside WHENs (requires a recursive analysis).
1708    
1709     @see ProcessSolverWhens
1710     */
1711 aw0a 1 static
1712     void ProcessModelsInWhens(struct Instance *cur_inst, struct gl_list_t *rels,
1713     struct gl_list_t *logrels, struct gl_list_t *whens)
1714     {
1715     struct rel_relation *rel;
1716     struct logrel_relation *lrel;
1717     struct w_when *w;
1718     struct Instance *child;
1719     struct solver_ipdata *ip;
1720     unsigned long c,nch;
1721    
1722     if (cur_inst==NULL) return;
1723     nch = NumberChildren(cur_inst);
1724     for (c=1;c<=nch;c++) {
1725     child = InstanceChild(cur_inst,c);
1726     if (child==NULL) continue;
1727     switch (InstanceKind(child)) {
1728     case REL_INST:
1729     ip = SIP(GetInterfacePtr(child));
1730     ip->u.r.active = 0;
1731     rel = ip->u.r.data;
1732     gl_append_ptr(rels,rel);
1733     break;
1734     case LREL_INST:
1735     ip = SIP(GetInterfacePtr(child));
1736     ip->u.lr.active = 0;
1737     lrel = ip->u.lr.data;
1738     gl_append_ptr(logrels,lrel);
1739     break;
1740     case WHEN_INST:
1741     ip = SIP(GetInterfacePtr(child));
1742     w = ip->u.w.data;
1743     gl_append_ptr(whens,w);
1744     when_set_inwhen(w,TRUE);
1745     break;
1746     case MODEL_INST:
1747     ProcessModelsInWhens(child,rels,logrels,whens);
1748     break;
1749     case ARRAY_ENUM_INST:
1750     case ARRAY_INT_INST:
1751     if (ArrayIsRelation(child) || ArrayIsWhen(child)
1752     || ArrayIsLogRel(child) || ArrayIsModel(child)) {
1753     ProcessArraysInWhens(child,rels,logrels,whens);
1754     }
1755     break;
1756     default:
1757     break;
1758     }
1759     }
1760     }
1761    
1762    
1763 johnpye 669 /**
1764     Fill in the list of cases and variables of a w_when structure with
1765     the appropriate data.
1766    
1767     The information required is provided by the corresponding when Instance
1768     generated in the compilation time. So, what we do is:
1769 johnpye 219 1) Obtain the list of variables and the list of cases from each
1770     WHEN intance.
1771     The list of variables is actually a list of pointers to instances
1772     2) From each CASE, obtain also the list of references. This list of
1773     references contains a list of pointers to each relation,logrelation and
1774     model included inside the case.
1775     3) The pointers to the variables, relations, logrelations and models are
1776     used to obtain the solver data associated with the compiled instances.
1777     4) Arrays and models are managed recursively with the two previous
1778     functions.
1779     */
1780 aw0a 1 static
1781     void ProcessSolverWhens(struct w_when *when,struct Instance *i)
1782     {
1783     struct gl_list_t *scratch;
1784     struct gl_list_t *wvars;
1785     struct gl_list_t *ref;
1786     struct gl_list_t *rels;
1787     struct gl_list_t *logrels;
1788     struct gl_list_t *whens;
1789     struct gl_list_t *diswhens;
1790     struct Set *ValueList;
1791     struct Instance *cur_inst;
1792     struct Case *cur_case;
1793     struct solver_ipdata *ip;
1794     struct dis_discrete *dvar;
1795     struct rel_relation *rel;
1796     struct logrel_relation *lrel;
1797     struct w_when *w;
1798     struct when_case *cur_sol_case;
1799     int c,r,len,lref;
1800     int *value;
1801    
1802     scratch = GetInstanceWhenVars(i);
1803     len = gl_length(scratch);
1804     wvars = gl_create(len);
1805     when->dvars = wvars;
1806     for (c=1;c<=len;c++) {
1807     cur_inst = (struct Instance *)(gl_fetch(scratch,c));
1808     ip = SIP(GetInterfacePtr(cur_inst));
1809     dvar = ip->u.dv.data;
1810     if (dis_whens_list(dvar)==NULL) {
1811     diswhens = gl_create(2L);
1812     dis_set_whens_list(dvar,diswhens);
1813     } else {
1814     diswhens = dis_whens_list(dvar);
1815     }
1816     gl_append_ptr(diswhens,when);
1817     gl_append_ptr(when->dvars,dvar);
1818     }
1819    
1820     scratch = GetInstanceWhenCases(i);
1821     len = gl_length(scratch);
1822     when->cases = gl_create(len);
1823     for (c=1;c<=len;c++) {
1824     cur_sol_case = when_case_create(NULL);
1825     cur_case = (struct Case *)(gl_fetch(scratch,c));
1826     ValueList = GetCaseValues(cur_case);
1827     value = &(cur_sol_case->values[0]);
1828     if (g_symbol_values_list == NULL) {
1829     g_symbol_values_list = gl_create(2L);
1830     }
1831     ProcessValueList(ValueList,value,g_symbol_values_list);
1832     ref = GetCaseReferences(cur_case);
1833     lref = gl_length(ref);
1834     rels = gl_create(lref); /* maybe allocating less than needed (models) */
1835     logrels = gl_create(lref); /* maybe allocating less than needed */
1836     whens = gl_create(lref); /* maybe allocating more than needed */
1837     for (r=1;r<=lref;r++) {
1838     cur_inst = (struct Instance *)(gl_fetch(ref,r));
1839     switch(InstanceKind(cur_inst)){
1840     case REL_INST:
1841     ip = SIP(GetInterfacePtr(cur_inst));
1842     ip->u.r.active = 0;
1843     rel = ip->u.r.data;
1844     gl_append_ptr(rels,rel);
1845     break;
1846     case LREL_INST:
1847     ip = SIP(GetInterfacePtr(cur_inst));
1848     ip->u.lr.active = 0;
1849     lrel = ip->u.lr.data;
1850     gl_append_ptr(logrels,lrel);
1851     break;
1852     case WHEN_INST:
1853     ip = SIP(GetInterfacePtr(cur_inst));
1854     w = ip->u.w.data;
1855     gl_append_ptr(whens,w);
1856     when_set_inwhen(w,TRUE);
1857     break;
1858     case MODEL_INST:
1859     ProcessModelsInWhens(cur_inst,rels,logrels,whens);
1860     break;
1861     default:
1862     break;
1863     }
1864     }
1865     when_case_set_rels_list(cur_sol_case,rels);
1866     when_case_set_logrels_list(cur_sol_case,logrels);
1867     when_case_set_whens_list(cur_sol_case,whens);
1868     when_case_set_active(cur_sol_case,FALSE);
1869     gl_append_ptr(when->cases,cur_sol_case);
1870     }
1871     }
1872    
1873 johnpye 669 /*------------------------------------------------------------------------------
1874     RECONFIGURATION OF CONDITIONAL MODELS
1875 aw0a 1
1876 johnpye 669 /**
1877     Is this (discrete) variable inside a WHEN?
1878 aw0a 1
1879 johnpye 669 @return
1880     1 if discrete var is a member of the when var list,
1881     else 0
1882 johnpye 219 */
1883 aw0a 1 int dis_var_in_a_when(struct Instance *var, struct w_when *when)
1884     {
1885     struct Instance *winst;
1886    
1887     winst = (struct Instance *)(when_instance(when));
1888     return VarFoundInWhen(var,winst);
1889     }
1890    
1891    
1892 johnpye 669 /**
1893 johnpye 219 Determine if the conditional variable inst is part of the
1894     variable list of some when in the when list.
1895     */
1896 aw0a 1 int varinst_found_in_whenlist(slv_system_t sys, struct Instance *inst)
1897     {
1898     struct w_when **whenlist;
1899     struct w_when *when;
1900     int c;
1901    
1902     whenlist = slv_get_solvers_when_list(sys);
1903     for (c=0; whenlist[c]!=NULL; c++) {
1904     when = whenlist[c];
1905     if (dis_var_in_a_when(inst,when)) {
1906     return 1;
1907     }
1908     }
1909     return 0;
1910     }
1911    
1912 johnpye 669 /*------------------------------------------------------------------------------
1913     BOUNDARY PROCESSING
1914 johnpye 219 */
1915 aw0a 1
1916 johnpye 669 /**
1917 johnpye 219 Get the list or logrelation including a boundary (by means of a
1918     SATISFIED term). This function look the structures in the compiler
1919     side and make the same link in the solver side
1920     */
1921 aw0a 1 static
1922     void GetListOfLogRels(struct bnd_boundary *bnd, struct Instance *inst)
1923     {
1924     struct gl_list_t *logrels;
1925     unsigned long c,len;
1926     struct Instance *i;
1927     struct logrel_relation *lrel;
1928     struct solver_ipdata *lrip;
1929    
1930     len = LogRelationsCount(inst);
1931    
1932     if (len>0) {
1933     logrels = gl_create(len);
1934     for (c=1; c<=len; c++) {
1935     i = LogRelationsForInstance(inst,c);
1936     lrip = SIP(GetInterfacePtr(i));
1937     lrel = lrip->u.lr.data;
1938     gl_append_ptr(logrels,lrel);
1939     }
1940     bnd_set_logrels(bnd,logrels);
1941     }
1942     return;
1943     }
1944    
1945 johnpye 669 /**
1946 johnpye 219 Get the tolerance used to define the satisfaction of a boundary
1947     (Defined in the SATISFIED term)
1948     */
1949 aw0a 1 static
1950     void GetTolerance(struct bnd_boundary *bnd)
1951     {
1952     struct gl_list_t *logrels;
1953     unsigned long c,len;
1954     struct logrel_relation *lrel;
1955     struct Instance *i,*rel;
1956     double tolerance;
1957    
1958     rel = (struct Instance *)(rel_instance(bnd_rel(bnd_real_cond(bnd))));
1959     logrels = bnd_logrels(bnd);
1960     len = gl_length(logrels);
1961     for (c=1; c<=len; c++) {
1962     lrel = (struct logrel_relation *)(gl_fetch(logrels,c));
1963     i = (struct Instance *)(logrel_instance(lrel));
1964     if (FindTolInSatTermOfLogRel(i,rel,&tolerance )) {
1965     bnd_set_tolerance(bnd,tolerance);
1966     return;
1967     }
1968     }
1969     }
1970    
1971 johnpye 669 /**
1972 johnpye 219 Here we roll the master lists and bridge data into relation/var/
1973     logrelation/conditional/when etc. lists for the consumer.
1974     Includes fixing up rel caches and initing flagbits as best we can.
1975     includes setting master indices on rel/var/logrel/when etc.
1976     returns 0 if ok, 1 if out of memory, 2 if the problem does not
1977     contain at least one variable in one equation
1978     */
1979 aw0a 1 static int analyze_make_solvers_lists(struct problem_t *p_data)
1980     {
1981     CONST struct relation *gut;
1982     CONST struct logrelation *lgut;
1983     struct ExtRelCache *cache;
1984     struct Instance *i;
1985     struct Instance *i_r;
1986 johnpye 89 struct solver_ipdata *rip = NULL, *vip;
1987 aw0a 1 struct solver_ipdata *lrip, *dvip, *wip;
1988     struct var_variable **incidence = NULL;
1989     struct rel_relation **varincidence = NULL;
1990     struct dis_discrete **logincidence = NULL;
1991     struct var_variable *var;
1992     struct rel_relation *rel;
1993     struct dis_discrete *dvar;
1994     struct logrel_relation *lrel;
1995     struct bnd_boundary *bnd;
1996     struct w_when *when;
1997     int order,nnzold, nodestamp;
1998     int logorder,lognnzold;
1999     int c,len,v,vlen,r,found;
2000     uint32 flags;
2001    
2002     order = MAX(gl_length(p_data->vars),gl_length(p_data->rels));
2003 johnpye 190 nnzold = p_data->nnz = p_data->nnztot
2004 aw0a 1 = p_data->nnzobj = p_data->nnzcond = 0;
2005     p_data->nrow = 0; /* number of included relations */
2006     for (c=1,len = gl_length(p_data->rels); c <= len; c++) {
2007     rip = SIP(gl_fetch(p_data->rels,c));
2008     gut = GetInstanceRelationOnly(rip->i);
2009     vlen = NumberVariables(gut);
2010     p_data->nnztot += vlen;
2011     if (rip->u.r.included) {
2012     p_data->nrow++;
2013     nnzold = p_data->nnz;
2014     for( v = 1 ; v <= vlen; v++ ) {
2015     i = RelationVariable(gut,v);
2016     vip = SIP(GetInterfacePtr(i));
2017     if (!(vip->u.v.fixed)) {
2018     p_data->nnz++;
2019     }
2020     }
2021     if (p_data->nnz==nnzold) {
2022 johnpye 222 ERROR_REPORTER_START_NOLINE(ASC_USER_WARNING);
2023 johnpye 76 FPRINTF(ASCERR,"No free variables in included relation '");
2024     WriteInstanceName(ASCERR,rip->i,p_data->root);
2025     FPRINTF(ASCERR,"'");
2026     error_reporter_end_flush();
2027 aw0a 1 }
2028     }
2029     }
2030     for (c=1,len = gl_length(p_data->objrels); c <= len; c++) {
2031     rip = SIP(gl_fetch(p_data->objrels,c));
2032     gut = GetInstanceRelationOnly(rip->i);
2033     vlen = NumberVariables(gut);
2034     p_data->nnzobj += vlen;
2035     }
2036    
2037     /* Conditional relations */
2038     for (c=1,len = gl_length(p_data->cnds); c <= len; c++) {
2039     rip = SIP(gl_fetch(p_data->cnds,c));
2040     gut = GetInstanceRelationOnly(rip->i);
2041     vlen = NumberVariables(gut);
2042     p_data->nnzcond += vlen;
2043     }
2044    
2045    
2046 johnpye 190 /*
2047 johnpye 219 calculate the number of free and incident variables, ncol
2048     we put all the nonincident on the unas list, so just check fixed.
2049     */
2050 aw0a 1 for (c=1,len = gl_length(p_data->vars); c <= len; c++) {
2051     vip = SIP(gl_fetch(p_data->vars,c));
2052     if (!(vip->u.v.fixed)) p_data->ncol++;
2053     }
2054 johnpye 190 /*
2055 johnpye 219 now, at last we have cols jacobian in the order we want the lists to
2056     be handed to the solvers.
2057     */
2058 aw0a 1
2059 johnpye 219
2060 aw0a 1 logorder = MAX((unsigned long)p_data->lrelinc,gl_length(p_data->logrels));
2061     lognnzold = p_data->lognnz = p_data->lrelincsize = 0;
2062     p_data->lognrow = 0; /* number of included logrelations */
2063     for (c=1,len = gl_length(p_data->logrels); c <= len; c++) {
2064     lrip = SIP(gl_fetch(p_data->logrels,c));
2065     lgut = GetInstanceLogRelOnly(lrip->i);
2066     vlen = NumberBoolVars(lgut);
2067     p_data->lrelincsize += vlen;
2068     if (lrip->u.lr.included) {
2069     p_data->lognrow++;
2070     lognnzold = p_data->lognnz;
2071     for( v = 1 ; v <= vlen; v++ ) {
2072     i = LogRelBoolVar(lgut,v);
2073     dvip = SIP(GetInterfacePtr(i));
2074     if (!(dvip->u.dv.fixed)) {
2075     p_data->lognnz++;
2076     }
2077     }
2078     if (p_data->lognnz==lognnzold) {
2079     FPRINTF(ASCWAR,
2080     "No free boolean variables in included logrelation:\n");
2081     WriteInstanceName(ASCWAR,rip->i,p_data->root);
2082     }
2083     }
2084     }
2085    
2086     /* Conditional logrelations */
2087     for (c=1,len = gl_length(p_data->logcnds); c <= len; c++) {
2088     lrip = SIP(gl_fetch(p_data->logcnds,c));
2089     lgut = GetInstanceLogRelOnly(lrip->i);
2090     vlen = NumberBoolVars(lgut);
2091     p_data->lrelincsize += vlen;
2092     }
2093    
2094     if (!(p_data->nnztot+p_data->nnzobj) && !(p_data->lognnz)) {
2095     FPRINTF(ASCERR, "Problem should contain at least one variable %s",
2096     "and one relation\n");
2097     return 2;
2098     }
2099     /*
2100 johnpye 219 we want at least one variable in one obj or rel,
2101     or at least one boolean variable in one logrel
2102     */
2103 aw0a 1
2104    
2105     /* calculate the number of free and incident boolean variables, logncol */
2106     for (c=1,len = p_data->lrelinc; c <= len; c++) {
2107     dvip = SIP(gl_fetch(p_data->dvars,c));
2108     if (!(dvip->u.dv.fixed)) p_data->logncol++;
2109     }
2110    
2111 johnpye 219
2112 aw0a 1 /* now malloc and build things, remember to punt the matrix soon */
2113     /* remember we must NEVER free these things individually. */
2114    
2115     #define ALLOCVARDATA(p,n) (p) = (struct var_variable *)( \
2116     ((n)>0) ? ascmalloc((n)*sizeof(struct var_variable)) : NULL)
2117     #define ALLOCRELDATA(p,n) (p) = (struct rel_relation *)( \
2118     ((n)>0) ? ascmalloc((n)*sizeof(struct rel_relation)) : NULL)
2119     #define ALLOCDISVARDATA(p,n) (p) = (struct dis_discrete *)( \
2120     ((n)>0) ? ascmalloc((n)*sizeof(struct dis_discrete)) : NULL)
2121     #define ALLOCLOGRELDATA(p,n) (p) = (struct logrel_relation *)( \
2122     ((n)>0) ? ascmalloc((n)*sizeof(struct logrel_relation)) : NULL)
2123     #define ALLOCWHENDATA(p,n) (p) = (struct w_when *)( \
2124     ((n)>0) ? ascmalloc((n)*sizeof(struct w_when)) : NULL)
2125     #define ALLOCBNDDATA(p,n) (p) = (struct bnd_boundary *)( \
2126     ((n)>0) ? ascmalloc((n)*sizeof(struct bnd_boundary)) : NULL)
2127     ALLOCVARDATA(p_data->vardata,p_data->nv);
2128     ALLOCVARDATA(p_data->pardata,p_data->np);
2129     ALLOCVARDATA(p_data->undata,p_data->nu);
2130     ALLOCDISVARDATA(p_data->disdata,p_data->ndv);
2131     ALLOCDISVARDATA(p_data->undisdata,p_data->nud);
2132     ALLOCRELDATA(p_data->reldata,p_data->nr);
2133     ALLOCRELDATA(p_data->objdata,p_data->no);
2134     ALLOCRELDATA(p_data->condata,p_data->nc);
2135     ALLOCLOGRELDATA(p_data->lrdata,p_data->nl);
2136     ALLOCLOGRELDATA(p_data->logcondata,p_data->ncl);
2137     ALLOCWHENDATA(p_data->whendata,p_data->nw);
2138     ALLOCBNDDATA(p_data->bnddata,p_data->nc+p_data->ncl);
2139    
2140     #define ALLOCVARLIST(p,n) (p) = (struct var_variable **)( \
2141     ((n)>0) ? ascmalloc((n)*sizeof(struct var_variable *)) : NULL)
2142     #define ALLOCRELLIST(p,n) (p) = (struct rel_relation **)( \
2143     ((n)>0) ? ascmalloc((n)*sizeof(struct rel_relation *)) : NULL)
2144     #define ALLOCDISVARLIST(p,n) (p) = (struct dis_discrete **)( \
2145     ((n)>0) ? ascmalloc((n)*sizeof(struct dis_discrete *)) : NULL)
2146     #define ALLOCLOGRELLIST(p,n) (p) = (struct logrel_relation **)( \
2147     ((n)>0) ? ascmalloc((n)*sizeof(struct logrel_relation *)) : NULL)
2148     #define ALLOCWHENLIST(p,n) (p) = (struct w_when **)( \
2149     ((n)>0) ? ascmalloc((n)*sizeof(struct w_when *)) : NULL)
2150     #define ALLOCBNDLIST(p,n) (p) = (struct bnd_boundary **)( \
2151     ((n)>0) ? ascmalloc((n)*sizeof(struct bnd_boundary *)) : NULL)
2152     ALLOCVARLIST(p_data->mastervl,p_data->nv+1);
2153     ALLOCVARLIST(p_data->masterpl,p_data->np+1);
2154     ALLOCVARLIST(p_data->masterul,p_data->nu+1);
2155     ALLOCDISVARLIST(p_data->masterdl,p_data->ndv+1);
2156     ALLOCDISVARLIST(p_data->masterdul,p_data->nud+1);
2157     ALLOCRELLIST(p_data->masterrl,p_data->nr+1);
2158     ALLOCRELLIST(p_data->masterol,p_data->no+1);
2159     ALLOCRELLIST(p_data->mastercl,p_data->nc+1);
2160     ALLOCLOGRELLIST(p_data->masterll,p_data->nl+1);
2161     ALLOCLOGRELLIST(p_data->mastercll,p_data->ncl+1);
2162     ALLOCWHENLIST(p_data->masterwl,p_data->nw+1);
2163     ALLOCBNDLIST(p_data->masterbl,p_data->nc+p_data->ncl+1);
2164     ALLOCVARLIST(p_data->solvervl,p_data->nv+1);
2165     ALLOCVARLIST(p_data->solverpl,p_data->np+1);
2166     ALLOCVARLIST(p_data->solverul,p_data->nu+1);
2167     ALLOCDISVARLIST(p_data->solverdl,p_data->ndv+1);
2168     ALLOCDISVARLIST(p_data->solverdul,p_data->nud+1);
2169     ALLOCRELLIST(p_data->solverrl,p_data->nr+1);
2170     ALLOCRELLIST(p_data->solverol,p_data->no+1);
2171     ALLOCRELLIST(p_data->solvercl,p_data->nc+1);
2172     ALLOCLOGRELLIST(p_data->solverll,p_data->nl+1);
2173     ALLOCLOGRELLIST(p_data->solvercll,p_data->ncl+1);
2174     ALLOCWHENLIST(p_data->solverwl,p_data->nw+1);
2175     ALLOCBNDLIST(p_data->solverbl,p_data->nc+p_data->ncl+1);
2176    
2177     ALLOCVARLIST(p_data->relincidence,p_data->nnztot+p_data->nnzobj +
2178     p_data->nnzcond);
2179     ALLOCDISVARLIST(p_data->logrelinciden,p_data->lrelincsize);
2180     #define CHECKPTRSIZE(n,p) if ((n)>0 && (p)==NULL) return 1
2181     #define CHECKPTR(p) if ((p)==NULL) return 1
2182     /* verify mem allocations. */
2183     CHECKPTRSIZE(p_data->nv,p_data->vardata);
2184     CHECKPTRSIZE(p_data->np,p_data->pardata);
2185     CHECKPTRSIZE(p_data->nu,p_data->undata);
2186     CHECKPTRSIZE(p_data->ndv,p_data->disdata);
2187     CHECKPTRSIZE(p_data->nud,p_data->undisdata);
2188     CHECKPTRSIZE(p_data->nr,p_data->reldata);
2189     CHECKPTRSIZE(p_data->no,p_data->objdata);
2190     CHECKPTRSIZE(p_data->nc,p_data->condata);
2191     CHECKPTRSIZE(p_data->nl,p_data->lrdata);
2192     CHECKPTRSIZE(p_data->ncl,p_data->logcondata);
2193     CHECKPTRSIZE(p_data->nw,p_data->whendata);
2194     CHECKPTRSIZE(p_data->nc+p_data->ncl,p_data->bnddata);
2195     CHECKPTR(p_data->mastervl);
2196     CHECKPTR(p_data->masterpl);
2197     CHECKPTR(p_data->masterul);
2198     CHECKPTR(p_data->masterdl);
2199     CHECKPTR(p_data->masterdul);
2200     CHECKPTR(p_data->masterrl);
2201     CHECKPTR(p_data->masterol);
2202     CHECKPTR(p_data->mastercl);
2203     CHECKPTR(p_data->masterll);
2204     CHECKPTR(p_data->mastercll);
2205     CHECKPTR(p_data->masterwl);
2206     CHECKPTR(p_data->masterbl);
2207     CHECKPTR(p_data->solvervl);
2208     CHECKPTR(p_data->solverpl);
2209     CHECKPTR(p_data->solverul);
2210     CHECKPTR(p_data->solverdl);
2211     CHECKPTR(p_data->solverdul);
2212     CHECKPTR(p_data->solverrl);
2213     CHECKPTR(p_data->solverol);
2214     CHECKPTR(p_data->solvercl);
2215     CHECKPTR(p_data->solverll);
2216     CHECKPTR(p_data->solvercll);
2217     CHECKPTR(p_data->solverwl);
2218     CHECKPTR(p_data->solverbl);
2219     CHECKPTR(p_data->relincidence);
2220     CHECKPTRSIZE(p_data->lrelincsize,p_data->logrelinciden);
2221     p_data->relincsize = p_data->nnztot+p_data->nnzobj + p_data->nnzcond;
2222     p_data->relincinuse = 0;
2223     p_data->lrelincinuse = 0;
2224 johnpye 669
2225     /*-------*/
2226 johnpye 190 /*
2227 johnpye 219 for c in varlist copy vardata. remember gllist # from 1 and data from 0
2228     */
2229 johnpye 190 /*
2230 johnpye 219 for c in varlist set mastervl, solvervl pointer to point to data
2231     */
2232 aw0a 1 vlen = gl_length(p_data->vars);
2233     for (v = 0; v < vlen; v++) {
2234     var = &(p_data->vardata[v]);
2235     vip = SIP(gl_fetch(p_data->vars,v+1));
2236     vip->u.v.data = var;
2237     var_set_instance(var,vip->i);
2238     var_set_mindex(var,v);
2239     var_set_sindex(var,v);
2240     flags = 0; /* all init to FALSE */
2241     /* turn on appropriate ones */
2242     if (vip->u.v.incident) flags |= VAR_INCIDENT;
2243     if (vip->u.v.in_block) flags |= VAR_INBLOCK;
2244     if (vip->u.v.fixed) flags |= VAR_FIXED;
2245     if (!vip->u.v.basis) flags |= VAR_NONBASIC;
2246     if (vip->u.v.solvervar) flags |= VAR_SVAR;
2247     var_set_flags(var,flags);
2248     p_data->mastervl[v] = var;
2249     p_data->solvervl[v] = var;
2250     }
2251     p_data->mastervl[vlen] = NULL; /* terminator */
2252     p_data->solvervl[vlen] = NULL; /* terminator */
2253 johnpye 190 /*
2254 johnpye 219 for c in parlist copy pardata. remember gllist # from 1 and data from 0
2255     for c in parlist set masterpl, solverpl pointer to point to data
2256     */
2257 aw0a 1 vlen = gl_length(p_data->pars);
2258     for (v = 0; v < vlen; v++) {
2259     var = &(p_data->pardata[v]);
2260     vip = SIP(gl_fetch(p_data->pars,v+1));
2261     vip->u.v.data = var;
2262     var_set_instance(var,vip->i);
2263     var_set_mindex(var,v);
2264     var_set_sindex(var,v);
2265     flags = 0; /* all init to FALSE */
2266     /* turn on appropriate ones */
2267     if (vip->u.v.incident) flags |= VAR_INCIDENT;
2268     if (vip->u.v.in_block) flags |= VAR_INBLOCK;
2269     if (vip->u.v.fixed) flags |= VAR_FIXED;
2270     if (vip->u.v.solvervar) flags |= VAR_SVAR; /* shouldn't this be here? */
2271     var_set_flags(var,flags);
2272     p_data->masterpl[v] = var;
2273     p_data->solverpl[v] = var;
2274     }
2275     p_data->masterpl[vlen] = NULL; /* terminator */
2276     p_data->solverpl[vlen] = NULL; /* terminator */
2277 johnpye 190 /*
2278 johnpye 219 for c in unalist copy undata. remember gllist # from 1 and data from 0
2279     for c in unalist set masterul, solverul pointer to point to data
2280     */
2281 aw0a 1 vlen = gl_length(p_data->unas);
2282     for (v = 0; v < vlen; v++) {
2283     var = &(p_data->undata[v]);
2284     vip = SIP(gl_fetch(p_data->unas,v+1));
2285     vip->u.v.data = var;
2286     var_set_instance(var,vip->i);
2287     var_set_mindex(var,v);
2288     var_set_sindex(var,v);
2289     flags = 0; /* all init to FALSE */
2290     /* turn on appropriate ones */
2291     if (vip->u.v.incident) flags |= VAR_INCIDENT;
2292     if (vip->u.v.fixed) flags |= VAR_FIXED;
2293     if (vip->u.v.solvervar) flags |= VAR_SVAR;
2294     /* others may be appropriate (PVAR) */
2295     var_set_flags(var,flags);
2296     p_data->masterul[v] = var;
2297     p_data->solverul[v] = var;
2298     }
2299     p_data->masterul[vlen] = NULL; /* terminator */
2300     p_data->solverul[vlen] = NULL; /* terminator */
2301 johnpye 219
2302 johnpye 190 /*
2303 johnpye 219 process the constraining relations
2304     for v in rellist copy reldata and fix extrels.
2305     */
2306 aw0a 1 vlen = gl_length(p_data->rels);
2307     for (v = 0; v < vlen; v++) {
2308     rel = &(p_data->reldata[v]);
2309     rip = SIP(gl_fetch(p_data->rels,v+1));
2310     rel = rel_create(rip->i,rel);
2311     rip->u.r.data = rel;
2312     rel_set_mindex(rel,v);
2313     rel_set_sindex(rel,v);
2314     rel_set_model(rel,rip->u.r.model-1);
2315     /* here set up the var list */
2316     gut = GetInstanceRelationOnly(rip->i);
2317     assert(gut!=NULL);
2318     len = NumberVariables(gut);
2319     if (len > 0) {
2320     incidence = get_incidence_space(len,p_data);
2321     for( c = 0; c < len; c++ ) {
2322     i = RelationVariable(gut,c+1);
2323     incidence[c] = SIP(GetInterfacePtr(i))->u.v.data;
2324     }
2325     rel_set_incidences(rel,len,incidence);
2326     } else {
2327     rel_set_incidences(rel,0,NULL);
2328     }
2329 johnpye 709 if(rel_extnodeinfo(rel)) {
2330 aw0a 1 cache = CheckIfCacheExists(rip->i,&nodestamp,p_data);
2331     if (cache) {
2332     rel_set_extcache(rel,cache);
2333 johnpye 709 }else{
2334 johnpye 710 CONSOLE_DEBUG("rip = %p, rip->i = %p",rip,rip->i);
2335 aw0a 1 cache = CreateCacheFromInstance(rip->i);
2336 johnpye 710 CONSOLE_DEBUG("cache = %p",cache);
2337 aw0a 1 gl_append_ptr(p_data->extrels,(POINTER)cache);
2338     rel_set_extcache(rel,cache);
2339     }
2340     }
2341     flags = 0; /* all init to FALSE */
2342     /* TURN ON APPROPRIATE ONES */
2343     if (rip->u.r.included) flags |= (REL_INCLUDED | REL_INBLOCK);
2344     if (rip->u.r.ext) flags |= REL_BLACKBOX;
2345     if (rip->u.r.active) flags |= ( REL_ACTIVE | REL_INVARIANT);
2346     if (rip->u.r.inwhen) flags |= REL_INWHEN;
2347     if ( RelationRelop(GetInstanceRelationOnly(rip->i)) == e_equal ) {
2348     flags |= REL_EQUALITY;
2349     }
2350     rel_set_flags(rel,flags);
2351     /* for c in rellist set masterrl, solverrl pointer to point to data */
2352     p_data->masterrl[v] = rel;
2353     p_data->solverrl[v] = rel;
2354     }
2355     p_data->masterrl[vlen] = NULL; /* terminator */
2356     p_data->solverrl[vlen] = NULL; /* terminator */
2357    
2358     /* cobble together external rel list */
2359     len = gl_length(p_data->extrels);
2360     p_data->erlist = (struct ExtRelCache **)
2361     ascmalloc((1+len)*sizeof(struct ExtRelCache *));
2362     if (p_data->erlist==NULL) return 1;
2363     for (c=1; c <= len; c++) {
2364     p_data->erlist[c-1] = (struct ExtRelCache *)gl_fetch(p_data->extrels,c);
2365     }
2366     p_data->erlist[len] = NULL; /* terminator */
2367 johnpye 219
2368 aw0a 1 /*
2369 johnpye 219 for c in objlist copy objdata.
2370     for c in objlist set masterrl, solverrl pointer to point to data.
2371     */
2372 johnpye 190 /*
2373 johnpye 219 process the objective relations
2374     for v in objlist copy objdata
2375     */
2376 aw0a 1 vlen = gl_length(p_data->objrels);
2377     found = 0;
2378     for (v = 0; v < vlen; v++) {
2379     rel = &(p_data->objdata[v]);
2380     rip = SIP(gl_fetch(p_data->objrels,v+1));
2381     rel = rel_create(rip->i,rel);
2382     rip->u.r.data = rel;
2383     rel_set_mindex(rel,v);
2384     rel_set_sindex(rel,v);
2385     rel_set_model(rel,rip->u.r.model-1);
2386     /* here set up the var list */
2387     gut = GetInstanceRelationOnly(rip->i);
2388     assert(gut!=NULL);
2389     len = NumberVariables(gut);
2390     if (len > 0) {
2391     incidence = get_incidence_space(len,p_data);
2392     for( c = 0; c < len; c++ ) {
2393     i = RelationVariable(gut,c+1);
2394     incidence[c] = SIP(GetInterfacePtr(i))->u.v.data;
2395     }
2396     rel_set_incidences(rel,len,incidence);
2397     } else {
2398     rel_set_incidences(rel,0,NULL);
2399     }
2400     /* black box objectives not supported. skip it */
2401     flags = 0; /* all init to FALSE */
2402     /* TURN ON APPROPRIATE ONES */
2403     if (rip->u.r.included) {
2404     flags |= (REL_INCLUDED | REL_INBLOCK | REL_ACTIVE);
2405     }
2406     if (rip->u.r.obj < 0) flags |= REL_OBJNEGATE;
2407     rel_set_flags(rel,flags);
2408     /* for c in objrellist set masterol, solverol pointer to point to data */
2409     p_data->masterol[v] = rel;
2410     p_data->solverol[v] = rel;
2411     /* set objective to first included objective on list */
2412     if (!found && (rip->u.r.included)) {
2413     p_data->obj = rel;
2414     found = 1;
2415     }
2416     }
2417     p_data->masterol[vlen] = NULL; /* terminator */
2418     p_data->solverol[vlen] = NULL; /* terminator */
2419    
2420 johnpye 190 /*
2421 johnpye 219 process the conditional relations
2422     for v in cndlist copy conddata .
2423     */
2424 aw0a 1 vlen = gl_length(p_data->cnds);
2425     for (v = 0; v < vlen; v++) {
2426     rel = &(p_data->condata[v]);
2427     rip = SIP(gl_fetch(p_data->cnds,v+1));
2428     rel = rel_create(rip->i,rel);
2429     rip->u.r.data = rel;
2430     rel_set_mindex(rel,v);
2431     rel_set_sindex(rel,v);
2432     rel_set_model(rel,rip->u.r.model-1);
2433     gut = GetInstanceRelationOnly(rip->i);
2434     assert(gut!=NULL);
2435     len = NumberVariables(gut);
2436     if (len > 0) {
2437     incidence = get_incidence_space(len,p_data);
2438     for( c = 0; c < len; c++ ) {
2439     i = RelationVariable(gut,c+1);
2440     incidence[c] = SIP(GetInterfacePtr(i))->u.v.data;