/[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 1068 - (show annotations) (download) (as text)
Mon Jan 8 04:45:47 2007 UTC (15 years, 5 months ago) by johnpye
File MIME type: text/x-csrc
File size: 99611 byte(s)
Fixed some ASC_PANIC calls in atomvalue.c
Removed some <!-- --> comments from list.h
Added flagging of 'deriv' vars in analyse.c (no new lists are added though)
Created separate doxygen module 'Analyse' (only affect C comments)
Fixed return codes in slv9a.c, as well as some FPRINTFs.
Cleaned up some documentation in slv_client.h.
Removed var_diff, var_set_diff flag stuff.
Added docstring for Integrator_getEngines in python wrapper.

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

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