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

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