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

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