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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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