Parent Directory
|
Revision Log
Added my so-called 'quick fix' to external relation processing. Still need to pursue corruption of efunc->etype pointer, for some reason.
1 | johnpye | 669 | /* 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 | johnpye | 219 | Problem Analysis Routines |
22 | johnpye | 220 | |
23 | johnpye | 669 | @NOTE 'ip' signifies 'interface pointer' @ENDNOTE |
24 | aw0a | 1 | |
25 | johnpye | 669 | 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 | johnpye | 219 | |
39 | johnpye | 669 | 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 | johnpye | 219 | |
48 | johnpye | 669 | @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 | johnpye | 219 | |
57 | johnpye | 669 | 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 | johnpye | 219 | |
65 | johnpye | 220 | @see analyze.h |
66 | johnpye | 669 | *//* |
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 | johnpye | 219 | */ |
72 | |||
73 | aw0a | 1 | #include <stdarg.h> |
74 | johnpye | 399 | #include <utilities/ascConfig.h> |
75 | #include <utilities/ascPanic.h> | ||
76 | #include <utilities/ascMalloc.h> | ||
77 | #include <general/list.h> | ||
78 | #include <general/dstring.h> | ||
79 | #include <compiler/compiler.h> | ||
80 | #include <compiler/symtab.h> | ||
81 | #include <compiler/instance_enum.h> | ||
82 | #include <compiler/fractions.h> | ||
83 | #include <compiler/dimen.h> | ||
84 | #include <compiler/atomvalue.h> | ||
85 | #include <compiler/parentchild.h> | ||
86 | #include <compiler/visitinst.h> | ||
87 | johnpye | 669 | #include <compiler/expr_types.h> |
88 | johnpye | 399 | #include <compiler/exprs.h> |
89 | #include <compiler/sets.h> | ||
90 | #include <compiler/mathinst.h> | ||
91 | #include <compiler/instquery.h> | ||
92 | #include <compiler/instance_io.h> | ||
93 | #include <compiler/relation_type.h> | ||
94 | #include <compiler/find.h> | ||
95 | #include <compiler/extfunc.h> | ||
96 | #include <compiler/extcall.h> | ||
97 | #include <compiler/relation.h> | ||
98 | #include <compiler/functype.h> | ||
99 | #include <compiler/safe.h> | ||
100 | #include <compiler/relation_util.h> | ||
101 | #include <compiler/logical_relation.h> | ||
102 | #include <compiler/logrelation.h> | ||
103 | #include <compiler/logrel_util.h> | ||
104 | #include <compiler/case.h> | ||
105 | #include <compiler/when_util.h> | ||
106 | #include "mtx.h" | ||
107 | #include "slv_types.h" | ||
108 | #include "var.h" | ||
109 | aw0a | 1 | #define _SLV_SERVER_C_SEEN_ |
110 | johnpye | 399 | #include "rel.h" |
111 | #include "logrel.h" | ||
112 | #include "discrete.h" | ||
113 | #include "conditional.h" | ||
114 | #include "bnd.h" | ||
115 | #include "slv_server.h" | ||
116 | #include "slv_common.h" | ||
117 | #include "linsol.h" | ||
118 | #include "linsolqr.h" | ||
119 | #include "slv_client.h" | ||
120 | #include "cond_config.h" | ||
121 | #include "analyze.h" | ||
122 | #include <general/mathmacros.h> | ||
123 | aw0a | 1 | |
124 | /* stuff to get rid of */ | ||
125 | #ifndef MAX_VAR_IN_LIST | ||
126 | #define MAX_VAR_IN_LIST 20 | ||
127 | #endif /* MAX_VAR_IN_LIST */ | ||
128 | #define DEBUG_ANALYSIS FALSE | ||
129 | |||
130 | johnpye | 669 | /*------------------------------------------------------------------------------ |
131 | GLOBAL VARS | ||
132 | */ | ||
133 | |||
134 | static symchar *g_strings[3]; | ||
135 | |||
136 | aw0a | 1 | /* symbol table entries we need */ |
137 | #define INCLUDED_A g_strings[0] | ||
138 | #define FIXED_A g_strings[1] | ||
139 | #define BASIS_A g_strings[2] | ||
140 | |||
141 | johnpye | 190 | /* |
142 | johnpye | 219 | Global variable. Set to true by classify if need be |
143 | johnpye | 222 | */ |
144 | aw0a | 1 | static int g_bad_rel_in_list; |
145 | |||
146 | |||
147 | /* used to give an integer value to each symbol used in a when */ | ||
148 | struct gl_list_t *g_symbol_values_list = NULL; | ||
149 | |||
150 | johnpye | 669 | |
151 | /*----------------------------------------------------------------------------- | ||
152 | FORWARD DECLARATIONS | ||
153 | */ | ||
154 | static void ProcessModelsInWhens(struct Instance *, struct gl_list_t *, | ||
155 | struct gl_list_t *, struct gl_list_t *); | ||
156 | |||
157 | /*----------------------------------------------------------------------------- | ||
158 | DATA STRUCTURES FOR USE DURING PROBLEM ANALYSIS | ||
159 | */ | ||
160 | |||
161 | aw0a | 1 | struct varip { |
162 | struct var_variable *data; /* ptr to destination of data */ | ||
163 | int index; /* master gl index */ | ||
164 | johnpye | 219 | int incident; /* set 0 in classify_instance, 1 make_master_lists */ |
165 | aw0a | 1 | int in_block; /* set 0 in classify_instance */ |
166 | int fixed; /* set in classify_instance */ | ||
167 | int solvervar; /* set in classify_instance */ | ||
168 | johnpye | 219 | int active; /* is this var a part of my problem */ |
169 | int basis; /* set in classify_instance */ | ||
170 | aw0a | 1 | }; |
171 | |||
172 | |||
173 | struct disvarip { | ||
174 | struct dis_discrete *data; /* ptr to destination of data */ | ||
175 | johnpye | 219 | int index; /* master gl index */ |
176 | int fixed; /* set in classify_instance */ | ||
177 | aw0a | 1 | int isconst; /* is this dis var constant ? */ |
178 | int distype; /* 0 boolean, 1 int, -1 symbol */ | ||
179 | int value; /* integer value of the variable */ | ||
180 | int incident; /* is it incident in a logrel */ | ||
181 | int inwhen; /* is it in a when var list */ | ||
182 | int booleanvar; /* Not sure if I need it */ | ||
183 | int active; /* is this disvar a part of my problem */ | ||
184 | }; | ||
185 | |||
186 | |||
187 | struct relip { | ||
188 | struct rel_relation *data; /* ptr to destination of data */ | ||
189 | long model; /* relation is in this model in model gllist */ | ||
190 | johnpye | 219 | /* set in CollectRelsAndWhens. = 1.. nmodels */ |
191 | /* rel_relation models = u.r.model-1 */ | ||
192 | aw0a | 1 | int index; /* master gl list index */ |
193 | johnpye | 219 | int obj; /* is it an objective relation. set in classify_instance */ |
194 | int ext; /* is it e_blackbox. set in classify_instance */ | ||
195 | int included; /* set in classify_instance */ | ||
196 | int cond; /* is it a conditional relation. set in classify_instance */ | ||
197 | int inwhen; /* is it in a when */ | ||
198 | int active; /* is this rel a part of my problem */ | ||
199 | aw0a | 1 | }; |
200 | |||
201 | struct logrelip { | ||
202 | struct logrel_relation *data; /* ptr to destination of data */ | ||
203 | johnpye | 219 | long model; /* logrelation is in this model in model gllist */ |
204 | int index; /* master gllist index */ | ||
205 | int included; /* set in classify_instance */ | ||
206 | int cond; /* is it a conditional logrelation. */ | ||
207 | aw0a | 1 | int inwhen; /* is it in a when */ |
208 | int active; /* is this logrel a part of my problem */ | ||
209 | }; | ||
210 | |||
211 | struct whenip{ | ||
212 | johnpye | 219 | struct w_when *data; /* ptr to destination of data */ |
213 | long model; /* when is in this model in model gllist */ | ||
214 | int index; /* master gllist index */ | ||
215 | int inwhen; /* is it in a when */ | ||
216 | aw0a | 1 | }; |
217 | |||
218 | struct modip { | ||
219 | johnpye | 219 | int index; /* set in make master lists. 1..nmodels */ |
220 | int inwhen; /* is it in a when */ | ||
221 | aw0a | 1 | }; |
222 | |||
223 | /* we will decorate the ascend instance tree with these in the interface | ||
224 | johnpye | 219 | pointers, but ONLY for the system build process and not persistently. |
225 | DO NOT EVER UNDER ANY CIRCUMSTANCES EXPORT THIS DATA STRUCTURE. | ||
226 | */ | ||
227 | aw0a | 1 | struct solver_ipdata { |
228 | struct Instance *i; /* the kind of instance is the enum for union */ | ||
229 | union { | ||
230 | struct modip m; | ||
231 | struct varip v; | ||
232 | struct disvarip dv; | ||
233 | struct relip r; | ||
234 | struct logrelip lr; | ||
235 | struct whenip w; | ||
236 | } u; | ||
237 | }; | ||
238 | |||
239 | /* a handy cast for fetching things off gllists */ | ||
240 | #define SIP(x) ((struct solver_ipdata *)(x)) | ||
241 | |||
242 | johnpye | 190 | /* |
243 | johnpye | 219 | a bridge buffer used so much we aren't going to free it, just reuse it |
244 | */ | ||
245 | aw0a | 1 | static struct reuse_t { |
246 | size_t ipcap; /* number of ips allocated in ipbuf */ | ||
247 | size_t ipused; /* number of ips in use */ | ||
248 | struct solver_ipdata *ipbuf; | ||
249 | } g_reuse = {0,0,NULL}; | ||
250 | |||
251 | johnpye | 222 | /** |
252 | a data structure for bridge-building only. hell of a scaffolding. | ||
253 | johnpye | 219 | all fields should be empty if construction is not in progress. |
254 | In particular, do no operations that can throw an exception | ||
255 | while manipulating a problem_t, as it is way too big to let leak. | ||
256 | johnpye | 669 | |
257 | @TODO is this comment in the right place? | ||
258 | we are making the ANSI assumption that this will be init to 0/NULL | ||
259 | |||
260 | @TODO what about this one?: | ||
261 | container for globals during assembly. | ||
262 | At present, the mastervl and solvervl are of the same length. This | ||
263 | is purely coincidental and the long run intent is that there is one | ||
264 | master list and that a problem coordinator would set up the | ||
265 | solver var/rel lists blockwise as we go along. We may want to put | ||
266 | block information in the rel/var structures. | ||
267 | johnpye | 219 | */ |
268 | aw0a | 1 | struct problem_t { |
269 | johnpye | 222 | |
270 | /* the following are established by CountStuffInTree */ | ||
271 | johnpye | 219 | long nv; /* number of solvervar/solveratom */ |
272 | long np; /* number of real ATOM instance parameters */ | ||
273 | long nu; /* number of real ATOM instance uninteresting */ | ||
274 | aw0a | 1 | long ndv; /* number of discrete variables */ |
275 | long nud; /* number of uninteresting discretes */ | ||
276 | johnpye | 219 | long nc; /* number of conditional relations */ |
277 | long ncl; /* number of conditional logrelations */ | ||
278 | long nr; /* number of algebraic relations */ | ||
279 | long no; /* number of objective rels */ | ||
280 | long nl; /* number of logical rels */ | ||
281 | aw0a | 1 | long nw; /* number of whens */ |
282 | johnpye | 219 | long ne; /* number of external rels subset overestimate*/ |
283 | long nm; /* number of models */ | ||
284 | johnpye | 222 | |
285 | /* | ||
286 | The following gllists contain pointers to interface ptrs as | ||
287 | locally defined. | ||
288 | The lists will be in order found by a visit instance tree. | ||
289 | */ | ||
290 | aw0a | 1 | struct gl_list_t *vars; /* solvervar/solveratom. varips */ |
291 | struct gl_list_t *pars; /* real ATOM instance parameters */ | ||
292 | struct gl_list_t *unas; /* real ATOM instance of no 'apparent' use */ | ||
293 | struct gl_list_t *models; /* models in tree. modips */ | ||
294 | johnpye | 222 | |
295 | /* | ||
296 | The following gllists contain pointers to interface ptrs as | ||
297 | locally defined. | ||
298 | The lists will be in order found by running over the models list. | ||
299 | */ | ||
300 | aw0a | 1 | struct gl_list_t *dvars; /* discrete variables */ |
301 | struct gl_list_t *dunas; /* discrete variables of no use */ | ||
302 | struct gl_list_t *whens; /* whens */ | ||
303 | struct gl_list_t *cnds; /* conditional relations */ | ||
304 | struct gl_list_t *logcnds; /* conditional logrelations */ | ||
305 | struct gl_list_t *rels; /* ascend relations. relips */ | ||
306 | struct gl_list_t *objrels; /* objective rels. relips */ | ||
307 | struct gl_list_t *logrels; /* logical rels */ | ||
308 | johnpye | 222 | |
309 | /* bridge ip data */ | ||
310 | aw0a | 1 | struct gl_list_t *oldips; /* buffer of oldip crap we're protecting */ |
311 | johnpye | 222 | |
312 | /* misc stuff */ | ||
313 | aw0a | 1 | struct gl_list_t *tmplist; /* sort space */ |
314 | johnpye | 222 | |
315 | /* stuff that will end up in the slv_system_t */ | ||
316 | aw0a | 1 | struct rel_relation *obj; /* DEFAULT objective relation, if any */ |
317 | struct Instance *root; /* instance we construct system from */ | ||
318 | struct gl_list_t *extrels; /* black box stub list */ | ||
319 | johnpye | 222 | |
320 | /* stuff that should move elsewhere, but end up in slv_system_t */ | ||
321 | aw0a | 1 | mtx_region_t *blocks; /* array of partitions in reordered matrix */ |
322 | int32 nblocks; /* size of array of partitions */ | ||
323 | johnpye | 219 | int nnz; /* free nonzeros in processed jacobian */ |
324 | aw0a | 1 | int nnztot; /* total nonzeros in processed relations */ |
325 | int nnzobj; /* total nonzeros in objective gradients */ | ||
326 | int nnzcond; /* total nonzeros in conditional relations */ | ||
327 | int relincsize; /* total nonzeros in gradients */ | ||
328 | int relincinuse; /* incidence given to relations so far */ | ||
329 | int varincsize; /* total nonzeros in gradients (redundant) */ | ||
330 | int varincinuse; /* incidence given to variables so far */ | ||
331 | johnpye | 219 | int ncol; /* free and incident vars */ |
332 | int nrow; /* included relations */ | ||
333 | aw0a | 1 | /* conditional stuff */ |
334 | int32 need_consistency; /* Conistency analysis is required ? */ | ||
335 | johnpye | 222 | |
336 | /* logical relation stuff */ | ||
337 | johnpye | 219 | int lognnz; /* Summ of free boolean vars in inc logrels */ |
338 | int lognrow; /* included logrelations */ | ||
339 | int logncol; /* free and incident boolean vars */ | ||
340 | int lrelinc; /* incident boolean vars */ | ||
341 | int lrelincsize; /* Total summ of incidences (boolean vars) | ||
342 | in logrels*/ | ||
343 | aw0a | 1 | int lrelincinuse; /* incidence given to log relations so far */ |
344 | johnpye | 222 | |
345 | /* data to go to slv_system_t */ | ||
346 | aw0a | 1 | struct rel_relation *reldata; /* rel data space, mass allocated */ |
347 | struct rel_relation *objdata; /* objrel data space, mass allocated */ | ||
348 | struct rel_relation *condata; /* cond rel data space, mass allocated*/ | ||
349 | struct logrel_relation *lrdata; /* logrel data space, mass allocated */ | ||
350 | struct logrel_relation *logcondata; /* cond logrel data space, allocated */ | ||
351 | struct var_variable *vardata; /* svar data space, mass allocated */ | ||
352 | struct var_variable *pardata; /* par data space, mass allocated */ | ||
353 | struct var_variable *undata; /* data space, mass allocated */ | ||
354 | struct dis_discrete *disdata; /* dis var data space, mass allocated */ | ||
355 | struct dis_discrete *undisdata; /* data space, mass allocated */ | ||
356 | struct w_when *whendata; /* when data space, mass allocated */ | ||
357 | struct bnd_boundary *bnddata; /* boundaries data space, allocated */ | ||
358 | struct var_variable **mastervl; /* master null-terminated list */ | ||
359 | struct var_variable **solvervl; /* solvers null-terminated list */ | ||
360 | struct dis_discrete **masterdl; /* master null-terminated list */ | ||
361 | struct dis_discrete **solverdl; /* solvers null-terminated list */ | ||
362 | struct rel_relation **masterrl; /* master null-terminated list */ | ||
363 | struct rel_relation **solverrl; /* solvers null-terminated list */ | ||
364 | struct rel_relation **mastercl; /* master null-terminated list */ | ||
365 | struct rel_relation **solvercl; /* solvers null-terminated list */ | ||
366 | struct rel_relation **masterol; /* master null-terminated list */ | ||
367 | struct rel_relation **solverol; /* solvers null-terminated list */ | ||
368 | struct logrel_relation **masterll; /* master null-terminated list */ | ||
369 | struct logrel_relation **solverll; /* solvers null-terminated list */ | ||
370 | struct logrel_relation **mastercll; /* master null-terminated list */ | ||
371 | struct logrel_relation **solvercll; /* solvers null-terminated list */ | ||
372 | struct w_when **masterwl; /* master null-terminated list */ | ||
373 | struct w_when **solverwl; /* solvers null-terminated list */ | ||
374 | struct bnd_boundary **masterbl; /* master null-terminated list */ | ||
375 | struct bnd_boundary **solverbl; /* solvers null-terminated list */ | ||
376 | struct var_variable **masterpl; /* master null-terminated list */ | ||
377 | struct var_variable **solverpl; /* solvers null-terminated list */ | ||
378 | struct var_variable **masterul; /* master null-terminated list */ | ||
379 | struct var_variable **solverul; /* solvers null-terminated list */ | ||
380 | struct dis_discrete **masterdul; /* master null-terminated list */ | ||
381 | struct dis_discrete **solverdul; /* solvers null-terminated list */ | ||
382 | struct var_variable **relincidence; /* rel_relation incidence source */ | ||
383 | struct rel_relation **varincidence; /* var_variable incidence source */ | ||
384 | struct dis_discrete **logrelinciden; /* logrel_relation incidence source */ | ||
385 | |||
386 | struct ExtRelCache **erlist; /* external rel cache null terminated list */ | ||
387 | }; | ||
388 | johnpye | 222 | |
389 | johnpye | 669 | /*------------------------------------------------------------------------------ |
390 | SOME STUFF WITH INTERFACE POINTERS | ||
391 | johnpye | 219 | */ |
392 | aw0a | 1 | /* return a pointer to the oncesizefitsall ips we're using. |
393 | johnpye | 219 | always returns nonnull because if we run out we exit |
394 | */ | ||
395 | aw0a | 1 | static struct solver_ipdata *analyze_getip(void) |
396 | { | ||
397 | if (g_reuse.ipbuf!=NULL && g_reuse.ipused < g_reuse.ipcap) { | ||
398 | return &(g_reuse.ipbuf[g_reuse.ipused++]); | ||
399 | } else { | ||
400 | Asc_Panic(2, "ananlyze_getip", | ||
401 | "Too many ips requested by analyze_getip\n"); | ||
402 | exit(2);/* NOT REACHED. Needed to keep gcc from whining */ | ||
403 | } | ||
404 | } | ||
405 | |||
406 | johnpye | 190 | /* |
407 | johnpye | 219 | reallocates to the requested size (newcap) the ipbuf. |
408 | if newcap = 0, frees ipbuf. | ||
409 | if insufficient memory returns 1. | ||
410 | if newcap > 0 and reset mem != 0, initializes ipbuf to 0s. | ||
411 | Resets ipused to 0. | ||
412 | */ | ||
413 | aw0a | 1 | static |
414 | int resize_ipbuf(size_t newcap, int resetmem) | ||
415 | { | ||
416 | struct solver_ipdata *tmp; | ||
417 | if (newcap ==0) { | ||
418 | if (g_reuse.ipbuf != NULL) { | ||
419 | ascfree(g_reuse.ipbuf); | ||
420 | } | ||
421 | g_reuse.ipcap = g_reuse.ipused = 0; | ||
422 | g_reuse.ipbuf = NULL; | ||
423 | return 0; | ||
424 | } | ||
425 | if (newcap > g_reuse.ipcap) { | ||
426 | if ( g_reuse.ipcap >0 ) { | ||
427 | tmp = (struct solver_ipdata *) | ||
428 | ascrealloc(g_reuse.ipbuf,newcap*sizeof(struct solver_ipdata)); | ||
429 | if (tmp == NULL) { | ||
430 | FPRINTF(ASCERR,"ERROR: (resize_ipbuf) Insufficient memory.\n"); | ||
431 | return 1; | ||
432 | } | ||
433 | g_reuse.ipbuf = tmp; | ||
434 | g_reuse.ipcap = newcap; | ||
435 | } else { | ||
436 | tmp = (struct solver_ipdata *) | ||
437 | ascmalloc(newcap*sizeof(struct solver_ipdata)); | ||
438 | if (tmp == NULL) { | ||
439 | FPRINTF(ASCERR, | ||
440 | "ERROR:(resize_ipbuf 1st call) Insufficient memory.\n"); | ||
441 | return 1; | ||
442 | } | ||
443 | g_reuse.ipbuf = tmp; | ||
444 | g_reuse.ipcap = newcap; | ||
445 | } | ||
446 | } | ||
447 | if (resetmem) { | ||
448 | memset((char *)g_reuse.ipbuf,0, | ||
449 | g_reuse.ipcap*sizeof(struct solver_ipdata)); | ||
450 | } | ||
451 | g_reuse.ipused = 0; | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | johnpye | 669 | /*------------------------------------------------------------------------------ |
456 | SOME STUFF TO DO WITH INCIDENCE SPACE | ||
457 | */ | ||
458 | aw0a | 1 | |
459 | johnpye | 190 | /* |
460 | johnpye | 219 | checks size of request and returns a pointer to the next available |
461 | chunk of incidence space. if too much requested or 0 requested returns | ||
462 | NULL. p_data->relincidence must have been allocated for this to work. | ||
463 | */ | ||
464 | aw0a | 1 | static |
465 | struct var_variable **get_incidence_space(int len, struct problem_t *p_data) | ||
466 | { | ||
467 | struct var_variable **tmp; | ||
468 | if (p_data->relincidence == NULL) { | ||
469 | Asc_Panic(2,NULL,"get_incidence_space called prematurely. bye.\n"); | ||
470 | } | ||
471 | if (len <1) return NULL; | ||
472 | if (p_data->relincinuse + len > p_data->relincsize) { | ||
473 | FPRINTF(ASCERR,"get_incidence_space called excessively.\n"); | ||
474 | return NULL; | ||
475 | } | ||
476 | tmp = &(p_data->relincidence[p_data->relincinuse]); | ||
477 | p_data->relincinuse += len; | ||
478 | return tmp; | ||
479 | } | ||
480 | |||
481 | johnpye | 190 | /* |
482 | johnpye | 219 | checks size of request and returns a pointer to the next available |
483 | chunk of incidence space. if too much requested or 0 requested returns | ||
484 | NULL. p_data->varincidence must have been allocated for this to work. | ||
485 | */ | ||
486 | aw0a | 1 | static |
487 | struct rel_relation **get_var_incidence_space(int len, | ||
488 | struct problem_t *p_data) | ||
489 | { | ||
490 | struct rel_relation **tmp; | ||
491 | if (p_data->varincidence == NULL) { | ||
492 | Asc_Panic(2,NULL,"get_var_incidence_space called prematurely. bye.\n"); | ||
493 | } | ||
494 | if (len <1) return NULL; | ||
495 | if (p_data->varincinuse + len > p_data->varincsize) { | ||
496 | FPRINTF(ASCERR,"get_var_incidence_space called excessively.\n"); | ||
497 | return NULL; | ||
498 | } | ||
499 | tmp = &(p_data->varincidence[p_data->varincinuse]); | ||
500 | p_data->varincinuse += len; | ||
501 | return tmp; | ||
502 | } | ||
503 | |||
504 | |||
505 | /* | ||
506 | johnpye | 219 | p_data->logrelinciden must have been allocated for this to work. |
507 | */ | ||
508 | aw0a | 1 | static |
509 | struct dis_discrete **get_logincidence_space(int len, | ||
510 | struct problem_t *p_data) | ||
511 | { | ||
512 | struct dis_discrete **tmp; | ||
513 | if (p_data->logrelinciden == NULL) { | ||
514 | Asc_Panic(2,NULL,"get_logincidence_space called prematurely. bye.\n"); | ||
515 | } | ||
516 | if (len <1) return NULL; | ||
517 | if (p_data->lrelincinuse + len > p_data->lrelincsize) { | ||
518 | FPRINTF(ASCERR,"get_logincidence_space called excessively.\n"); | ||
519 | return NULL; | ||
520 | } | ||
521 | tmp = &(p_data->logrelinciden[p_data->lrelincinuse]); | ||
522 | p_data->lrelincinuse += len; | ||
523 | return tmp; | ||
524 | } | ||
525 | |||
526 | johnpye | 669 | /*------------------------------------------------------------------------------ |
527 | SOME OTHER STUFF | ||
528 | */ | ||
529 | aw0a | 1 | |
530 | /* | ||
531 | johnpye | 219 | InitTreeCounts(i); This resets the pointers and counters in |
532 | p_data to null. p_data is supposed to be a temporary structure | ||
533 | so the memory management of the pointers in p_data is the job | ||
534 | of the caller. | ||
535 | p_data->root is set to i. | ||
536 | */ | ||
537 | aw0a | 1 | static void InitTreeCounts(struct Instance *i,struct problem_t *p_data) |
538 | { | ||
539 | memset((char *)p_data,0,sizeof(struct problem_t)); | ||
540 | p_data->root = i; | ||
541 | } | ||
542 | |||
543 | #define AVG_PARENTS 2 | ||
544 | #define AVG_CHILDREN 4 | ||
545 | #define AVG_RELATIONS 15 | ||
546 | #define AVG_GROWTH 2 | ||
547 | #define PART_THRESHOLD 1000 | ||
548 | |||
549 | /* | ||
550 | johnpye | 219 | The following function should be moved out to the compiler |
551 | under the guise of a supported attribute. | ||
552 | */ | ||
553 | aw0a | 1 | static int BooleanChildValue(struct Instance *i,symchar *sc) |
554 | { | ||
555 | johnpye | 62 | /* FPRINTF(ASCERR,"GETTING BOOLEAN CHILD VALUE OF %s\n",SCP(sc)); */ |
556 | aw0a | 1 | if (i == NULL || sc == NULL || (i=ChildByChar(i,sc)) == NULL) { |
557 | return 0; | ||
558 | } else { | ||
559 | return ( GetBooleanAtomValue(i) ); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | static void CollectArrayRelsAndWhens(struct Instance *i, long modindex, | ||
564 | struct problem_t *p_data) | ||
565 | { | ||
566 | struct Instance *child; | ||
567 | struct solver_ipdata *rip; | ||
568 | unsigned long nch,c; | ||
569 | |||
570 | if (i==NULL) return; | ||
571 | nch = NumberChildren(i); | ||
572 | for (c=1;c<=nch;c++) { | ||
573 | child = InstanceChild(i,c); | ||
574 | if (child==NULL) continue; | ||
575 | switch (InstanceKind(child)) { | ||
576 | case REL_INST: | ||
577 | rip = SIP(GetInterfacePtr(child)); | ||
578 | if (rip->u.r.model == 0) { | ||
579 | rip->u.r.model = modindex; | ||
580 | } else { | ||
581 | /* ah hah! found an array with two distinct MODEL parents! skip it */ | ||
582 | break; | ||
583 | } | ||
584 | if (rip->u.r.cond) { | ||
585 | gl_append_ptr(p_data->cnds,(VOIDPTR)rip); | ||
586 | } | ||
587 | else { | ||
588 | if (rip->u.r.obj) { | ||
589 | gl_append_ptr(p_data->objrels,(VOIDPTR)rip); | ||
590 | } else { | ||
591 | gl_append_ptr(p_data->rels,(VOIDPTR)rip); | ||
592 | } | ||
593 | } | ||
594 | break; | ||
595 | case LREL_INST: | ||
596 | rip = SIP(GetInterfacePtr(child)); | ||
597 | if (rip->u.lr.model == 0) { | ||
598 | rip->u.lr.model = modindex; | ||
599 | } else { | ||
600 | break; | ||
601 | } | ||
602 | if (rip->u.lr.cond) { | ||
603 | gl_append_ptr(p_data->logcnds,(VOIDPTR)rip); | ||
604 | } | ||
605 | else { | ||
606 | gl_append_ptr(p_data->logrels,(VOIDPTR)rip); | ||
607 | } | ||
608 | break; | ||
609 | case WHEN_INST: | ||
610 | rip = SIP(GetInterfacePtr(child)); | ||
611 | if (rip->u.w.model == 0) { | ||
612 | rip->u.w.model = modindex; | ||
613 | } else { | ||
614 | break; | ||
615 | } | ||
616 | gl_append_ptr(p_data->whens,(VOIDPTR)rip); | ||
617 | break; | ||
618 | case ARRAY_ENUM_INST: | ||
619 | case ARRAY_INT_INST: | ||
620 | johnpye | 190 | if (ArrayIsRelation(child) || |
621 | aw0a | 1 | ArrayIsLogRel(child) || |
622 | johnpye | 669 | ArrayIsWhen(child) |
623 | ){ | ||
624 | CollectArrayRelsAndWhens(child,modindex,p_data); | ||
625 | aw0a | 1 | } |
626 | break; | ||
627 | default: | ||
628 | break; | ||
629 | } | ||
630 | } | ||
631 | } | ||
632 | |||
633 | johnpye | 222 | |
634 | aw0a | 1 | /* |
635 | johnpye | 219 | Collect all the logrels/relations at the local scope of the MODEL |
636 | associated with ip->i. Local scope includes arrays of logrels/relations, | ||
637 | mainly because these arrays don't have interface pointers so we | ||
638 | can't treat them separately. | ||
639 | */ | ||
640 | aw0a | 1 | static void CollectRelsAndWhens(struct solver_ipdata *ip, |
641 | long modindex, | ||
642 | struct problem_t *p_data) | ||
643 | { | ||
644 | struct Instance *child; | ||
645 | struct solver_ipdata *rip; | ||
646 | unsigned long nch,c; | ||
647 | |||
648 | if (ip->i==NULL) return; | ||
649 | nch = NumberChildren(ip->i); | ||
650 | for (c=1;c<=nch;c++) { | ||
651 | child = InstanceChild(ip->i,c); | ||
652 | if (child==NULL) continue; | ||
653 | switch (InstanceKind(child)) { | ||
654 | case REL_INST: | ||
655 | rip = SIP(GetInterfacePtr(child)); | ||
656 | rip->u.r.model = modindex; | ||
657 | if (rip->u.r.cond) { | ||
658 | gl_append_ptr(p_data->cnds,(VOIDPTR)rip); | ||
659 | } | ||
660 | else { | ||
661 | if (rip->u.r.obj) { | ||
662 | gl_append_ptr(p_data->objrels,(VOIDPTR)rip); | ||
663 | } else { | ||
664 | gl_append_ptr(p_data->rels,(VOIDPTR)rip); | ||
665 | } | ||
666 | } | ||
667 | break; | ||
668 | case LREL_INST: | ||
669 | rip = SIP(GetInterfacePtr(child)); | ||
670 | rip->u.lr.model = modindex; | ||
671 | if (rip->u.lr.cond) { | ||
672 | gl_append_ptr(p_data->logcnds,(VOIDPTR)rip); | ||
673 | } | ||
674 | else { | ||
675 | gl_append_ptr(p_data->logrels,(VOIDPTR)rip); | ||
676 | } | ||
677 | break; | ||
678 | case WHEN_INST: | ||
679 | rip = SIP(GetInterfacePtr(child)); | ||
680 | rip->u.w.model = modindex; | ||
681 | gl_append_ptr(p_data->whens,(VOIDPTR)rip); | ||
682 | break; | ||
683 | case ARRAY_ENUM_INST: | ||
684 | case ARRAY_INT_INST: | ||
685 | johnpye | 190 | if (ArrayIsRelation(child) || |
686 | ArrayIsLogRel(child)|| | ||
687 | johnpye | 669 | ArrayIsWhen(child) |
688 | ){ | ||
689 | CollectArrayRelsAndWhens(child,modindex,p_data); | ||
690 | aw0a | 1 | } |
691 | break; | ||
692 | default: | ||
693 | break; | ||
694 | } | ||
695 | } | ||
696 | } | ||
697 | |||
698 | /* | ||
699 | johnpye | 219 | Checks the problem extrels list to see whether a cache has been |
700 | created for the given relation in the problem_t bridge. | ||
701 | If not will return NULL, else | ||
702 | will return the pointer to the cache. The nodestamp corresponding | ||
703 | to this relation is returned regardless. | ||
704 | */ | ||
705 | aw0a | 1 | static struct ExtRelCache |
706 | *CheckIfCacheExists( struct Instance *relinst, int *nodestamp, | ||
707 | struct problem_t *p_data) | ||
708 | { | ||
709 | struct ExtCallNode *ext; | ||
710 | struct ExtRelCache *cache; | ||
711 | CONST struct relation *gut; | ||
712 | enum Expr_enum type; | ||
713 | unsigned long len,c; | ||
714 | |||
715 | gut = GetInstanceRelation(relinst,&type); | ||
716 | assert(type==e_blackbox); | ||
717 | ext = BlackBoxExtCall(gut); | ||
718 | *nodestamp = ExternalCallNodeStamp(ext); | ||
719 | len = gl_length(p_data->extrels); | ||
720 | |||
721 | for (c=1;c<=len;c++) { | ||
722 | cache = (struct ExtRelCache *)gl_fetch(p_data->extrels,c); | ||
723 | if (cache->nodestamp == *nodestamp) { | ||
724 | return cache; | ||
725 | } | ||
726 | } | ||
727 | return NULL; | ||
728 | } | ||
729 | johnpye | 219 | |
730 | aw0a | 1 | /* |
731 | johnpye | 219 | Count the instance into the required bin. |
732 | johnpye | 669 | |
733 | @NOTE Call only with good relation instances. | ||
734 | johnpye | 219 | */ |
735 | aw0a | 1 | static void analyze_CountRelation(struct Instance *inst, |
736 | struct problem_t *p_data) | ||
737 | { | ||
738 | switch( RelationRelop(GetInstanceRelationOnly(inst)) ) { | ||
739 | case e_maximize: | ||
740 | case e_minimize: | ||
741 | p_data->no++; | ||
742 | break; | ||
743 | case e_less: case e_lesseq: | ||
744 | case e_greater: case e_greatereq: | ||
745 | case e_equal: case e_notequal: | ||
746 | if ( RelationIsCond(GetInstanceRelationOnly(inst)) ) { | ||
747 | p_data->nc++; | ||
748 | } | ||
749 | else { | ||
750 | p_data->nr++; | ||
751 | if ( GetInstanceRelationType(inst)==e_blackbox ) { | ||
752 | p_data->ne++; | ||
753 | } | ||
754 | } | ||
755 | break; | ||
756 | default: | ||
757 | FPRINTF(ASCERR,"ERROR: (analyze) analyze_CountRelation\n"); | ||
758 | FPRINTF(ASCERR," Unknown relation type.\n"); | ||
759 | } | ||
760 | } | ||
761 | |||
762 | johnpye | 219 | |
763 | aw0a | 1 | /* |
764 | johnpye | 669 | Obtain an integer value from a symbol value |
765 | Used for a WHEN statement. Each symbol value is storaged in a symbol list. | ||
766 | johnpye | 219 | It checks if the symval is already in the solver symbol list, |
767 | if it is, returns the integer corresponding to the position of symval | ||
768 | if it is not, appends the symval to the list and then returns the int | ||
769 | johnpye | 669 | |
770 | @NOTE This is terrible inefficient as the number of symbols grows. | ||
771 | johnpye | 219 | I am keeping it by now, are they going to be so many symbols in |
772 | whens anyway ? | ||
773 | */ | ||
774 | aw0a | 1 | |
775 | int GetIntFromSymbol(CONST char *symval, | ||
776 | struct gl_list_t *symbol_list) | ||
777 | { | ||
778 | struct SymbolValues *entry,*dummy; | ||
779 | unsigned long length; | ||
780 | int len,c,value; | ||
781 | int symbol_list_count; | ||
782 | |||
783 | if (symbol_list != NULL) { | ||
784 | len = gl_length(symbol_list); | ||
785 | for (c=1; c<= len; c++) { | ||
786 | dummy = (struct SymbolValues *)(gl_fetch(symbol_list,c)); | ||
787 | if (!strcmp(dummy->name,symval)) { | ||
788 | return (dummy->value); | ||
789 | } | ||
790 | } | ||
791 | symbol_list_count = len; | ||
792 | } else { | ||
793 | symbol_list_count = 0; | ||
794 | symbol_list = gl_create(2L); | ||
795 | } | ||
796 | length = (unsigned long)strlen(symval); | ||
797 | length++; | ||
798 | symbol_list_count++; | ||
799 | entry = (struct SymbolValues *)ascmalloc(sizeof(struct SymbolValues)); | ||
800 | johnpye | 669 | entry->name = ASC_NEW_ARRAY(char,length); |
801 | aw0a | 1 | strcpy(entry->name,symval); |
802 | entry->value = symbol_list_count; | ||
803 | value = entry->value; | ||
804 | gl_append_ptr(symbol_list,entry); | ||
805 | return value; | ||
806 | } | ||
807 | |||
808 | void DestroySymbolValuesList(struct gl_list_t *symbol_list) | ||
809 | { | ||
810 | struct SymbolValues *entry; | ||
811 | int len,c; | ||
812 | if (symbol_list != NULL) { | ||
813 | len = gl_length(symbol_list); | ||
814 | for (c=1; c<= len; c++) { | ||
815 | entry = (struct SymbolValues *)(gl_fetch(symbol_list,c)); | ||
816 | ascfree((char *)entry->name); /* Do I need this ? */ | ||
817 | ascfree((char *)entry); | ||
818 | } | ||
819 | gl_destroy(symbol_list); | ||
820 | symbol_list = NULL; | ||
821 | } | ||
822 | } | ||
823 | |||
824 | johnpye | 669 | /*------------------------------------------------------------------------------ |
825 | CLASSIFICATION OF INSTANCES, CREATING INTERFACE POINTERS | ||
826 | */ | ||
827 | aw0a | 1 | |
828 | johnpye | 219 | /* |
829 | classify_instance : to be called by PushInterfacPtrs. | ||
830 | aw0a | 1 | |
831 | johnpye | 219 | This function classifies the given instance and appends into |
832 | the necessary list in the p_data structure. | ||
833 | It also sets returns a pointer to the caller for insertion into | ||
834 | the interface_ptr slot. | ||
835 | |||
836 | Note, we should be passing the ipbuf info via vp so we don't | ||
837 | need the nasty global variable and can be more thread safe. | ||
838 | vp is a struct problem_t. | ||
839 | */ | ||
840 | aw0a | 1 | static |
841 | void *classify_instance(struct Instance *inst, VOIDPTR vp) | ||
842 | { | ||
843 | struct solver_ipdata *ip; | ||
844 | struct problem_t *p_data; | ||
845 | CONST char *symval; | ||
846 | p_data = (struct problem_t *)vp; | ||
847 | switch( InstanceKind(inst) ) { | ||
848 | case REAL_ATOM_INST: /* Variable or parameter or real */ | ||
849 | ip = analyze_getip(); | ||
850 | ip->i = inst; | ||
851 | ip->u.v.incident = 0; | ||
852 | ip->u.v.in_block = 0; | ||
853 | ip->u.v.index = 0; | ||
854 | ip->u.v.active = 0; | ||
855 | if( solver_var(inst) ) { | ||
856 | ip->u.v.solvervar = 1; /* must set this regardless of what list */ | ||
857 | ip->u.v.fixed = BooleanChildValue(inst,FIXED_A); | ||
858 | ip->u.v.basis = BooleanChildValue(inst,BASIS_A); | ||
859 | if (RelationsCount(inst)) { | ||
860 | gl_append_ptr(p_data->vars,(POINTER)ip); | ||
861 | } else { | ||
862 | gl_append_ptr(p_data->unas,(POINTER)ip); | ||
863 | } | ||
864 | } else { | ||
865 | ip->u.v.fixed = 1; | ||
866 | ip->u.v.solvervar=0; | ||
867 | if (solver_par(inst) && RelationsCount(inst)) { | ||
868 | gl_append_ptr(p_data->pars,(POINTER)ip); | ||
869 | } else { | ||
870 | gl_append_ptr(p_data->unas,(POINTER)ip); | ||
871 | } | ||
872 | } | ||
873 | return ip; | ||
874 | case BOOLEAN_ATOM_INST: | ||
875 | ip = analyze_getip(); | ||
876 | ip->i = inst; | ||
877 | ip->u.dv.isconst = 0; | ||
878 | ip->u.dv.distype = 0; | ||
879 | ip->u.dv.incident = 0; | ||
880 | ip->u.dv.index = 0; | ||
881 | ip->u.dv.active = 0; | ||
882 | ip->u.dv.value = GetBooleanAtomValue(inst); | ||
883 | if( boolean_var(inst) ) { | ||
884 | ip->u.dv.booleanvar = 1; | ||
885 | ip->u.dv.fixed = BooleanChildValue(inst,FIXED_A); | ||
886 | } else { | ||
887 | ip->u.dv.fixed = 1; | ||
888 | ip->u.dv.booleanvar=0; | ||
889 | } | ||
890 | if( LogRelationsCount(inst) || WhensCount(inst) ) { | ||
891 | gl_append_ptr(p_data->dvars,(POINTER)ip); | ||
892 | if ( WhensCount(inst) ) { | ||
893 | ip->u.dv.inwhen = 1; | ||
894 | } else { | ||
895 | ip->u.dv.inwhen = 0; | ||
896 | } | ||
897 | } else { | ||
898 | gl_append_ptr(p_data->dunas,(POINTER)ip); | ||
899 | } | ||
900 | return ip; | ||
901 | case BOOLEAN_CONSTANT_INST: | ||
902 | if (WhensCount(inst)) { | ||
903 | ip = analyze_getip(); | ||
904 | ip->i = inst; | ||
905 | ip->u.dv.isconst = 1; | ||
906 | ip->u.dv.distype = 0; | ||
907 | ip->u.dv.index = 0; | ||
908 | ip->u.dv.incident = 0; | ||
909 | ip->u.dv.booleanvar=0; | ||
910 | ip->u.dv.fixed = 1; | ||
911 | ip->u.dv.active = 0; | ||
912 | ip->u.dv.value = GetBooleanAtomValue(inst); | ||
913 | gl_append_ptr(p_data->dvars,(POINTER)ip); | ||
914 | return ip; | ||
915 | } else { | ||
916 | return NULL; | ||
917 | } | ||
918 | case INTEGER_ATOM_INST: | ||
919 | if (WhensCount(inst)) { | ||
920 | ip = analyze_getip(); | ||
921 | ip->i = inst; | ||
922 | ip->u.dv.isconst = 0; | ||
923 | ip->u.dv.distype = 1; | ||
924 | ip->u.dv.index = 0; | ||
925 | ip->u.dv.incident = 0; | ||
926 | ip->u.dv.booleanvar=0; | ||
927 | ip->u.dv.fixed = 0; | ||
928 | ip->u.dv.active = 0; | ||
929 | ip->u.dv.value = GetIntegerAtomValue(inst); | ||
930 | gl_append_ptr(p_data->dvars,(POINTER)ip); | ||
931 | return ip; | ||
932 | } else { | ||
933 | return NULL; | ||
934 | } | ||
935 | case SYMBOL_ATOM_INST: | ||
936 | if (WhensCount(inst)) { | ||
937 | symval = SCP(GetSymbolAtomValue(inst)); | ||
938 | if (symval == NULL) { | ||
939 | return NULL; | ||
940 | } | ||
941 | ip = analyze_getip(); | ||
942 | ip->i = inst; | ||
943 | ip->u.dv.isconst = 0; | ||
944 | ip->u.dv.distype = -1; | ||
945 | ip->u.dv.index = 0; | ||
946 | ip->u.dv.incident = 0; | ||
947 | ip->u.dv.booleanvar=0; | ||
948 | ip->u.dv.fixed = 0; | ||
949 | ip->u.dv.active = 0; | ||
950 | if (g_symbol_values_list == NULL) { | ||
951 | g_symbol_values_list = gl_create(2L); | ||
952 | } | ||
953 | ip->u.dv.value = GetIntFromSymbol(symval,g_symbol_values_list); | ||
954 | gl_append_ptr(p_data->dvars,(POINTER)ip); | ||
955 | return ip; | ||
956 | } else { | ||
957 | return NULL; | ||
958 | } | ||
959 | case INTEGER_CONSTANT_INST: | ||
960 | if (WhensCount(inst)) { | ||
961 | ip = analyze_getip(); | ||
962 | ip->i = inst; | ||
963 | ip->u.dv.isconst = 1; | ||
964 | ip->u.dv.distype = 1; | ||
965 | ip->u.dv.index = 0; | ||
966 | ip->u.dv.incident = 0; | ||
967 | ip->u.dv.booleanvar=0; | ||
968 | ip->u.dv.fixed = 1; | ||
969 | ip->u.dv.active = 0; | ||
970 | ip->u.dv.value = GetIntegerAtomValue(inst); | ||
971 | gl_append_ptr(p_data->dvars,(POINTER)ip); | ||
972 | return ip; | ||
973 | } else { | ||
974 | return NULL; | ||
975 | } | ||
976 | case SYMBOL_CONSTANT_INST: | ||
977 | if (WhensCount(inst)) { | ||
978 | symval = SCP(GetSymbolAtomValue(inst)); | ||
979 | if (symval == NULL) { | ||
980 | return NULL; | ||
981 | } | ||
982 | ip = analyze_getip(); | ||
983 | ip->i = inst; | ||
984 | ip->u.dv.isconst = 1; | ||
985 | ip->u.dv.distype = -1; | ||
986 | ip->u.dv.index = 0; | ||
987 | ip->u.dv.incident = 0; | ||
988 | ip->u.dv.booleanvar=0; | ||
989 | ip->u.dv.fixed = 1; | ||
990 | ip->u.dv.active = 0; | ||
991 | if (g_symbol_values_list == NULL) { | ||
992 | g_symbol_values_list = gl_create(2L); | ||
993 | } | ||
994 | ip->u.dv.value = GetIntFromSymbol(symval,g_symbol_values_list); | ||
995 | gl_append_ptr(p_data->dvars,(POINTER)ip); | ||
996 | return ip; | ||
997 | } else { | ||
998 | return NULL; | ||
999 | } | ||
1000 | case REL_INST: /* Relation (or conditional or objective) */ | ||
1001 | ip = analyze_getip(); | ||
1002 | ip->i = inst; | ||
1003 | ip->u.r.active = 1; | ||
1004 | switch(RelationRelop(GetInstanceRelationOnly(inst))) { | ||
1005 | case e_minimize: | ||
1006 | ip->u.r.obj = 1; | ||
1007 | break; | ||
1008 | case e_maximize: | ||
1009 | ip->u.r.obj = -1; | ||
1010 | break; | ||
1011 | default: | ||
1012 | ip->u.r.obj = 0; | ||
1013 | break; | ||
1014 | } | ||
1015 | if ( GetInstanceRelationType(inst)==e_blackbox ) { | ||
1016 | ip->u.r.ext = 1; | ||
1017 | } else { | ||
1018 | ip->u.r.ext = 0; | ||
1019 | } | ||
1020 | if ( RelationIsCond(GetInstanceRelationOnly(inst)) ) { | ||
1021 | ip->u.r.cond = 1; | ||
1022 | } else { | ||
1023 | ip->u.r.cond = 0; | ||
1024 | } | ||
1025 | if ( WhensCount(inst) ) { | ||
1026 | ip->u.r.inwhen = 1; | ||
1027 | } else { | ||
1028 | ip->u.r.inwhen = 0; | ||
1029 | } | ||
1030 | ip->u.r.included = BooleanChildValue(inst,INCLUDED_A); | ||
1031 | ip->u.r.model = 0; | ||
1032 | ip->u.r.index = 0; | ||
1033 | return ip; | ||
1034 | /* note we do NOT append it to lists here */ | ||
1035 | case LREL_INST: /* LogRelation */ | ||
1036 | ip = analyze_getip(); | ||
1037 | ip->i = inst; | ||
1038 | ip->u.lr.active = 1; | ||
1039 | if ( LogRelIsCond(GetInstanceLogRel(inst)) ) { | ||
1040 | ip->u.lr.cond = 1; | ||
1041 | } else { | ||
1042 | ip->u.lr.cond = 0; | ||
1043 | } | ||
1044 | if ( WhensCount(inst) ) { | ||
1045 | ip->u.lr.inwhen = 1; | ||
1046 | } else { | ||
1047 | ip->u.lr.inwhen = 0; | ||
1048 | } | ||
1049 | ip->u.lr.included = BooleanChildValue(inst,INCLUDED_A); | ||
1050 | ip->u.lr.model = 0; | ||
1051 | ip->u.lr.index = 0; | ||
1052 | return ip; | ||
1053 | /* note we do NOT append it to lists here */ | ||
1054 | case MODEL_INST: | ||
1055 | ip = analyze_getip(); | ||
1056 | ip->i = inst; | ||
1057 | ip->u.m.index = 0; | ||
1058 | if ( WhensCount(inst) ) { | ||
1059 | ip->u.m.inwhen = 1; | ||
1060 | } else { | ||
1061 | ip->u.m.inwhen = 0; | ||
1062 | } | ||
1063 | gl_append_ptr(p_data->models,(POINTER)ip); | ||
1064 | return ip; | ||
1065 | case WHEN_INST: | ||
1066 | ip = analyze_getip(); | ||
1067 | ip->i = inst; | ||
1068 | ip->u.w.index = 0; | ||
1069 | if ( WhensCount(inst) ) { | ||
1070 | ip->u.w.inwhen = 1; | ||
1071 | } else { | ||
1072 | ip->u.w.inwhen = 0; | ||
1073 | } | ||
1074 | return ip; | ||
1075 | /* note we do NOT append it to lists here */ | ||
1076 | default: | ||
1077 | return NULL; | ||
1078 | } | ||
1079 | } | ||
1080 | johnpye | 219 | |
1081 | johnpye | 669 | /*------------------------------------------------------------------------------ |
1082 | MAKE PROBLEM routines | ||
1083 | */ | ||
1084 | johnpye | 219 | |
1085 | aw0a | 1 | /* |
1086 | johnpye | 219 | This function sets g_bad_rel_in_list TRUE if it finds any unhappy |
1087 | relations. All the rest of the code depends on ALL relations being | ||
1088 | good, so don't disable the g_bad_rel_in_list feature. | ||
1089 | */ | ||
1090 | johnpye | 190 | static |
1091 | aw0a | 1 | void CountStuffInTree(struct Instance *inst, struct problem_t *p_data) |
1092 | { | ||
1093 | CONST char *symval; | ||
1094 | if (inst!=NULL) { | ||
1095 | switch (InstanceKind(inst)) { | ||
1096 | case REL_INST: | ||
1097 | if( GetInstanceRelationOnly(inst) == NULL || | ||
1098 | GetInstanceRelationType(inst) == e_undefined) { | ||
1099 | /* guard against null relations, unfinished ones */ | ||
1100 | johnpye | 222 | ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR); |
1101 | johnpye | 76 | FPRINTF(ASCERR,"Found bad (unfinished?) relation '"); |
1102 | aw0a | 1 | WriteInstanceName(ASCERR,inst,p_data->root); |
1103 | johnpye | 76 | FPRINTF(ASCERR,"' (in CountStuffInTree)"); |
1104 | error_reporter_end_flush(); | ||
1105 | aw0a | 1 | g_bad_rel_in_list = TRUE; |
1106 | return; | ||
1107 | } | ||
1108 | /* increment according to classification */ | ||
1109 | analyze_CountRelation(inst,p_data); | ||
1110 | break; | ||
1111 | case REAL_ATOM_INST: | ||
1112 | if( solver_var(inst) && RelationsCount(inst)) { | ||
1113 | p_data->nv++; | ||
1114 | } else { | ||
1115 | if (solver_par(inst) && RelationsCount(inst)) { | ||
1116 | /* never passes right now */ | ||
1117 | p_data->np++; | ||
1118 | } else { | ||
1119 | p_data->nu++; | ||
1120 | } | ||
1121 | } | ||
1122 | /* The use of RelationsCount is heuristic since vars may be | ||
1123 | johnpye | 219 | used in relations higher in the tree than the problem is rooted. |
1124 | aw0a | 1 | */ |
1125 | break; | ||
1126 | case BOOLEAN_ATOM_INST: | ||
1127 | if ( ( boolean_var(inst) && LogRelationsCount(inst) ) || | ||
1128 | WhensCount(inst) ) { | ||
1129 | p_data->ndv++; | ||
1130 | } | ||
1131 | else { | ||
1132 | p_data->nud++; | ||
1133 | } | ||
1134 | break; | ||
1135 | case BOOLEAN_CONSTANT_INST: | ||
1136 | case INTEGER_ATOM_INST: | ||
1137 | case INTEGER_CONSTANT_INST: | ||
1138 | if (WhensCount(inst)) { | ||
1139 | p_data->ndv++; | ||
1140 | } | ||
1141 | break; | ||
1142 | case SYMBOL_ATOM_INST: | ||
1143 | case SYMBOL_CONSTANT_INST: | ||
1144 | if (WhensCount(inst)) { | ||
1145 | symval = SCP(GetSymbolAtomValue(inst)); | ||
1146 | if (symval == NULL) { | ||
1147 | FPRINTF(ASCERR,"ERROR: CountStuffInTree found undefined symbol or symbol_constant in WHEN.\n"); | ||
1148 | WriteInstanceName(ASCERR,inst,p_data->root); | ||
1149 | FPRINTF(ASCERR,"\n"); | ||
1150 | g_bad_rel_in_list = TRUE; | ||
1151 | return; | ||
1152 | } | ||
1153 | p_data->ndv++; | ||
1154 | } | ||
1155 | break; | ||
1156 | case LREL_INST: | ||
1157 | if( GetInstanceLogRelOnly(inst) == NULL ) { | ||
1158 | FPRINTF(ASCERR,"ERROR: CountStuffInTree found bad logrel.\n"); | ||
1159 | WriteInstanceName(ASCERR,inst,p_data->root); | ||
1160 | FPRINTF(ASCERR,"\n"); | ||
1161 | g_bad_rel_in_list = TRUE; | ||
1162 | return; | ||
1163 | } | ||
1164 | if ( LogRelIsCond(GetInstanceLogRel(inst)) ) { | ||
1165 | p_data->ncl++; | ||
1166 | } | ||
1167 | else { | ||
1168 | p_data->nl++; | ||
1169 | } | ||
1170 | break; | ||
1171 | case WHEN_INST: | ||
1172 | p_data->nw++; | ||
1173 | break; | ||
1174 | case MODEL_INST: | ||
1175 | p_data->nm++; | ||
1176 | break; | ||
1177 | default: | ||
1178 | break; | ||
1179 | } | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | johnpye | 219 | |
1184 | johnpye | 669 | /** |
1185 | johnpye | 219 | This takes the already derived counts, |
1186 | allocates all the memory we need to allocate for master, | ||
1187 | and builds the var/rel/MODEL/etc master lists. | ||
1188 | filling in p_data and ips as far as possible. | ||
1189 | Returns 0 normally, or 1 if insufficient memory, 2 if nothing to do. | ||
1190 | If 1, then the user should deallocate any partial results in | ||
1191 | a separate cleanup function for p_data-> | ||
1192 | |||
1193 | In particular, after this is done we have | ||
1194 | vars with correct ip values for: | ||
1195 | index; | ||
1196 | incident; | ||
1197 | in_block; | ||
1198 | fixed; (as flag) | ||
1199 | basis; (as flag) | ||
1200 | solvervar; (as flag) | ||
1201 | relations and conditional relations with correct ip values for: | ||
1202 | index; | ||
1203 | model; | ||
1204 | obj; (0 constraint, -1 maximize, +1 minimize) | ||
1205 | ext; | ||
1206 | inwhen; | ||
1207 | cond; | ||
1208 | included; (as flag) | ||
1209 | discrete vars with correct ip values for: | ||
1210 | index; | ||
1211 | incident; | ||
1212 | isconst; | ||
1213 | distype; | ||
1214 | fixed; (as flag) | ||
1215 | booleanvar; (as flag) | ||
1216 | inwhen; | ||
1217 | logrelations and conditional logrelations with correct ip values for: | ||
1218 | index; | ||
1219 | model; | ||
1220 | included; (as flag) | ||
1221 | inwhen; | ||
1222 | cond; | ||
1223 | whens with correct ip values for: | ||
1224 | index; | ||
1225 | model; | ||
1226 | inwhen; | ||
1227 | models with correct ip values for: | ||
1228 | index; | ||
1229 | |||
1230 | Note that these are all indexed from 1, being stored in gllists. | ||
1231 | */ | ||
1232 | aw0a | 1 | static int analyze_make_master_lists(struct problem_t *p_data) |
1233 | { | ||
1234 | long int c, len,v,vlen; | ||
1235 | CONST struct Instance *i; | ||
1236 | CONST struct relation *gut; | ||
1237 | CONST struct logrelation *lgut; | ||
1238 | struct solver_ipdata *vip; | ||
1239 | struct gl_list_t *scratch; | ||
1240 | size_t reqlen; | ||
1241 | int stat; | ||
1242 | johnpye | 190 | reqlen = |
1243 | aw0a | 1 | p_data->nr + p_data->no + p_data->nc + p_data->nl+ p_data->ncl+ /*rels*/ |
1244 | p_data->nv + p_data->ndv + | ||
1245 | p_data->np + p_data->nu + p_data->nud + /* atoms */ | ||
1246 | p_data->nw + /* when */ | ||
1247 | p_data->nm; /* model */ | ||
1248 | if (reqlen <1) { | ||
1249 | return 2; | ||
1250 | } | ||
1251 | |||
1252 | /* CREATE memory for ips */ | ||
1253 | #ifdef NDEBUG | ||
1254 | stat = resize_ipbuf(reqlen,0); | ||
1255 | #else | ||
1256 | stat = resize_ipbuf(reqlen,1); | ||
1257 | #endif /* NDEBUG */ | ||
1258 | if (stat) { | ||
1259 | FPRINTF(ASCERR,"Error: (analyze_make_master) Insufficient memory.\n"); | ||
1260 | return 1; | ||
1261 | } | ||
1262 | |||
1263 | p_data->vars = gl_create(p_data->nv); /* variables */ | ||
1264 | if (p_data->vars == NULL) return 1; | ||
1265 | |||
1266 | p_data->dvars = gl_create(p_data->ndv); /* discrete variables */ | ||
1267 | if (p_data->dvars == NULL) return 1; | ||
1268 | |||
1269 | p_data->pars = gl_create(p_data->np); /* parameters */ | ||
1270 | if (p_data->pars == NULL) return 1; | ||
1271 | |||
1272 | p_data->unas = gl_create(p_data->nu); /* unattached */ | ||
1273 | if (p_data->unas == NULL) return 1; | ||
1274 | |||
1275 | p_data->dunas = gl_create(p_data->nud); /* discrete unattached */ | ||
1276 | if (p_data->dunas == NULL) return 1; | ||
1277 | |||
1278 | p_data->cnds = gl_create(p_data->nc); /* conditional relations */ | ||
1279 | if (p_data->cnds == NULL) return 1; | ||
1280 | |||
1281 | p_data->rels = gl_create(p_data->nr); /* relations */ | ||
1282 | if (p_data->rels == NULL) return 1; | ||
1283 | |||
1284 | p_data->logrels = gl_create(p_data->nl); /* logical relations */ | ||
1285 | if (p_data->logrels == NULL) return 1; | ||
1286 | |||
1287 | p_data->logcnds = gl_create(p_data->ncl); /* conditional logrelations */ | ||
1288 | if (p_data->logcnds == NULL) return 1; | ||
1289 | |||
1290 | p_data->extrels = gl_create(p_data->ne); /* extrelations */ | ||
1291 | if (p_data->extrels == NULL) return 1; | ||
1292 | |||
1293 | p_data->objrels = gl_create(p_data->no); /* objectives */ | ||
1294 | if (p_data->objrels == NULL) return 1; | ||
1295 | |||
1296 | p_data->whens = gl_create(p_data->nw); /* whens */ | ||
1297 | if (p_data->whens == NULL) return 1; | ||
1298 | |||
1299 | p_data->models = gl_create(p_data->nm); /* models */ | ||
1300 | if (p_data->models == NULL) return 1; | ||
1301 | |||
1302 | /* decorate the instance tree with ips, collecting vars and models. */ | ||
1303 | p_data->oldips = PushInterfacePtrs(p_data->root,classify_instance, | ||
1304 | g_reuse.ipcap,1,p_data); | ||
1305 | if (p_data->oldips == NULL) { | ||
1306 | FPRINTF(ASCERR,"Error: (analyze) Insufficient memory.\n"); | ||
1307 | return 1; | ||
1308 | } | ||
1309 | |||
1310 | johnpye | 190 | /* |
1311 | johnpye | 219 | collect relations, objectives, logrels and whens recording the |
1312 | MODEL number in each rel's ip and setting incidence. | ||
1313 | */ | ||
1314 | aw0a | 1 | len = gl_length(p_data->models); |
1315 | for (c=1; c <= len; c++) { | ||
1316 | CollectRelsAndWhens(SIP(gl_fetch(p_data->models,c)),c,p_data); | ||
1317 | SIP(gl_fetch(p_data->models,c))->u.m.index = c; | ||
1318 | } | ||
1319 | if ((long)gl_length(p_data->rels) != p_data->nr || | ||
1320 | (long)gl_length(p_data->objrels) != p_data->no || | ||
1321 | (long)gl_length(p_data->logrels) != p_data->nl || | ||
1322 | (long)gl_length(p_data->whens) != p_data->nw) { | ||
1323 | FPRINTF(ASCERR, | ||
1324 | "Warning: Mismatch in problem census and problem found\n"); | ||
1325 | FPRINTF(ASCERR,"Rels: Counted %lu\t Found %ld\n", | ||
1326 | gl_length(p_data->rels), p_data->nr); | ||
1327 | FPRINTF(ASCERR,"Objs: Counted %lu\t Found %ld\n", | ||
1328 | gl_length(p_data->objrels), p_data->no); | ||
1329 | FPRINTF(ASCERR,"LogRels: Counted %lu\t Found %ld\n", | ||
1330 | gl_length(p_data->logrels),p_data->nl); | ||
1331 | FPRINTF(ASCERR,"Whens: Counted %lu\t Found %ld\n", | ||
1332 | gl_length(p_data->whens), p_data->nw); | ||
1333 | } | ||
1334 | johnpye | 190 | /* |
1335 | johnpye | 219 | relation list is now grouped by model, and the order will be |
1336 | invariant with hardware and ascend invocation so long as | ||
1337 | set FIRSTCHOICE holds in compilation. | ||
1338 | */ | ||
1339 | aw0a | 1 | /* mark vars in constraints incident and index rels */ |
1340 | len = gl_length(p_data->rels); | ||
1341 | for (c=1; c <= len; c++) { | ||
1342 | SIP(gl_fetch(p_data->rels,c))->u.r.index = c; | ||
1343 | gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->rels,c))->i); | ||
1344 | vlen = NumberVariables(gut); | ||
1345 | for( v = 1; v <= vlen; v++ ) { | ||
1346 | i = RelationVariable(gut,v); | ||
1347 | SIP(GetInterfacePtr(i))->u.v.incident = 1; | ||
1348 | } | ||
1349 | } | ||
1350 | /* mark vars in objectives incident */ | ||
1351 | len = gl_length(p_data->objrels); | ||
1352 | for (c=1; c <= len; c++) { | ||
1353 | gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->objrels,c))->i); | ||
1354 | vlen = NumberVariables(gut); | ||
1355 | for( v = 1; v <= vlen; v++ ) { | ||
1356 | i = RelationVariable(gut,v); | ||
1357 | SIP(GetInterfacePtr(i))->u.v.incident = 1; | ||
1358 | } | ||
1359 | } | ||
1360 | |||
1361 | /* mark vars in conditional relations incident */ | ||
1362 | len = gl_length(p_data->cnds); | ||
1363 | for (c=1; c <= len; c++) { | ||
1364 | SIP(gl_fetch(p_data->cnds,c))->u.r.index = c; | ||
1365 | gut = GetInstanceRelationOnly(SIP(gl_fetch(p_data->cnds,c))->i); | ||
1366 | vlen = NumberVariables(gut); | ||
1367 | for( v = 1; v <= vlen; v++ ) { | ||
1368 | i = RelationVariable(gut,v); | ||
1369 | SIP(GetInterfacePtr(i))->u.v.incident = 1; | ||
1370 | } | ||
1371 | } | ||
1372 | |||
1373 | /* mark dvars in logrels incident and index logrels */ | ||
1374 | len = gl_length(p_data->logrels); | ||
1375 | for (c=1; c <= len; c++) { | ||
1376 | SIP(gl_fetch(p_data->logrels,c))->u.lr.index = c; | ||
1377 | lgut = GetInstanceLogRelOnly(SIP(gl_fetch(p_data->logrels,c))->i); | ||
1378 | vlen = NumberBoolVars(lgut); | ||
1379 | for( v = 1; v <= vlen; v++ ) { | ||
1380 | i = LogRelBoolVar(lgut,v); | ||
1381 | SIP(GetInterfacePtr(i))->u.dv.incident = 1; | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1385 | |||
1386 | /* mark dvars in conditional logrels incident */ | ||
1387 | len = gl_length(p_data->logcnds); | ||
1388 | for (c=1; c <= len; c++) { | ||
1389 | SIP(gl_fetch(p_data->logcnds,c))->u.lr.index = c; | ||
1390 | lgut = GetInstanceLogRelOnly(SIP(gl_fetch(p_data->logcnds,c))->i); | ||
1391 | vlen = NumberBoolVars(lgut); | ||
1392 | for( v = 1; v <= vlen; v++ ) { | ||
1393 | i = LogRelBoolVar(lgut,v); | ||
1394 | SIP(GetInterfacePtr(i))->u.dv.incident = 1; | ||
1395 | } | ||
1396 | } | ||
1397 | |||
1398 | /* mark index whens */ | ||
1399 | len = gl_length(p_data->whens); | ||
1400 | for (c=1; c <= len; c++) { | ||
1401 | SIP(gl_fetch(p_data->whens,c))->u.w.index = c; | ||
1402 | } | ||
1403 | johnpye | 190 | /* |
1404 | johnpye | 219 | now we need to move all the nonincident vars off the var list |
1405 | onto the unas list. It is easiest to make a new list and copy | ||
1406 | the existing var list to either it if keep or unas if punt. | ||
1407 | the same goes for parameters that aren't incident. | ||
1408 | We don't do exactly the same for discrete variables because | ||
1409 | many of them are not incident but they are used in when's | ||
1410 | */ | ||
1411 | aw0a | 1 | len = gl_length(p_data->vars); |
1412 | p_data->tmplist = gl_create(len); | ||
1413 | if (p_data->tmplist == NULL) return 1; | ||
1414 | for (c=1; c <= len; c++) { | ||
1415 | /* dispose of var */ | ||
1416 | vip = SIP(gl_fetch(p_data->vars,c)); | ||
1417 | if ( vip->u.v.incident == 1) { | ||
1418 | gl_append_ptr(p_data->tmplist,vip); | ||
1419 | } else { | ||
1420 | gl_append_ptr(p_data->unas,vip); | ||
1421 | } | ||
1422 | } | ||
1423 | gl_destroy(p_data->vars); /* punt the old list */ | ||
1424 | p_data->vars = p_data->tmplist; /* make shortened list var list */ | ||
1425 | p_data->tmplist = NULL; | ||
1426 | |||
1427 | p_data->nv = gl_length(p_data->vars); | ||
1428 | |||
1429 | len = gl_length(p_data->pars); | ||
1430 | p_data->tmplist = gl_create(len); | ||
1431 | if (p_data->tmplist == NULL) { | ||
1432 | return 1; | ||
1433 | } | ||
1434 | for (c=1; c <= len; c++) { | ||
1435 | /* dispose of par */ | ||
1436 | vip = SIP(gl_fetch(p_data->pars,c)); | ||
1437 | if ( vip->u.v.incident == 1) { | ||
1438 | gl_append_ptr(p_data->tmplist,vip); | ||
1439 | } else { | ||
1440 | gl_append_ptr(p_data->unas,vip); | ||
1441 | } | ||
1442 | } | ||
1443 | gl_destroy(p_data->pars); /* punt the old list */ | ||
1444 | p_data->pars = p_data->tmplist; /* make shortened list par list */ | ||
1445 | p_data->tmplist = NULL; | ||
1446 | |||
1447 | p_data->np = gl_length(p_data->pars); | ||
1448 | johnpye | 190 | p_data->nu = gl_length(p_data->unas); |
1449 | |||
1450 | aw0a | 1 | /* |
1451 | johnpye | 219 | discrete variables: take the incident dis vars in logrels first, |
1452 | then append the dis vars which are used only in whens | ||
1453 | */ | ||
1454 | aw0a | 1 | p_data->lrelinc = 0; |
1455 | len = gl_length(p_data->dvars); | ||
1456 | if ( len > 0) { | ||
1457 | p_data->tmplist = gl_create(len); | ||
1458 | scratch = gl_create(2L); | ||
1459 | if (p_data->tmplist == NULL) return 1; | ||
1460 | for (c=1; c <= len; c++) { | ||
1461 | /* dispose of incident discrete vars */ | ||
1462 | vip = SIP(gl_fetch(p_data->dvars,c)); | ||
1463 | if ( vip->u.dv.incident == 1) { | ||
1464 | gl_append_ptr(p_data->tmplist,vip); | ||
1465 | p_data->lrelinc++; /* Number of incident dis vars */ | ||
1466 | } else { | ||
1467 | gl_append_ptr(scratch,vip); | ||
1468 | } | ||
1469 | } | ||
1470 | gl_destroy(p_data->dvars); | ||
1471 | p_data->dvars = p_data->tmplist; | ||
1472 | p_data->tmplist = NULL; | ||
1473 | /* append discrete non-boolean vars at the end of the list */ | ||
1474 | len = gl_length(scratch); | ||
1475 | for (c=1; c <= len; c++) { | ||
1476 | vip = SIP(gl_fetch(scratch,c)); | ||
1477 | gl_append_ptr(p_data->dvars,vip); | ||
1478 | } | ||
1479 | gl_destroy(scratch); | ||
1480 | scratch = NULL; | ||
1481 | } | ||
1482 | |||
1483 | /* | ||
1484 | johnpye | 219 | The following patch is to avoid the system to crash. |
1485 | When multiple definitions of a solver_var have introduced into the | ||
1486 | system, ASCEND may fail in identifying that a REAL_ATOM is a refinement | ||
1487 | of a solver_var. This causes the system to think that, even that there | ||
1488 | are relations into the system, there are no incidences in these relations | ||
1489 | that fall into the category of a variable. As a consequence, the length | ||
1490 | of the list of variables is zero. That of course will introduce | ||
1491 | insanities while trying to build the slv system. Some | ||
1492 | solutions to this problem are: | ||
1493 | johnpye | 190 | |
1494 | johnpye | 219 | The easier for us is just to alert the user and to force him/her to |
1495 | reload all the type defintions again. That is the current solution | ||
1496 | |||
1497 | The correct (but time consuming) solution is the implementation of a | ||
1498 | SolverAtomInstance, which still needs parser and interpreter support | ||
1499 | */ | ||
1500 | |||
1501 | aw0a | 1 | if (p_data->nr != 0 && p_data->nv==0) { |
1502 | FPRINTF(ASCERR, "\n"); | ||
1503 | FPRINTF(ASCERR, "A L E R T\n"); | ||
1504 | johnpye | 190 | FPRINTF(ASCERR, "\n"); |
1505 | aw0a | 1 | FPRINTF(ASCERR, "Problem should contain at least one variable %s", |
1506 | "and one relation\n"); | ||
1507 | johnpye | 190 | FPRINTF(ASCERR, "\n"); |
1508 | aw0a | 1 | FPRINTF(ASCERR, "There are relations into the system, but the number \n"); |
1509 | FPRINTF(ASCERR, "of variables is zero. That means that the existent \n"); | ||
1510 | FPRINTF(ASCERR, "vars were not recognized as solver_vars. A possible \n"); | ||
1511 | FPRINTF(ASCERR, "reason is that you have introduced conflicting \n"); | ||
1512 | FPRINTF(ASCERR, "definitions of solver_var into the system. Please \n"); | ||
1513 | FPRINTF(ASCERR, "delete all your types and reload your models \n"); | ||
1514 | FPRINTF(ASCERR, "with the appropriate definition of solver_var\n"); | ||
1515 | FPRINTF(ASCERR, "\n"); | ||
1516 | FPRINTF(ASCERR, "Solver system will not be built.\n"); | ||
1517 | FPRINTF(ASCERR, "\n"); | ||
1518 | return 2; | ||
1519 | } | ||
1520 | johnpye | 190 | |
1521 | aw0a | 1 | return 0; |
1522 | } | ||
1523 | |||
1524 | johnpye | 669 | /** |
1525 | johnpye | 219 | This function cleans up an errant problem_t or a good one that we're |
1526 | done with. We should have set to null any pointers to memory we are | ||
1527 | keeping elsewhere before calling this. | ||
1528 | */ | ||
1529 | johnpye | 669 | static void analyze_free_lists(struct problem_t *p_data) |
1530 | { | ||
1531 | /* memory containing gl_lists of atomic structure pointers */ | ||
1532 | if(p_data->extrels != NULL)gl_free_and_destroy(p_data->extrels); | ||
1533 | |||
1534 | aw0a | 1 | #define AFUN(ptr) if (ptr!=NULL) ascfree(ptr); (ptr) = NULL |
1535 | #define ADUN(ptr) if (ptr!=NULL) gl_destroy(ptr); (ptr) = NULL | ||
1536 | johnpye | 669 | |
1537 | /* gl_lists without memory items use ADUN */ | ||
1538 | aw0a | 1 | ADUN(p_data->vars); |
1539 | ADUN(p_data->dvars); | ||
1540 | ADUN(p_data->pars); | ||
1541 | ADUN(p_data->unas); | ||
1542 | ADUN(p_data->dunas); | ||
1543 | ADUN(p_data->rels); | ||
1544 | ADUN(p_data->objrels); | ||
1545 | ADUN(p_data->models); | ||
1546 | ADUN(p_data->cnds); | ||
1547 | ADUN(p_data->logrels); | ||
1548 | ADUN(p_data->logcnds); | ||
1549 | ADUN(p_data->whens); | ||
1550 | johnpye | 669 | |
1551 | /* blocks of memory use AFUN */ | ||
1552 | aw0a | 1 | AFUN(p_data->blocks); |
1553 | AFUN(p_data->reldata); | ||
1554 | AFUN(p_data->objdata); | ||
1555 | AFUN(p_data->condata); | ||
1556 | AFUN(p_data->lrdata); | ||
1557 | AFUN(p_data->logcondata); | ||
1558 | AFUN(p_data->vardata); | ||
1559 | AFUN(p_data->pardata); | ||
1560 | AFUN(p_data->undata); | ||
1561 | AFUN(p_data->disdata); | ||
1562 | AFUN(p_data->undisdata); | ||
1563 | AFUN(p_data->whendata); | ||
1564 | AFUN(p_data->bnddata); | ||
1565 | AFUN(p_data->relincidence); | ||
1566 | AFUN(p_data->varincidence); | ||
1567 | AFUN(p_data->logrelinciden); | ||
1568 | AFUN(p_data->mastervl); | ||
1569 | AFUN(p_data->masterdl); | ||
1570 | AFUN(p_data->masterrl); | ||
1571 | AFUN(p_data->masterol); | ||
1572 | AFUN(p_data->mastercl); | ||
1573 | AFUN(p_data->masterll); | ||
1574 | AFUN(p_data->mastercll); | ||
1575 | AFUN(p_data->masterpl); | ||
1576 | AFUN(p_data->masterul); | ||
1577 | AFUN(p_data->masterdul); | ||
1578 | AFUN(p_data->masterwl); | ||
1579 | AFUN(p_data->masterbl); | ||
1580 | AFUN(p_data->solvervl); | ||
1581 | AFUN(p_data->solverdl); | ||
1582 | AFUN(p_data->solverrl); | ||
1583 | AFUN(p_data->solverol); | ||
1584 | AFUN(p_data->solvercl); | ||
1585 | AFUN(p_data->solverll); | ||
1586 | AFUN(p_data->solvercll); | ||
1587 | AFUN(p_data->solverpl); | ||
1588 | AFUN(p_data->solverul); | ||
1589 | AFUN(p_data->solverdul); | ||
1590 | AFUN(p_data->solverwl); | ||
1591 | AFUN(p_data->solverbl); | ||
1592 | AFUN(p_data->erlist); | ||
1593 | johnpye | 669 | |
1594 | #undef AFUN | ||
1595 | #undef ADUN | ||
1596 | aw0a | 1 | } |
1597 | |||
1598 | |||
1599 | johnpye | 669 | /*------------------------------------------------------------------------------ |
1600 | 'WHEN' PROCESSING | ||
1601 | johnpye | 219 | */ |
1602 | aw0a | 1 | |
1603 | johnpye | 669 | /** |
1604 | johnpye | 219 | This function receives as argument the list of values of each of the |
1605 | CASES of a WHEN statement. The values in the list can be integer values, | ||
1606 | symbol values, or boolean values. So, the goal of this function is to | ||
1607 | obtain an equivalent list of ONLY integer values for such a list. In this | ||
1608 | way, for example, the boolean value TRUE is equivalent to the integer | ||
1609 | 1. The function GentIntFromSymbol is used to generate an integer value | ||
1610 | which will be equivalent to a symbol value | ||
1611 | */ | ||
1612 | aw0a | 1 | static |
1613 | void ProcessValueList(struct Set *ValueList, int *value, | ||
1614 | struct gl_list_t *symbol_list) | ||
1615 | { | ||
1616 | CONST struct Expr *expr; | ||
1617 | struct Set *s; | ||
1618 | |||
1619 | s = ValueList; | ||
1620 | if (ValueList!=NULL) { | ||
1621 | while (s != NULL) { | ||
1622 | expr = GetSingleExpr(s); | ||
1623 | switch(ExprType(expr)) { | ||
1624 | case e_boolean: | ||
1625 | *value = ExprBValue(expr); | ||
1626 | if (*value == 2) { /* ANY */ | ||
1627 | *value = -2; | ||
1628 | } | ||
1629 | break; | ||
1630 | case e_int: | ||
1631 | *value = ExprIValue(expr); | ||
1632 | break; | ||
1633 | case e_symbol: | ||
1634 | *value = GetIntFromSymbol(SCP(ExprSymValue(expr)),symbol_list); | ||
1635 | break; | ||
1636 | default: | ||
1637 | break; | ||
1638 | } | ||
1639 | s = NextSet(s); | ||
1640 | value++; | ||
1641 | } | ||
1642 | } else { | ||
1643 | *value = -1; /* OTHERWISE */ | ||
1644 | } | ||
1645 | } | ||
1646 | |||
1647 | |||
1648 | johnpye | 669 | /** |
1649 | Process arrays inside WHENs (requires a recursive analysis). | ||
1650 | |||
1651 | @see ProcessSolverWhens | ||
1652 | johnpye | 219 | */ |
1653 | aw0a | 1 | static |
1654 | void ProcessArraysInWhens(struct Instance *cur_inst, | ||
1655 | struct gl_list_t *rels, | ||
1656 | struct gl_list_t *logrels, | ||
1657 | struct gl_list_t *whens) | ||
1658 | { | ||
1659 | struct rel_relation *rel; | ||
1660 | struct logrel_relation *lrel; | ||
1661 | struct w_when *w; | ||
1662 | struct Instance *child; | ||
1663 | struct solver_ipdata *ip; | ||
1664 | unsigned long c,nch; | ||
1665 | |||
1666 | if (cur_inst==NULL) return; | ||
1667 | nch = NumberChildren(cur_inst); | ||
1668 | for (c=1;c<=nch;c++) { | ||
1669 | child = InstanceChild(cur_inst,c); | ||
1670 | if (child==NULL) continue; | ||
1671 | switch (InstanceKind(child)) { | ||
1672 | case REL_INST: | ||
1673 | ip = SIP(GetInterfacePtr(child)); | ||
1674 | ip->u.r.active = 0; | ||
1675 | rel = ip->u.r.data; | ||
1676 | gl_append_ptr(rels,rel); | ||
1677 | break; | ||
1678 | case LREL_INST: | ||
1679 | ip = SIP(GetInterfacePtr(child)); | ||
1680 | ip->u.lr.active = 0; | ||
1681 | lrel = ip->u.lr.data; | ||
1682 | gl_append_ptr(logrels,lrel); | ||
1683 | break; | ||
1684 | case WHEN_INST: | ||
1685 | ip = SIP(GetInterfacePtr(child)); | ||
1686 | w = ip->u.w.data; | ||
1687 | gl_append_ptr(whens,w); | ||
1688 | when_set_inwhen(w,TRUE); | ||
1689 | break; | ||
1690 | case MODEL_INST: | ||
1691 | ProcessModelsInWhens(child,rels,logrels,whens); | ||
1692 | break; | ||
1693 | case ARRAY_ENUM_INST: | ||
1694 | case ARRAY_INT_INST: | ||
1695 | if (ArrayIsRelation(child) || ArrayIsWhen(child) | ||
1696 | || ArrayIsLogRel(child) || ArrayIsModel(child)) { | ||
1697 | ProcessArraysInWhens(child,rels,logrels,whens); | ||
1698 | } | ||
1699 | break; | ||
1700 | default: | ||
1701 | break; | ||
1702 | } | ||
1703 | } | ||
1704 | } | ||
1705 | |||
1706 | johnpye | 669 | /** |
1707 | Process MODELs inside WHENs (requires a recursive analysis). | ||
1708 | |||
1709 | @see ProcessSolverWhens | ||
1710 | */ | ||
1711 | aw0a | 1 | static |
1712 | void ProcessModelsInWhens(struct Instance *cur_inst, struct gl_list_t *rels, | ||
1713 | struct gl_list_t *logrels, struct gl_list_t *whens) | ||
1714 | { | ||
1715 | struct rel_relation *rel; | ||
1716 | struct logrel_relation *lrel; | ||
1717 | struct w_when *w; | ||
1718 | struct Instance *child; | ||
1719 | struct solver_ipdata *ip; | ||
1720 | unsigned long c,nch; | ||
1721 | |||
1722 | if (cur_inst==NULL) return; | ||
1723 | nch = NumberChildren(cur_inst); | ||
1724 | for (c=1;c<=nch;c++) { | ||
1725 | child = InstanceChild(cur_inst,c); | ||
1726 | if (child==NULL) continue; | ||
1727 | switch (InstanceKind(child)) { | ||
1728 | case REL_INST: | ||
1729 | ip = SIP(GetInterfacePtr(child)); | ||
1730 | ip->u.r.active = 0; | ||
1731 | rel = ip->u.r.data; | ||
1732 | gl_append_ptr(rels,rel); | ||
1733 | break; | ||
1734 | case LREL_INST: | ||
1735 | ip = SIP(GetInterfacePtr(child)); | ||
1736 | ip->u.lr.active = 0; | ||
1737 | lrel = ip->u.lr.data; | ||
1738 | gl_append_ptr(logrels,lrel); | ||
1739 | break; | ||
1740 | case WHEN_INST: | ||
1741 | ip = SIP(GetInterfacePtr(child)); | ||
1742 | w = ip->u.w.data; | ||
1743 | gl_append_ptr(whens,w); | ||
1744 | when_set_inwhen(w,TRUE); | ||
1745 | break; | ||
1746 | case MODEL_INST: | ||
1747 | ProcessModelsInWhens(child,rels,logrels,whens); | ||
1748 | break; | ||
1749 | case ARRAY_ENUM_INST: | ||
1750 | case ARRAY_INT_INST: | ||
1751 | if (ArrayIsRelation(child) || ArrayIsWhen(child) | ||
1752 | || ArrayIsLogRel(child) || ArrayIsModel(child)) { | ||
1753 | ProcessArraysInWhens(child,rels,logrels,whens); | ||
1754 | } | ||
1755 | break; | ||
1756 | default: | ||
1757 | break; | ||
1758 | } | ||
1759 | } | ||
1760 | } | ||
1761 | |||
1762 | |||
1763 | johnpye | 669 | /** |
1764 | Fill in the list of cases and variables of a w_when structure with | ||
1765 | the appropriate data. | ||
1766 | |||
1767 | The information required is provided by the corresponding when Instance | ||
1768 | generated in the compilation time. So, what we do is: | ||
1769 | johnpye | 219 | 1) Obtain the list of variables and the list of cases from each |
1770 | WHEN intance. | ||
1771 | The list of variables is actually a list of pointers to instances | ||
1772 | 2) From each CASE, obtain also the list of references. This list of | ||
1773 | references contains a list of pointers to each relation,logrelation and | ||
1774 | model included inside the case. | ||
1775 | 3) The pointers to the variables, relations, logrelations and models are | ||
1776 | used to obtain the solver data associated with the compiled instances. | ||
1777 | 4) Arrays and models are managed recursively with the two previous | ||
1778 | functions. | ||
1779 | */ | ||
1780 | aw0a | 1 | static |
1781 | void ProcessSolverWhens(struct w_when *when,struct Instance *i) | ||
1782 | { | ||
1783 | struct gl_list_t *scratch; | ||
1784 | struct gl_list_t *wvars; | ||
1785 | struct gl_list_t *ref; | ||
1786 | struct gl_list_t *rels; | ||
1787 | struct gl_list_t *logrels; | ||
1788 | struct gl_list_t *whens; | ||
1789 | struct gl_list_t *diswhens; | ||
1790 | struct Set *ValueList; | ||
1791 | struct Instance *cur_inst; | ||
1792 | struct Case *cur_case; | ||
1793 | struct solver_ipdata *ip; | ||
1794 | struct dis_discrete *dvar; | ||
1795 | struct rel_relation *rel; | ||
1796 | struct logrel_relation *lrel; | ||
1797 | struct w_when *w; | ||
1798 | struct when_case *cur_sol_case; | ||
1799 | int c,r,len,lref; | ||
1800 | int *value; | ||
1801 | |||
1802 | scratch = GetInstanceWhenVars(i); | ||
1803 | len = gl_length(scratch); | ||
1804 | wvars = gl_create(len); | ||
1805 | when->dvars = wvars; | ||
1806 | for (c=1;c<=len;c++) { | ||
1807 | cur_inst = (struct Instance *)(gl_fetch(scratch,c)); | ||
1808 | ip = SIP(GetInterfacePtr(cur_inst)); | ||
1809 | dvar = ip->u.dv.data; | ||
1810 | if (dis_whens_list(dvar)==NULL) { | ||
1811 | diswhens = gl_create(2L); | ||
1812 | dis_set_whens_list(dvar,diswhens); | ||
1813 | } else { | ||
1814 | diswhens = dis_whens_list(dvar); | ||
1815 | } | ||
1816 | gl_append_ptr(diswhens,when); | ||
1817 | gl_append_ptr(when->dvars,dvar); | ||
1818 | } | ||
1819 | |||
1820 | scratch = GetInstanceWhenCases(i); | ||
1821 | len = gl_length(scratch); | ||
1822 | when->cases = gl_create(len); | ||
1823 | for (c=1;c<=len;c++) { | ||
1824 | cur_sol_case = when_case_create(NULL); | ||
1825 | cur_case = (struct Case *)(gl_fetch(scratch,c)); | ||
1826 | ValueList = GetCaseValues(cur_case); | ||
1827 | value = &(cur_sol_case->values[0]); | ||
1828 | if (g_symbol_values_list == NULL) { | ||
1829 | g_symbol_values_list = gl_create(2L); | ||
1830 | } | ||
1831 | ProcessValueList(ValueList,value,g_symbol_values_list); | ||
1832 | ref = GetCaseReferences(cur_case); | ||
1833 | lref = gl_length(ref); | ||
1834 | rels = gl_create(lref); /* maybe allocating less than needed (models) */ | ||
1835 | logrels = gl_create(lref); /* maybe allocating less than needed */ | ||
1836 | whens = gl_create(lref); /* maybe allocating more than needed */ | ||
1837 | for (r=1;r<=lref;r++) { | ||
1838 | cur_inst = (struct Instance *)(gl_fetch(ref,r)); | ||
1839 | switch(InstanceKind(cur_inst)){ | ||
1840 | case REL_INST: | ||
1841 | ip = SIP(GetInterfacePtr(cur_inst)); | ||
1842 | ip->u.r.active = 0; | ||
1843 | rel = ip->u.r.data; | ||
1844 | gl_append_ptr(rels,rel); | ||
1845 | break; | ||
1846 | case LREL_INST: | ||
1847 | ip = SIP(GetInterfacePtr(cur_inst)); | ||
1848 | ip->u.lr.active = 0; | ||
1849 | lrel = ip->u.lr.data; | ||
1850 | gl_append_ptr(logrels,lrel); | ||
1851 | break; | ||
1852 | case WHEN_INST: | ||
1853 | ip = SIP(GetInterfacePtr(cur_inst)); | ||
1854 | w = ip->u.w.data; | ||
1855 | gl_append_ptr(whens,w); | ||
1856 | when_set_inwhen(w,TRUE); | ||
1857 | break; | ||
1858 | case MODEL_INST: | ||
1859 | ProcessModelsInWhens(cur_inst,rels,logrels,whens); | ||
1860 | break; | ||
1861 | default: | ||
1862 | break; | ||
1863 | } | ||
1864 | } | ||
1865 | when_case_set_rels_list(cur_sol_case,rels); | ||
1866 | when_case_set_logrels_list(cur_sol_case,logrels); | ||
1867 | when_case_set_whens_list(cur_sol_case,whens); | ||
1868 | when_case_set_active(cur_sol_case,FALSE); | ||
1869 | gl_append_ptr(when->cases,cur_sol_case); | ||
1870 | } | ||
1871 | } | ||
1872 | |||
1873 | johnpye | 669 | /*------------------------------------------------------------------------------ |
1874 | RECONFIGURATION OF CONDITIONAL MODELS | ||
1875 | aw0a | 1 | |
1876 | johnpye | 669 | /** |
1877 | Is this (discrete) variable inside a WHEN? | ||
1878 | aw0a | 1 | |
1879 | johnpye | 669 | @return |
1880 | 1 if discrete var is a member of the when var list, | ||
1881 | else 0 | ||
1882 | johnpye | 219 | */ |
1883 | aw0a | 1 | int dis_var_in_a_when(struct Instance *var, struct w_when *when) |
1884 | { | ||
1885 | struct Instance *winst; | ||
1886 | |||
1887 | winst = (struct Instance *)(when_instance(when)); | ||
1888 | return VarFoundInWhen(var,winst); | ||
1889 | } | ||
1890 | |||
1891 | |||
1892 | johnpye | 669 | /** |
1893 | johnpye | 219 | Determine if the conditional variable inst is part of the |
1894 | variable list of some when in the when list. | ||
1895 | */ | ||
1896 | aw0a | 1 | int varinst_found_in_whenlist(slv_system_t sys, struct Instance *inst) |
1897 | { | ||
1898 | struct w_when **whenlist; | ||
1899 | struct w_when *when; | ||
1900 | int c; | ||
1901 | |||
1902 | whenlist = slv_get_solvers_when_list(sys); | ||
1903 | for (c=0; whenlist[c]!=NULL; c++) { | ||
1904 | when = whenlist[c]; | ||
1905 | if (dis_var_in_a_when(inst,when)) { | ||
1906 | return 1; | ||
1907 | } | ||
1908 | } | ||
1909 | return 0; | ||
1910 | } | ||
1911 | |||
1912 | johnpye | 669 | /*------------------------------------------------------------------------------ |
1913 | BOUNDARY PROCESSING | ||
1914 | johnpye | 219 | */ |
1915 | aw0a | 1 | |
1916 | johnpye | 669 | /** |
1917 | johnpye | 219 | Get the list or logrelation including a boundary (by means of a |
1918 | SATISFIED term). This function look the structures in the compiler | ||
1919 | side and make the same link in the solver side | ||
1920 | */ | ||
1921 | aw0a | 1 | static |
1922 | void GetListOfLogRels(struct bnd_boundary *bnd, struct Instance *inst) | ||
1923 | { | ||
1924 | struct gl_list_t *logrels; | ||
1925 | unsigned long c,len; | ||
1926 | struct Instance *i; | ||
1927 | struct logrel_relation *lrel; | ||
1928 | struct solver_ipdata *lrip; | ||
1929 | |||
1930 | len = LogRelationsCount(inst); | ||
1931 | |||
1932 | if (len>0) { | ||
1933 | logrels = gl_create(len); | ||
1934 | for (c=1; c<=len; c++) { | ||
1935 | i = LogRelationsForInstance(inst,c); | ||
1936 | lrip = SIP(GetInterfacePtr(i)); | ||
1937 | lrel = lrip->u.lr.data; | ||
1938 | gl_append_ptr(logrels,lrel); | ||
1939 | } | ||
1940 | bnd_set_logrels(bnd,logrels); | ||
1941 | } | ||
1942 | return; | ||
1943 | } | ||
1944 | |||
1945 | johnpye | 669 | /** |
1946 | johnpye | 219 | Get the tolerance used to define the satisfaction of a boundary |
1947 | (Defined in the SATISFIED term) | ||
1948 | */ | ||
1949 | aw0a | 1 | static |
1950 | void GetTolerance(struct bnd_boundary *bnd) | ||
1951 | { | ||
1952 | struct gl_list_t *logrels; | ||
1953 | unsigned long c,len; | ||
1954 | struct logrel_relation *lrel; | ||
1955 | struct Instance *i,*rel; | ||
1956 | double tolerance; | ||
1957 | |||
1958 | rel = (struct Instance *)(rel_instance(bnd_rel(bnd_real_cond(bnd)))); | ||
1959 | logrels = bnd_logrels(bnd); | ||
1960 | len = gl_length(logrels); | ||
1961 | for (c=1; c<=len; c++) { | ||
1962 | lrel = (struct logrel_relation *)(gl_fetch(logrels,c)); | ||
1963 | i = (struct Instance *)(logrel_instance(lrel)); | ||
1964 | if (FindTolInSatTermOfLogRel(i,rel,&tolerance )) { | ||
1965 | bnd_set_tolerance(bnd,tolerance); | ||
1966 | return; | ||
1967 | } | ||
1968 | } | ||
1969 | } | ||
1970 | |||
1971 | johnpye | 669 | /** |
1972 | johnpye | 219 | Here we roll the master lists and bridge data into relation/var/ |
1973 | logrelation/conditional/when etc. lists for the consumer. | ||
1974 | Includes fixing up rel caches and initing flagbits as best we can. | ||
1975 | includes setting master indices on rel/var/logrel/when etc. | ||
1976 | returns 0 if ok, 1 if out of memory, 2 if the problem does not | ||
1977 | contain at least one variable in one equation | ||
1978 | */ | ||
1979 | aw0a | 1 | static int analyze_make_solvers_lists(struct problem_t *p_data) |
1980 | { | ||
1981 | CONST struct relation *gut; | ||
1982 | CONST struct logrelation *lgut; | ||
1983 | struct ExtRelCache *cache; | ||
1984 | struct Instance *i; | ||
1985 | struct Instance *i_r; | ||
1986 | johnpye | 89 | struct solver_ipdata *rip = NULL, *vip; |
1987 | aw0a | 1 | struct solver_ipdata *lrip, *dvip, *wip; |
1988 | struct var_variable **incidence = NULL; | ||
1989 | struct rel_relation **varincidence = NULL; | ||
1990 | struct dis_discrete **logincidence = NULL; | ||
1991 | struct var_variable *var; | ||
1992 | struct rel_relation *rel; | ||
1993 | struct dis_discrete *dvar; | ||
1994 | struct logrel_relation *lrel; | ||
1995 | struct bnd_boundary *bnd; | ||
1996 | struct w_when *when; | ||
1997 | int order,nnzold, nodestamp; | ||
1998 | int logorder,lognnzold; | ||
1999 | int c,len,v,vlen,r,found; | ||
2000 | uint32 flags; | ||
2001 | |||
2002 | order = MAX(gl_length(p_data->vars),gl_length(p_data->rels)); | ||
2003 | johnpye | 190 | nnzold = p_data->nnz = p_data->nnztot |
2004 | aw0a | 1 | = p_data->nnzobj = p_data->nnzcond = 0; |
2005 | p_data->nrow = 0; /* number of included relations */ | ||
2006 | for (c=1,len = gl_length(p_data->rels); c <= len; c++) { | ||
2007 | rip = SIP(gl_fetch(p_data->rels,c)); | ||
2008 | gut = GetInstanceRelationOnly(rip->i); | ||
2009 | vlen = NumberVariables(gut); | ||
2010 | p_data->nnztot += vlen; | ||
2011 | if (rip->u.r.included) { | ||
2012 | p_data->nrow++; | ||
2013 | nnzold = p_data->nnz; | ||
2014 | for( v = 1 ; v <= vlen; v++ ) { | ||
2015 | i = RelationVariable(gut,v); | ||
2016 | vip = SIP(GetInterfacePtr(i)); | ||
2017 | if (!(vip->u.v.fixed)) { | ||
2018 | p_data->nnz++; | ||
2019 | } | ||
2020 | } | ||
2021 | if (p_data->nnz==nnzold) { | ||
2022 | johnpye | 222 | ERROR_REPORTER_START_NOLINE(ASC_USER_WARNING); |
2023 | johnpye | 76 | FPRINTF(ASCERR,"No free variables in included relation '"); |
2024 | WriteInstanceName(ASCERR,rip->i,p_data->root); | ||
2025 | FPRINTF(ASCERR,"'"); | ||
2026 | error_reporter_end_flush(); | ||
2027 | aw0a | 1 | } |
2028 | } | ||
2029 | } | ||
2030 | for (c=1,len = gl_length(p_data->objrels); c <= len; c++) { | ||
2031 | rip = SIP(gl_fetch(p_data->objrels,c)); | ||
2032 | gut = GetInstanceRelationOnly(rip->i); | ||
2033 | vlen = NumberVariables(gut); | ||
2034 | p_data->nnzobj += vlen; | ||
2035 | } | ||
2036 | |||
2037 | /* Conditional relations */ | ||
2038 | for (c=1,len = gl_length(p_data->cnds); c <= len; c++) { | ||
2039 | rip = SIP(gl_fetch(p_data->cnds,c)); | ||
2040 | gut = GetInstanceRelationOnly(rip->i); | ||
2041 | vlen = NumberVariables(gut); | ||
2042 | p_data->nnzcond += vlen; | ||
2043 | } | ||
2044 | |||
2045 | |||
2046 | johnpye | 190 | /* |
2047 | johnpye | 219 | calculate the number of free and incident variables, ncol |
2048 | we put all the nonincident on the unas list, so just check fixed. | ||
2049 | */ | ||
2050 | aw0a | 1 | for (c=1,len = gl_length(p_data->vars); c <= len; c++) { |
2051 | vip = SIP(gl_fetch(p_data->vars,c)); | ||
2052 | if (!(vip->u.v.fixed)) p_data->ncol++; | ||
2053 | } | ||
2054 | johnpye | 190 | /* |
2055 | johnpye | 219 | now, at last we have cols jacobian in the order we want the lists to |
2056 | be handed to the solvers. | ||
2057 | */ | ||
2058 | aw0a | 1 | |
2059 | johnpye | 219 | |
2060 | aw0a | 1 | logorder = MAX((unsigned long)p_data->lrelinc,gl_length(p_data->logrels)); |
2061 | lognnzold = p_data->lognnz = p_data->lrelincsize = 0; | ||
2062 | p_data->lognrow = 0; /* number of included logrelations */ | ||
2063 | for (c=1,len = gl_length(p_data->logrels); c <= len; c++) { | ||
2064 | lrip = SIP(gl_fetch(p_data->logrels,c)); | ||
2065 | lgut = GetInstanceLogRelOnly(lrip->i); | ||
2066 | vlen = NumberBoolVars(lgut); | ||
2067 | p_data->lrelincsize += vlen; | ||
2068 | if (lrip->u.lr.included) { | ||
2069 | p_data->lognrow++; | ||
2070 | lognnzold = p_data->lognnz; | ||
2071 | for( v = 1 ; v <= vlen; v++ ) { | ||
2072 | i = LogRelBoolVar(lgut,v); | ||
2073 | dvip = SIP(GetInterfacePtr(i)); | ||
2074 | if (!(dvip->u.dv.fixed)) { | ||
2075 | p_data->lognnz++; | ||
2076 | } | ||
2077 | } | ||
2078 | if (p_data->lognnz==lognnzold) { | ||
2079 | FPRINTF(ASCWAR, | ||
2080 | "No free boolean variables in included logrelation:\n"); | ||
2081 | WriteInstanceName(ASCWAR,rip->i,p_data->root); | ||
2082 | } | ||
2083 | } | ||
2084 | } | ||
2085 | |||
2086 | /* Conditional logrelations */ | ||
2087 | for (c=1,len = gl_length(p_data->logcnds); c <= len; c++) { | ||
2088 | lrip = SIP(gl_fetch(p_data->logcnds,c)); | ||
2089 | lgut = GetInstanceLogRelOnly(lrip->i); | ||
2090 | vlen = NumberBoolVars(lgut); | ||
2091 | p_data->lrelincsize += vlen; | ||
2092 | } | ||
2093 | |||
2094 | if (!(p_data->nnztot+p_data->nnzobj) && !(p_data->lognnz)) { | ||
2095 | FPRINTF(ASCERR, "Problem should contain at least one variable %s", | ||
2096 | "and one relation\n"); | ||
2097 | return 2; | ||
2098 | } | ||
2099 | /* | ||
2100 | johnpye | 219 | we want at least one variable in one obj or rel, |
2101 | or at least one boolean variable in one logrel | ||
2102 | */ | ||
2103 | aw0a | 1 | |
2104 | |||
2105 | /* calculate the number of free and incident boolean variables, logncol */ | ||
2106 | for (c=1,len = p_data->lrelinc; c <= len; c++) { | ||
2107 | dvip = SIP(gl_fetch(p_data->dvars,c)); | ||
2108 | if (!(dvip->u.dv.fixed)) p_data->logncol++; | ||
2109 | } | ||
2110 | |||
2111 | johnpye | 219 | |
2112 | aw0a | 1 | /* now malloc and build things, remember to punt the matrix soon */ |
2113 | /* remember we must NEVER free these things individually. */ | ||
2114 | |||
2115 | #define ALLOCVARDATA(p,n) (p) = (struct var_variable *)( \ | ||
2116 | ((n)>0) ? ascmalloc((n)*sizeof(struct var_variable)) : NULL) | ||
2117 | #define ALLOCRELDATA(p,n) (p) = (struct rel_relation *)( \ | ||
2118 | ((n)>0) ? ascmalloc((n)*sizeof(struct rel_relation)) : NULL) | ||
2119 | #define ALLOCDISVARDATA(p,n) (p) = (struct dis_discrete *)( \ | ||
2120 | ((n)>0) ? ascmalloc((n)*sizeof(struct dis_discrete)) : NULL) | ||
2121 | #define ALLOCLOGRELDATA(p,n) (p) = (struct logrel_relation *)( \ | ||
2122 | ((n)>0) ? ascmalloc((n)*sizeof(struct logrel_relation)) : NULL) | ||
2123 | #define ALLOCWHENDATA(p,n) (p) = (struct w_when *)( \ | ||
2124 | ((n)>0) ? ascmalloc((n)*sizeof(struct w_when)) : NULL) | ||
2125 | #define ALLOCBNDDATA(p,n) (p) = (struct bnd_boundary *)( \ | ||
2126 | ((n)>0) ? ascmalloc((n)*sizeof(struct bnd_boundary)) : NULL) | ||
2127 | ALLOCVARDATA(p_data->vardata,p_data->nv); | ||
2128 | ALLOCVARDATA(p_data->pardata,p_data->np); | ||
2129 | ALLOCVARDATA(p_data->undata,p_data->nu); | ||
2130 | ALLOCDISVARDATA(p_data->disdata,p_data->ndv); | ||
2131 | ALLOCDISVARDATA(p_data->undisdata,p_data->nud); | ||
2132 | ALLOCRELDATA(p_data->reldata,p_data->nr); | ||
2133 | ALLOCRELDATA(p_data->objdata,p_data->no); | ||
2134 | ALLOCRELDATA(p_data->condata,p_data->nc); | ||
2135 | ALLOCLOGRELDATA(p_data->lrdata,p_data->nl); | ||
2136 | ALLOCLOGRELDATA(p_data->logcondata,p_data->ncl); | ||
2137 | ALLOCWHENDATA(p_data->whendata,p_data->nw); | ||
2138 | ALLOCBNDDATA(p_data->bnddata,p_data->nc+p_data->ncl); | ||
2139 | |||
2140 | #define ALLOCVARLIST(p,n) (p) = (struct var_variable **)( \ | ||
2141 | ((n)>0) ? ascmalloc((n)*sizeof(struct var_variable *)) : NULL) | ||
2142 | #define ALLOCRELLIST(p,n) (p) = (struct rel_relation **)( \ | ||
2143 | ((n)>0) ? ascmalloc((n)*sizeof(struct rel_relation *)) : NULL) | ||
2144 | #define ALLOCDISVARLIST(p,n) (p) = (struct dis_discrete **)( \ | ||
2145 | ((n)>0) ? ascmalloc((n)*sizeof(struct dis_discrete *)) : NULL) | ||
2146 | #define ALLOCLOGRELLIST(p,n) (p) = (struct logrel_relation **)( \ | ||
2147 | ((n)>0) ? ascmalloc((n)*sizeof(struct logrel_relation *)) : NULL) | ||
2148 | #define ALLOCWHENLIST(p,n) (p) = (struct w_when **)( \ | ||
2149 | ((n)>0) ? ascmalloc((n)*sizeof(struct w_when *)) : NULL) | ||
2150 | #define ALLOCBNDLIST(p,n) (p) = (struct bnd_boundary **)( \ | ||
2151 | ((n)>0) ? ascmalloc((n)*sizeof(struct bnd_boundary *)) : NULL) | ||
2152 | ALLOCVARLIST(p_data->mastervl,p_data->nv+1); | ||
2153 | ALLOCVARLIST(p_data->masterpl,p_data->np+1); | ||
2154 | ALLOCVARLIST(p_data->masterul,p_data->nu+1); | ||
2155 | ALLOCDISVARLIST(p_data->masterdl,p_data->ndv+1); | ||
2156 | ALLOCDISVARLIST(p_data->masterdul,p_data->nud+1); | ||
2157 | ALLOCRELLIST(p_data->masterrl,p_data->nr+1); | ||
2158 | ALLOCRELLIST(p_data->masterol,p_data->no+1); | ||
2159 | ALLOCRELLIST(p_data->mastercl,p_data->nc+1); | ||
2160 | ALLOCLOGRELLIST(p_data->masterll,p_data->nl+1); | ||
2161 | ALLOCLOGRELLIST(p_data->mastercll,p_data->ncl+1); | ||
2162 | ALLOCWHENLIST(p_data->masterwl,p_data->nw+1); | ||
2163 | ALLOCBNDLIST(p_data->masterbl,p_data->nc+p_data->ncl+1); | ||
2164 | ALLOCVARLIST(p_data->solvervl,p_data->nv+1); | ||
2165 | ALLOCVARLIST(p_data->solverpl,p_data->np+1); | ||
2166 | ALLOCVARLIST(p_data->solverul,p_data->nu+1); | ||
2167 | ALLOCDISVARLIST(p_data->solverdl,p_data->ndv+1); | ||
2168 | ALLOCDISVARLIST(p_data->solverdul,p_data->nud+1); | ||
2169 | ALLOCRELLIST(p_data->solverrl,p_data->nr+1); | ||
2170 | ALLOCRELLIST(p_data->solverol,p_data->no+1); | ||
2171 | ALLOCRELLIST(p_data->solvercl,p_data->nc+1); | ||
2172 | ALLOCLOGRELLIST(p_data->solverll,p_data->nl+1); | ||
2173 | ALLOCLOGRELLIST(p_data->solvercll,p_data->ncl+1); | ||
2174 | ALLOCWHENLIST(p_data->solverwl,p_data->nw+1); | ||
2175 | ALLOCBNDLIST(p_data->solverbl,p_data->nc+p_data->ncl+1); | ||
2176 | |||
2177 | ALLOCVARLIST(p_data->relincidence,p_data->nnztot+p_data->nnzobj + | ||
2178 | p_data->nnzcond); | ||
2179 | ALLOCDISVARLIST(p_data->logrelinciden,p_data->lrelincsize); | ||
2180 | #define CHECKPTRSIZE(n,p) if ((n)>0 && (p)==NULL) return 1 | ||
2181 | #define CHECKPTR(p) if ((p)==NULL) return 1 | ||
2182 | /* verify mem allocations. */ | ||
2183 | CHECKPTRSIZE(p_data->nv,p_data->vardata); | ||
2184 | CHECKPTRSIZE(p_data->np,p_data->pardata); | ||
2185 | CHECKPTRSIZE(p_data->nu,p_data->undata); | ||
2186 | CHECKPTRSIZE(p_data->ndv,p_data->disdata); | ||
2187 | CHECKPTRSIZE(p_data->nud,p_data->undisdata); | ||
2188 | CHECKPTRSIZE(p_data->nr,p_data->reldata); | ||
2189 | CHECKPTRSIZE(p_data->no,p_data->objdata); | ||
2190 | CHECKPTRSIZE(p_data->nc,p_data->condata); | ||
2191 | CHECKPTRSIZE(p_data->nl,p_data->lrdata); | ||
2192 | CHECKPTRSIZE(p_data->ncl,p_data->logcondata); | ||
2193 | CHECKPTRSIZE(p_data->nw,p_data->whendata); | ||
2194 | CHECKPTRSIZE(p_data->nc+p_data->ncl,p_data->bnddata); | ||
2195 | CHECKPTR(p_data->mastervl); | ||
2196 | CHECKPTR(p_data->masterpl); | ||
2197 | CHECKPTR(p_data->masterul); | ||
2198 | CHECKPTR(p_data->masterdl); | ||
2199 | CHECKPTR(p_data->masterdul); | ||
2200 | CHECKPTR(p_data->masterrl); | ||
2201 | CHECKPTR(p_data->masterol); | ||
2202 | CHECKPTR(p_data->mastercl); | ||
2203 | CHECKPTR(p_data->masterll); | ||
2204 | CHECKPTR(p_data->mastercll); | ||
2205 | CHECKPTR(p_data->masterwl); | ||
2206 | CHECKPTR(p_data->masterbl); | ||
2207 | CHECKPTR(p_data->solvervl); | ||
2208 | CHECKPTR(p_data->solverpl); | ||
2209 | CHECKPTR(p_data->solverul); | ||
2210 | CHECKPTR(p_data->solverdl); | ||
2211 | CHECKPTR(p_data->solverdul); | ||
2212 | CHECKPTR(p_data->solverrl); | ||
2213 | CHECKPTR(p_data->solverol); | ||
2214 | CHECKPTR(p_data->solvercl); | ||
2215 | CHECKPTR(p_data->solverll); | ||
2216 | CHECKPTR(p_data->solvercll); | ||
2217 | CHECKPTR(p_data->solverwl); | ||
2218 | CHECKPTR(p_data->solverbl); | ||
2219 | CHECKPTR(p_data->relincidence); | ||
2220 | CHECKPTRSIZE(p_data->lrelincsize,p_data->logrelinciden); | ||
2221 | p_data->relincsize = p_data->nnztot+p_data->nnzobj + p_data->nnzcond; | ||
2222 | p_data->relincinuse = 0; | ||
2223 | p_data->lrelincinuse = 0; | ||
2224 | johnpye | 669 | |
2225 | /*-------*/ | ||
2226 | johnpye | 190 | /* |
2227 | johnpye | 219 | for c in varlist copy vardata. remember gllist # from 1 and data from 0 |
2228 | */ | ||
2229 | johnpye | 190 | /* |
2230 | johnpye | 219 | for c in varlist set mastervl, solvervl pointer to point to data |
2231 | */ | ||
2232 | aw0a | 1 | vlen = gl_length(p_data->vars); |
2233 | for (v = 0; v < vlen; v++) { | ||
2234 | var = &(p_data->vardata[v]); | ||
2235 | vip = SIP(gl_fetch(p_data->vars,v+1)); | ||
2236 | vip->u.v.data = var; | ||
2237 | var_set_instance(var,vip->i); | ||
2238 | var_set_mindex(var,v); | ||
2239 | var_set_sindex(var,v); | ||
2240 | flags = 0; /* all init to FALSE */ | ||
2241 | /* turn on appropriate ones */ | ||
2242 | if (vip->u.v.incident) flags |= VAR_INCIDENT; | ||
2243 | if (vip->u.v.in_block) flags |= VAR_INBLOCK; | ||
2244 | if (vip->u.v.fixed) flags |= VAR_FIXED; | ||
2245 | if (!vip->u.v.basis) flags |= VAR_NONBASIC; | ||
2246 | if (vip->u.v.solvervar) flags |= VAR_SVAR; | ||
2247 | var_set_flags(var,flags); | ||
2248 | p_data->mastervl[v] = var; | ||
2249 | p_data->solvervl[v] = var; | ||
2250 | } | ||
2251 | p_data->mastervl[vlen] = NULL; /* terminator */ | ||
2252 | p_data->solvervl[vlen] = NULL; /* terminator */ | ||
2253 | johnpye | 190 | /* |
2254 | johnpye | 219 | for c in parlist copy pardata. remember gllist # from 1 and data from 0 |
2255 | for c in parlist set masterpl, solverpl pointer to point to data | ||
2256 | */ | ||
2257 | aw0a | 1 | vlen = gl_length(p_data->pars); |
2258 | for (v = 0; v < vlen; v++) { | ||
2259 | var = &(p_data->pardata[v]); | ||
2260 | vip = SIP(gl_fetch(p_data->pars,v+1)); | ||
2261 | vip->u.v.data = var; | ||
2262 | var_set_instance(var,vip->i); | ||
2263 | var_set_mindex(var,v); | ||
2264 | var_set_sindex(var,v); | ||
2265 | flags = 0; /* all init to FALSE */ | ||
2266 | /* turn on appropriate ones */ | ||
2267 | if (vip->u.v.incident) flags |= VAR_INCIDENT; | ||
2268 | if (vip->u.v.in_block) flags |= VAR_INBLOCK; | ||
2269 | if (vip->u.v.fixed) flags |= VAR_FIXED; | ||
2270 | if (vip->u.v.solvervar) flags |= VAR_SVAR; /* shouldn't this be here? */ | ||
2271 | var_set_flags(var,flags); | ||
2272 | p_data->masterpl[v] = var; | ||
2273 | p_data->solverpl[v] = var; | ||
2274 | } | ||
2275 | p_data->masterpl[vlen] = NULL; /* terminator */ | ||
2276 | p_data->solverpl[vlen] = NULL; /* terminator */ | ||
2277 | johnpye | 190 | /* |
2278 | johnpye | 219 | for c in unalist copy undata. remember gllist # from 1 and data from 0 |
2279 | for c in unalist set masterul, solverul pointer to point to data | ||
2280 | */ | ||
2281 | aw0a | 1 | vlen = gl_length(p_data->unas); |
2282 | for (v = 0; v < vlen; v++) { | ||
2283 | var = &(p_data->undata[v]); | ||
2284 | vip = SIP(gl_fetch(p_data->unas,v+1)); | ||
2285 | vip->u.v.data = var; | ||
2286 | var_set_instance(var,vip->i); | ||
2287 | var_set_mindex(var,v); | ||
2288 | var_set_sindex(var,v); | ||
2289 | flags = 0; /* all init to FALSE */ | ||
2290 | /* turn on appropriate ones */ | ||
2291 | if (vip->u.v.incident) flags |= VAR_INCIDENT; | ||
2292 | if (vip->u.v.fixed) flags |= VAR_FIXED; | ||
2293 | if (vip->u.v.solvervar) flags |= VAR_SVAR; | ||
2294 | /* others may be appropriate (PVAR) */ | ||
2295 | var_set_flags(var,flags); | ||
2296 | p_data->masterul[v] = var; | ||
2297 | p_data->solverul[v] = var; | ||
2298 | } | ||
2299 | p_data->masterul[vlen] = NULL; /* terminator */ | ||
2300 | p_data->solverul[vlen] = NULL; /* terminator */ | ||
2301 | johnpye | 219 | |
2302 | johnpye | 190 | /* |
2303 | johnpye | 219 | process the constraining relations |
2304 | for v in rellist copy reldata and fix extrels. | ||
2305 | */ | ||
2306 | aw0a | 1 | vlen = gl_length(p_data->rels); |
2307 | for (v = 0; v < vlen; v++) { | ||
2308 | rel = &(p_data->reldata[v]); | ||
2309 | rip = SIP(gl_fetch(p_data->rels,v+1)); | ||
2310 | rel = rel_create(rip->i,rel); | ||
2311 | rip->u.r.data = rel; | ||
2312 | rel_set_mindex(rel,v); | ||
2313 | rel_set_sindex(rel,v); | ||
2314 | rel_set_model(rel,rip->u.r.model-1); | ||
2315 | /* here set up the var list */ | ||
2316 | gut = GetInstanceRelationOnly(rip->i); | ||
2317 | assert(gut!=NULL); | ||
2318 | len = NumberVariables(gut); | ||
2319 | if (len > 0) { | ||
2320 | incidence = get_incidence_space(len,p_data); | ||
2321 | for( c = 0; c < len; c++ ) { | ||
2322 | i = RelationVariable(gut,c+1); | ||
2323 | incidence[c] = SIP(GetInterfacePtr(i))->u.v.data; | ||
2324 | } | ||
2325 | rel_set_incidences(rel,len,incidence); | ||
2326 | } else { | ||
2327 | rel_set_incidences(rel,0,NULL); | ||
2328 | } | ||
2329 | johnpye | 709 | if(rel_extnodeinfo(rel)) { |
2330 | aw0a | 1 | cache = CheckIfCacheExists(rip->i,&nodestamp,p_data); |
2331 | if (cache) { | ||
2332 | rel_set_extcache(rel,cache); | ||
2333 | johnpye | 709 | }else{ |
2334 | johnpye | 710 | CONSOLE_DEBUG("rip = %p, rip->i = %p",rip,rip->i); |
2335 | aw0a | 1 | cache = CreateCacheFromInstance(rip->i); |
2336 | johnpye | 710 | CONSOLE_DEBUG("cache = %p",cache); |
2337 | aw0a | 1 | gl_append_ptr(p_data->extrels,(POINTER)cache); |
2338 | rel_set_extcache(rel,cache); | ||
2339 | } | ||
2340 | } | ||
2341 | flags = 0; /* all init to FALSE */ | ||
2342 | /* TURN ON APPROPRIATE ONES */ | ||
2343 | if (rip->u.r.included) flags |= (REL_INCLUDED | REL_INBLOCK); | ||
2344 | if (rip->u.r.ext) flags |= REL_BLACKBOX; | ||
2345 | if (rip->u.r.active) flags |= ( REL_ACTIVE | REL_INVARIANT); | ||
2346 | if (rip->u.r.inwhen) flags |= REL_INWHEN; | ||
2347 | if ( RelationRelop(GetInstanceRelationOnly(rip->i)) == e_equal ) { | ||
2348 | flags |= REL_EQUALITY; | ||
2349 | } | ||
2350 | rel_set_flags(rel,flags); | ||
2351 | /* for c in rellist set masterrl, solverrl pointer to point to data */ | ||
2352 | p_data->masterrl[v] = rel; | ||
2353 | p_data->solverrl[v] = rel; | ||
2354 | } | ||
2355 | p_data->masterrl[vlen] = NULL; /* terminator */ | ||
2356 | p_data->solverrl[vlen] = NULL; /* terminator */ | ||
2357 | |||
2358 | /* cobble together external rel list */ | ||
2359 | len = gl_length(p_data->extrels); | ||
2360 | p_data->erlist = (struct ExtRelCache **) | ||
2361 | ascmalloc((1+len)*sizeof(struct ExtRelCache *)); | ||
2362 | if (p_data->erlist==NULL) return 1; | ||
2363 | for (c=1; c <= len; c++) { | ||
2364 | p_data->erlist[c-1] = (struct ExtRelCache *)gl_fetch(p_data->extrels,c); | ||
2365 | } | ||
2366 | p_data->erlist[len] = NULL; /* terminator */ | ||
2367 | johnpye | 219 | |
2368 | aw0a | 1 | /* |
2369 | johnpye | 219 | for c in objlist copy objdata. |
2370 | for c in objlist set masterrl, solverrl pointer to point to data. | ||
2371 | */ | ||
2372 | johnpye | 190 | /* |
2373 | johnpye | 219 | process the objective relations |
2374 | for v in objlist copy objdata | ||
2375 | */ | ||
2376 | aw0a | 1 | vlen = gl_length(p_data->objrels); |
2377 | found = 0; | ||
2378 | for (v = 0; v < vlen; v++) { | ||
2379 | rel = &(p_data->objdata[v]); | ||
2380 | rip = SIP(gl_fetch(p_data->objrels,v+1)); | ||
2381 | rel = rel_create(rip->i,rel); | ||
2382 | rip->u.r.data = rel; | ||
2383 | rel_set_mindex(rel,v); | ||
2384 | rel_set_sindex(rel,v); | ||
2385 | rel_set_model(rel,rip->u.r.model-1); | ||
2386 | /* here set up the var list */ | ||
2387 | gut = GetInstanceRelationOnly(rip->i); | ||
2388 | assert(gut!=NULL); | ||
2389 | len = NumberVariables(gut); | ||
2390 | if (len > 0) { | ||
2391 | incidence = get_incidence_space(len,p_data); | ||
2392 | for( c = 0; c < len; c++ ) { | ||
2393 | i = RelationVariable(gut,c+1); | ||
2394 | incidence[c] = SIP(GetInterfacePtr(i))->u.v.data; | ||
2395 | } | ||
2396 | rel_set_incidences(rel,len,incidence); | ||
2397 | } else { | ||
2398 | rel_set_incidences(rel,0,NULL); | ||
2399 | } | ||
2400 | /* black box objectives not supported. skip it */ | ||
2401 | flags = 0; /* all init to FALSE */ | ||
2402 | /* TURN ON APPROPRIATE ONES */ | ||
2403 | if (rip->u.r.included) { | ||
2404 | flags |= (REL_INCLUDED | REL_INBLOCK | REL_ACTIVE); | ||
2405 | } | ||
2406 | if (rip->u.r.obj < 0) flags |= REL_OBJNEGATE; | ||
2407 | rel_set_flags(rel,flags); | ||
2408 | /* for c in objrellist set masterol, solverol pointer to point to data */ | ||
2409 | p_data->masterol[v] = rel; | ||
2410 | p_data->solverol[v] = rel; | ||
2411 | /* set objective to first included objective on list */ | ||
2412 | if (!found && (rip->u.r.included)) { | ||
2413 | p_data->obj = rel; | ||
2414 | found = 1; | ||
2415 | } | ||
2416 | } | ||
2417 | p_data->masterol[vlen] = NULL; /* terminator */ | ||
2418 | p_data->solverol[vlen] = NULL; /* terminator */ | ||
2419 | |||
2420 | johnpye | 190 | /* |
2421 | johnpye | 219 | process the conditional relations |
2422 | for v in cndlist copy conddata . | ||
2423 | */ | ||
2424 | aw0a | 1 | vlen = gl_length(p_data->cnds); |
2425 | for (v = 0; v < vlen; v++) { | ||
2426 | rel = &(p_data->condata[v]); | ||
2427 | rip = SIP(gl_fetch(p_data->cnds,v+1)); | ||
2428 | rel = rel_create(rip->i,rel); | ||
2429 | rip->u.r.data = rel; | ||
2430 | rel_set_mindex(rel,v); | ||
2431 | rel_set_sindex(rel,v); | ||
2432 | rel_set_model(rel,rip->u.r.model-1); | ||
2433 | gut = GetInstanceRelationOnly(rip->i); | ||
2434 | assert(gut!=NULL); | ||
2435 | len = NumberVariables(gut); | ||
2436 | if (len > 0) { | ||
2437 | incidence = get_incidence_space(len,p_data); | ||
2438 | for( c = 0; c < len; c++ ) { | ||
2439 | i = RelationVariable(gut,c+1); | ||
2440 | incidence[c] = SIP(GetInterfacePtr(i))->u.v.data; | ||