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

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