Parent Directory
|
Revision Log
Setting up web subdirectory in repository
1 | aw0a | 1 | /* |
2 | * Conditional Modeling Solver | ||
3 | * by Vicente Rico-Ramirez | ||
4 | * Version: $Revision: 1.22 $ | ||
5 | * Version control file: $RCSfile: slv9.c,v $ | ||
6 | * Date last modified: $Date: 2000/01/25 02:27:58 $ | ||
7 | * Last modified by: $Author: ballan $ | ||
8 | * | ||
9 | * This file is part of the SLV solver. | ||
10 | * | ||
11 | * The SLV solver is free software; you can redistribute | ||
12 | * it and/or modify it under the terms of the GNU General Public License as | ||
13 | * published by the Free Software Foundation; either version 2 of the | ||
14 | * License, or (at your option) any later version. | ||
15 | * | ||
16 | * The SLV solver is distributed in hope that it will be | ||
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | * General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with the program; if not, write to the Free Software Foundation, | ||
23 | * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named | ||
24 | * COPYING. COPYING is found in ../compiler. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <math.h> | ||
29 | #include "utilities/ascConfig.h" | ||
30 | #include "utilities/ascSignal.h" | ||
31 | #include "utilities/ascMalloc.h" | ||
32 | #include "general/tm_time.h" | ||
33 | #include "utilities/mem.h" | ||
34 | #include "compiler/compiler.h" | ||
35 | #include "compiler/instance_enum.h" | ||
36 | #include "general/list.h" | ||
37 | #include "compiler/fractions.h" | ||
38 | #include "compiler/dimen.h" | ||
39 | #include "compiler/functype.h" | ||
40 | #include "compiler/func.h" | ||
41 | #include "solver/mtx.h" | ||
42 | #include "solver/mtx_reorder.h" | ||
43 | #include "solver/linsol.h" | ||
44 | #include "solver/linsolqr.h" | ||
45 | #include "solver/slv_types.h" | ||
46 | #include "solver/var.h" | ||
47 | #include "solver/rel.h" | ||
48 | #include "solver/discrete.h" | ||
49 | #include "solver/conditional.h" | ||
50 | #include "solver/logrel.h" | ||
51 | #include "solver/bnd.h" | ||
52 | #include "solver/calc.h" | ||
53 | #include "solver/relman.h" | ||
54 | #include "solver/logrelman.h" | ||
55 | #include "solver/bndman.h" | ||
56 | #include "solver/cond_config.h" | ||
57 | #include "solver/slv_common.h" | ||
58 | #include "solver/slv_client.h" | ||
59 | #include "solver/conopt.h" | ||
60 | #include "solver/slv9.h" | ||
61 | #include "solver/slv_stdcalls.h" | ||
62 | #include "solver/slvDOF.h" | ||
63 | |||
64 | |||
65 | |||
66 | #if !defined(STATIC_CMSLV) && !defined(DYNAMIC_CMSLV) | ||
67 | int slv9_register(SlvFunctionsT *f) | ||
68 | { | ||
69 | (void)f; /* stop gcc whining about unused parameter */ | ||
70 | |||
71 | FPRINTF(ASCERR,"CMSlv not compiled in this ASCEND IV.\n"); | ||
72 | return 1; | ||
73 | } | ||
74 | #else /* either STATIC_CMSLV or DYNAMIC_CMSLV is defined */ | ||
75 | |||
76 | #ifdef DYNAMIC_CMSLV | ||
77 | /* do dynamic loading stuff. yeah, right */ | ||
78 | |||
79 | #else /* following is used if STATIC_CMSLV is defined */ | ||
80 | |||
81 | |||
82 | /* | ||
83 | * definitions to enable/disable the output of partial results in | ||
84 | * the solution of a problem | ||
85 | */ | ||
86 | #define DEBUG FALSE | ||
87 | #define SHOW_LOGICAL_DETAILS FALSE | ||
88 | #define SHOW_BOUNDARY_ANALYSIS_DETAILS FALSE | ||
89 | #define SHOW_OPTIMIZATION_DETAILS FALSE | ||
90 | #define SHOW_BISECTION_DETAILS FALSE | ||
91 | #define SHOW_LINEAR_SEARCH_DETAILS FALSE | ||
92 | #define SHOW_LAGRANGE_DETAILS FALSE | ||
93 | #define DEBUG_CONSISTENCY FALSE | ||
94 | #define TEST_CONSISTENCY FALSE | ||
95 | #define USE_CONSISTENCY FALSE | ||
96 | |||
97 | /* | ||
98 | * Is CONOPT available ? | ||
99 | */ | ||
100 | #if defined(STATIC_CONOPT) | ||
101 | |||
102 | #define CONOPT_ACTIVE TRUE | ||
103 | #else /* defined(STATIC_CONOPT) */ | ||
104 | #define CONOPT_ACTIVE FALSE | ||
105 | #endif /* defined(STATIC_CONOPT) */ | ||
106 | |||
107 | /* | ||
108 | * system definitions | ||
109 | */ | ||
110 | #define SLV9(s) ((slv9_system_t)(s)) | ||
111 | #define SERVER (sys->slv) | ||
112 | #define slv9_PA_SIZE 26 /* MUST INCREMENT WHEN ADDING PARAMETERS */ | ||
113 | #define LOGSOLVER_OPTION_PTR (sys->parm_array[0]) | ||
114 | #define LOGSOLVER_OPTION ((*(char **)LOGSOLVER_OPTION_PTR)) | ||
115 | #define NONLISOLVER_OPTION_PTR (sys->parm_array[1]) | ||
116 | #define NONLISOLVER_OPTION ((*(char **)NONLISOLVER_OPTION_PTR)) | ||
117 | #define OPTSOLVER_OPTION_PTR (sys->parm_array[2]) | ||
118 | #define OPTSOLVER_OPTION ((*(char **)OPTSOLVER_OPTION_PTR)) | ||
119 | #define TIME_LIMIT_PTR (sys->parm_array[3]) | ||
120 | #define TIME_LIMIT ((*(int32 *)TIME_LIMIT_PTR)) | ||
121 | #define ITER_LIMIT_PTR (sys->parm_array[4]) | ||
122 | #define ITER_LIMIT ((*(int32 *)ITER_LIMIT_PTR)) | ||
123 | #define ITER_BIS_LIMIT_PTR (sys->parm_array[5]) | ||
124 | #define ITER_BIS_LIMIT ((*(int32 *)ITER_BIS_LIMIT_PTR)) | ||
125 | #define TOO_SMALL_PTR (sys->parm_array[6]) | ||
126 | #define TOO_SMALL ((*(real64 *)TOO_SMALL_PTR)) | ||
127 | #define LINEAR_SEARCH_FACTOR_PTR (sys->parm_array[7]) | ||
128 | #define LINEAR_SEARCH_FACTOR ((*(real64 *)LINEAR_SEARCH_FACTOR_PTR)) | ||
129 | #define SHOW_MORE_IMPT_PTR (sys->parm_array[8]) | ||
130 | #define SHOW_MORE_IMPT ((*(int32 *)SHOW_MORE_IMPT_PTR)) | ||
131 | #define SHOW_LESS_IMPT_PTR (sys->parm_array[9]) | ||
132 | #define SHOW_LESS_IMPT ((*(int32 *)SHOW_LESS_IMPT_PTR)) | ||
133 | #define AUTO_RESOLVE_PTR (sys->parm_array[10]) | ||
134 | #define AUTO_RESOLVE ((*(int32 *)AUTO_RESOLVE_PTR)) | ||
135 | #define UNDEFINED_PTR (sys->parm_array[11]) | ||
136 | #define UNDEFINED ((*(real64 *)UNDEFINED_PTR)) | ||
137 | #define DOMLIM_PTR (sys->parm_array[12]) | ||
138 | #define DOMLIM ((*(int32 *)DOMLIM_PTR)) | ||
139 | #define OPT_ITER_LIMIT_PTR (sys->parm_array[13]) | ||
140 | #define OPT_ITER_LIMIT ((*(int32 *)OPT_ITER_LIMIT_PTR)) | ||
141 | #define INFINITY_PTR (sys->parm_array[14]) | ||
142 | #define INFINITY ((*(real64 *)INFINITY_PTR)) | ||
143 | #define OBJ_TOL_PTR (sys->parm_array[15]) | ||
144 | #define OBJ_TOL ((*(real64 *)OBJ_TOL_PTR)) | ||
145 | #define RTMAXJ_PTR (sys->parm_array[16]) | ||
146 | #define RTMAXJ ((*(real64 *)RTMAXJ_PTR)) | ||
147 | #define RHO_PTR (sys->parm_array[17]) | ||
148 | #define RHO ((*(real64 *)RHO_PTR)) | ||
149 | |||
150 | |||
151 | /* | ||
152 | * Client tokens of the different solvers: Conditional, Optimizer, | ||
153 | * Nonlinear, Logical. We will switch from one client token to | ||
154 | * another as the solution process occurs. | ||
155 | */ | ||
156 | #define NUMBER_OF_CLIENTS 4 | ||
157 | SlvClientToken token[NUMBER_OF_CLIENTS]; | ||
158 | int32 solver_index[NUMBER_OF_CLIENTS]; | ||
159 | |||
160 | /* | ||
161 | * indeces in arrays token and solver_index | ||
162 | */ | ||
163 | #define CONDITIONAL_SOLVER 0 | ||
164 | #define LOGICAL_SOLVER 1 | ||
165 | #define NONLINEAR_SOLVER 2 | ||
166 | #define OPTIMIZATION_SOLVER 3 | ||
167 | |||
168 | /* | ||
169 | * Do we have an optimization problem ?. Global variable initialized | ||
170 | * to 0 (not optimizing) | ||
171 | */ | ||
172 | static int32 g_optimizing = 0; | ||
173 | |||
174 | #if USE_CONSISTENCY | ||
175 | /* | ||
176 | * number of subregion visited during the solution of the conditional | ||
177 | * model. | ||
178 | */ | ||
179 | static int32 g_subregions_visited; | ||
180 | |||
181 | #endif /* USE_CONSISTENCY */ | ||
182 | |||
183 | |||
184 | /* auxiliar structures */ | ||
185 | struct boolean_values { | ||
186 | int32 *pre_val; /* previous values of dis_discrete */ | ||
187 | int32 *cur_val; /* current values of dis_discrete */ | ||
188 | }; | ||
189 | |||
190 | struct matching_cases { | ||
191 | int32 *case_list; /* list of cases */ | ||
192 | int32 ncases; /* number of cases */ | ||
193 | int32 diff_subregion; /* subregion ? */ | ||
194 | }; | ||
195 | |||
196 | struct real_values { | ||
197 | real64 *pre_values; /* previous values of var_variables */ | ||
198 | real64 *cur_values; /* current values of var_variables */ | ||
199 | }; | ||
200 | |||
201 | struct opt_vector { | ||
202 | real64 *element; /* elements in colum of matrix */ | ||
203 | }; | ||
204 | |||
205 | struct opt_matrix { | ||
206 | struct opt_vector *cols; /* columns in matrix */ | ||
207 | }; | ||
208 | |||
209 | struct subregionID { | ||
210 | unsigned long ID_number; | ||
211 | int32 *bool_values; | ||
212 | }; | ||
213 | |||
214 | struct ds_subregion_list { | ||
215 | int32 length,capacity; | ||
216 | struct subregionID *sub_stack; | ||
217 | }; | ||
218 | |||
219 | struct ds_subregions_visited { | ||
220 | int32 length,capacity; | ||
221 | unsigned long *visited; | ||
222 | }; | ||
223 | |||
224 | /* | ||
225 | * This solver's data structure (CMSlv) | ||
226 | */ | ||
227 | struct slv9_system_structure { | ||
228 | |||
229 | /* | ||
230 | * Problem definition | ||
231 | */ | ||
232 | slv_system_t slv; /* slv_system_t back-link */ | ||
233 | |||
234 | struct rel_relation *obj; /* Objective function: NULL = none */ | ||
235 | struct var_variable **vlist; /* Variable list (NULL terminated) */ | ||
236 | struct rel_relation **rlist; /* Relation list (NULL terminated) */ | ||
237 | struct dis_discrete **dvlist; /* Dis vars list (NULL terminated) */ | ||
238 | struct logrel_relation **lrlist; /* Logrels list(NULL terminated)*/ | ||
239 | struct bnd_boundary **blist; /* Variable list (NULL terminated) */ | ||
240 | struct var_variable **mvlist; | ||
241 | struct dis_discrete **mdvlist; /* We will not touch the masters list, | ||
242 | * but they can provide very useful | ||
243 | * information to the conditional | ||
244 | * solver since the master index does | ||
245 | * not change. | ||
246 | */ | ||
247 | |||
248 | /* | ||
249 | * for optimization at boundaries | ||
250 | */ | ||
251 | struct opt_matrix *coeff_matrix; /* Matrix for optimization problem */ | ||
252 | struct opt_vector *opt_var_values; /* Values of vars in opt problem */ | ||
253 | int32 subregions; /* number of subregions at cur bnd */ | ||
254 | mtx_matrix_t lin_mtx; /* Matrix to define the linear system | ||
255 | * for calculation of the lagrange | ||
256 | * multipliers | ||
257 | */ | ||
258 | /* | ||
259 | * For search consistency analysis | ||
260 | */ | ||
261 | struct ds_subregion_list subregion_list; | ||
262 | /* | ||
263 | * Information about the subregions | ||
264 | * visited during the solution of the | ||
265 | * conditional model | ||
266 | */ | ||
267 | struct ds_subregions_visited subregions_visited; | ||
268 | /* | ||
269 | * ID number of the subregions | ||
270 | * visited | ||
271 | */ | ||
272 | int32 *bool_mindex; /* master indices of boolean vars in | ||
273 | * the problem associated with WHENs | ||
274 | */ | ||
275 | int32 need_consistency_analysis; /* Is the consistency analysis needed */ | ||
276 | |||
277 | |||
278 | /* | ||
279 | * Solver information | ||
280 | */ | ||
281 | int32 integrity; /* Has the system been created ? */ | ||
282 | int32 presolved; /* Has the system been presolved ? */ | ||
283 | slv_parameters_t p; /* Parameters */ | ||
284 | slv_status_t s; /* Status (as of iteration end) */ | ||
285 | int32 cap; /* Order of matrix/vectors */ | ||
286 | int32 rank; /* Symbolic rank of problem */ | ||
287 | int32 vused; /* Free and incident variables */ | ||
288 | int32 vtot; /* length of varlist */ | ||
289 | int32 mvtot; /* length of master varlist */ | ||
290 | int32 rused; /* Included relations */ | ||
291 | int32 rtot; /* length of rellist */ | ||
292 | real64 clock; /* CPU time */ | ||
293 | int32 nliter; /* iterations in nonlinear solver */ | ||
294 | |||
295 | void *parm_array[slv9_PA_SIZE]; /* array of pointers to param values */ | ||
296 | struct slv_parameter pa[slv9_PA_SIZE]; /* &pa[0] => sys->p.parms */ | ||
297 | |||
298 | /* | ||
299 | * Data for optimizer at boundaries (CONOPT) | ||
300 | */ | ||
301 | struct conopt_data con; | ||
302 | }; | ||
303 | |||
304 | |||
305 | /* | ||
306 | * Integrity checks | ||
307 | * ---------------- | ||
308 | * check_system(sys) | ||
309 | */ | ||
310 | |||
311 | #define OK ((int32)813029392) | ||
312 | #define DESTROYED ((int32)103289182) | ||
313 | |||
314 | /* | ||
315 | * Checks sys for NULL and for integrity. | ||
316 | */ | ||
317 | static int check_system(slv9_system_t sys) | ||
318 | { | ||
319 | if( sys == NULL ) { | ||
320 | FPRINTF(ASCERR,"ERROR: (slv9) check_system\n"); | ||
321 | FPRINTF(ASCERR," NULL system handle.\n"); | ||
322 | return 1; | ||
323 | } | ||
324 | |||
325 | switch( sys->integrity ) { | ||
326 | case OK: | ||
327 | return 0; | ||
328 | case DESTROYED: | ||
329 | FPRINTF(ASCERR,"ERROR: (slv9) check_system\n"); | ||
330 | FPRINTF(ASCERR," System was recently destroyed.\n"); | ||
331 | return 1; | ||
332 | default: | ||
333 | FPRINTF(ASCERR,"ERROR: (slv9) check_system\n"); | ||
334 | FPRINTF(ASCERR," System reused or never allocated.\n"); | ||
335 | return 1; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | |||
340 | /* | ||
341 | * General input/output routines | ||
342 | * ----------------------------- | ||
343 | * print_var_name(out,sys,var) | ||
344 | */ | ||
345 | #define print_var_name(a,b,c) slv_print_var_name((a),(b)->slv,(c)) | ||
346 | |||
347 | |||
348 | /* | ||
349 | * Array operations | ||
350 | * ---------------- | ||
351 | * destroy_array(p) | ||
352 | * create_array(len,type) | ||
353 | * create_zero_array(len,type) | ||
354 | */ | ||
355 | #define destroy_array(p) \ | ||
356 | if( (p) != NULL ) ascfree((p)) | ||
357 | #define create_array(len,type) \ | ||
358 | ((len) > 0 ? (type *)ascmalloc((len)*sizeof(type)) : NULL) | ||
359 | #define create_zero_array(len,type) \ | ||
360 | ((len) > 0 ? (type *)asccalloc((len),sizeof(type)) : NULL) | ||
361 | |||
362 | |||
363 | /* | ||
364 | * Search Consistency Analysis during iterative process | ||
365 | * --------------------------------------------------------- | ||
366 | * The caller of this functions is in charge of | ||
367 | * defining the extension of the analysis by passing an integer | ||
368 | * which will tell us if 1) the analysis consider only the current | ||
369 | * and the previous alternatives or 2) the analysis consider all the | ||
370 | * alternatives visited at current the state of the solution | ||
371 | * algorithm. | ||
372 | */ | ||
373 | |||
374 | /* | ||
375 | * Handling dynamic allocation of the structural information | ||
376 | */ | ||
377 | |||
378 | #define alloc_array(nelts,type) \ | ||
379 | ((nelts) > 0 ? (type *)ascmalloc((nelts)*sizeof(type)) : NULL) | ||
380 | #define copy_nums(from,too,nnums) \ | ||
381 | asc_memcpy((from),(too),(nnums)*sizeof(int32)) | ||
382 | #define copy_subregions(from,too,nsubs) \ | ||
383 | asc_memcpy((from),(too),(nsubs)*sizeof(struct subregionID)) | ||
384 | |||
385 | /* | ||
386 | * Appends the subregion_visited into the list | ||
387 | */ | ||
388 | static void append_subregion(struct ds_subregion_list *sl, | ||
389 | struct subregionID sub) | ||
390 | { | ||
391 | if( sl->length == sl->capacity ) { | ||
392 | int32 newcap; | ||
393 | struct subregionID *newlist; | ||
394 | |||
395 | newcap = sl->capacity + 10; | ||
396 | newlist = alloc_array(newcap,struct subregionID); | ||
397 | copy_subregions((char *)sl->sub_stack,(char *)newlist,sl->length); | ||
398 | if( sl->sub_stack != NULL ) { | ||
399 | ascfree(sl->sub_stack); | ||
400 | } | ||
401 | sl->sub_stack = newlist; | ||
402 | sl->capacity = newcap; | ||
403 | } | ||
404 | |||
405 | sl->sub_stack[sl->length++] = sub; | ||
406 | } | ||
407 | |||
408 | /* | ||
409 | * Appends the subregion_visited into the list | ||
410 | */ | ||
411 | static void append_sub_visited(struct ds_subregions_visited *sv, | ||
412 | unsigned long sub_visited) | ||
413 | { | ||
414 | if( sv->length == sv->capacity ) { | ||
415 | int32 newcap; | ||
416 | unsigned long *newlist; | ||
417 | |||
418 | newcap = sv->capacity + 10; | ||
419 | newlist = alloc_array(newcap,unsigned long); | ||
420 | copy_nums((char *)sv->visited,(char *)newlist,sv->length); | ||
421 | if( sv->visited != NULL ) { | ||
422 | ascfree(sv->visited); | ||
423 | } | ||
424 | sv->visited = newlist; | ||
425 | sv->capacity = newcap; | ||
426 | } | ||
427 | |||
428 | sv->visited[sv->length++] = sub_visited; | ||
429 | } | ||
430 | |||
431 | static unsigned long powoftwo (int32 expo) | ||
432 | { | ||
433 | unsigned long val; | ||
434 | int32 c; | ||
435 | |||
436 | val = 1; | ||
437 | for (c=1; c<= expo; c++) { | ||
438 | val = val * 2; | ||
439 | } | ||
440 | |||
441 | return val; | ||
442 | } | ||
443 | |||
444 | |||
445 | /* | ||
446 | * Storage information (boolean values) about a subregion so that | ||
447 | * we can visit it later for interactive strucutral analysis | ||
448 | */ | ||
449 | static void ID_and_storage_subregion_information(slv_system_t server, | ||
450 | SlvClientToken asys) | ||
451 | { | ||
452 | slv9_system_t sys; | ||
453 | struct dis_discrete **bvlist; | ||
454 | struct dis_discrete *cur_dis; | ||
455 | struct ds_subregion_list *sl; | ||
456 | struct ds_subregions_visited *sv; | ||
457 | struct subregionID *sub; | ||
458 | dis_filter_t dfilter; | ||
459 | unsigned long val, visited, sID; | ||
460 | int32 d, numdvs, numdvf, dcount; | ||
461 | int32 len, s, found; | ||
462 | |||
463 | sys = SLV9(asys); | ||
464 | check_system(sys); | ||
465 | |||
466 | bvlist = sys->mdvlist; | ||
467 | if(bvlist == NULL ) { | ||
468 | FPRINTF(ASCERR,"ERROR: ID_and_storage_subregion_information.\n"); | ||
469 | FPRINTF(ASCERR," Master discrete var list was never set.\n"); | ||
470 | return; | ||
471 | } | ||
472 | numdvs = slv_get_num_master_dvars(server); | ||
473 | |||
474 | dfilter.matchbits = (DIS_INWHEN | DIS_BOOLEAN); | ||
475 | dfilter.matchvalue = (DIS_INWHEN | DIS_BOOLEAN); | ||
476 | numdvf = slv_count_master_dvars(server,&dfilter); | ||
477 | |||
478 | if (numdvf > 0) { | ||
479 | sub = (struct subregionID *)(ascmalloc(sizeof(struct subregionID))); | ||
480 | sub->bool_values = (int32 *)(ascmalloc(numdvf*sizeof(int32))); | ||
481 | } else { | ||
482 | FPRINTF(ASCERR,"ERROR: ID_and_storage_subregion_information.\n"); | ||
483 | FPRINTF(ASCERR," No boolean variables in the problem \n"); | ||
484 | return; | ||
485 | } | ||
486 | |||
487 | dcount = 0; | ||
488 | val = 0; | ||
489 | for (d=0; d<numdvs; d++) { | ||
490 | cur_dis = bvlist[d]; | ||
491 | if (dis_apply_filter(cur_dis,&dfilter)) { | ||
492 | sub->bool_values[dcount] = dis_value(cur_dis); | ||
493 | dcount++; | ||
494 | if (sub->bool_values[dcount - 1] == 1) { | ||
495 | val = val + powoftwo(numdvf - dcount); | ||
496 | } | ||
497 | } | ||
498 | } | ||
499 | if ( (val == 0 ) && (numdvf > 0) ) { | ||
500 | val = powoftwo(numdvf); | ||
501 | } | ||
502 | sub->ID_number = val; | ||
503 | #if DEBUG_CONSISTENCY | ||
504 | FPRINTF(ASCERR,"ID of alternative is %ul \n", val); | ||
505 | #endif /* DEBUG_CONSISTENCY */ | ||
506 | visited = val; | ||
507 | found = 0; | ||
508 | len = sys->subregions_visited.length; | ||
509 | if (len > 0) { | ||
510 | for (s=0; s<len; s++) { | ||
511 | sID = sys->subregions_visited.visited[s]; | ||
512 | if (visited == sID) { | ||
513 | found = 1; | ||
514 | break; | ||
515 | } | ||
516 | } | ||
517 | } | ||
518 | |||
519 | sv = &(sys->subregions_visited); | ||
520 | append_sub_visited(sv,visited); | ||
521 | |||
522 | if (found == 0) { | ||
523 | #if DEBUG_CONSISTENCY | ||
524 | FPRINTF(ASCERR,"Saving alternative\n"); | ||
525 | #endif /* DEBUG_CONSISTENCY */ | ||
526 | sl = &(sys->subregion_list); | ||
527 | append_subregion(sl,(*sub)); | ||
528 | } else { | ||
529 | destroy_array(sub->bool_values); | ||
530 | ascfree(sub); | ||
531 | } | ||
532 | |||
533 | return; | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Destroys subregion information | ||
538 | */ | ||
539 | static void destroy_subregion_information(SlvClientToken asys) | ||
540 | { | ||
541 | slv9_system_t sys; | ||
542 | struct subregionID *sub; | ||
543 | int32 lens, s; | ||
544 | |||
545 | sys = SLV9(asys); | ||
546 | check_system(sys); | ||
547 | |||
548 | if (sys->subregions_visited.visited != NULL) { | ||
549 | destroy_array(sys->subregions_visited.visited); | ||
550 | } | ||
551 | |||
552 | lens = sys->subregion_list.length; | ||
553 | if (lens != 0) { | ||
554 | for (s=0; s<lens; s++) { | ||
555 | sub = &(sys->subregion_list.sub_stack[s]); | ||
556 | if (sub->bool_values != NULL) { | ||
557 | destroy_array(sub->bool_values); | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | |||
562 | if (sys->subregion_list.sub_stack != NULL) { | ||
563 | destroy_array(sys->subregion_list.sub_stack); | ||
564 | } | ||
565 | |||
566 | if (sys->bool_mindex != NULL) { | ||
567 | destroy_array(sys->bool_mindex); | ||
568 | } | ||
569 | } | ||
570 | |||
571 | |||
572 | /* | ||
573 | * Storing original values of boolean variables | ||
574 | */ | ||
575 | static void store_original_bool_values(struct gl_list_t *bollist, | ||
576 | struct boolean_values *bval) | ||
577 | { | ||
578 | struct dis_discrete *dvar; | ||
579 | int32 d, dlen; | ||
580 | |||
581 | dlen = gl_length(bollist); | ||
582 | bval->pre_val = create_array(dlen,int32); | ||
583 | bval->cur_val = create_array(dlen,int32); | ||
584 | for (d=1; d<=dlen; d++){ | ||
585 | dvar = (struct dis_discrete *)gl_fetch(bollist,d); | ||
586 | bval->cur_val[d-1] = dis_value(dvar); | ||
587 | bval->pre_val[d-1] = dis_previous_value(dvar); | ||
588 | } | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * Restoring original values of boolean variables | ||
593 | */ | ||
594 | static void restore_original_bool_values(struct gl_list_t *bollist, | ||
595 | struct boolean_values *bval) | ||
596 | { | ||
597 | struct dis_discrete *dvar; | ||
598 | int32 d, dlen; | ||
599 | |||
600 | dlen = gl_length(bollist); | ||
601 | for (d=1; d<=dlen; d++){ | ||
602 | dvar = (struct dis_discrete *)gl_fetch(bollist,d); | ||
603 | dis_set_boolean_value(dvar,bval->cur_val[d-1]); | ||
604 | dis_set_value(dvar,bval->cur_val[d-1]); | ||
605 | dis_set_previous_value(dvar,bval->pre_val[d-1]); | ||
606 | } | ||
607 | destroy_array(bval->cur_val); | ||
608 | destroy_array(bval->pre_val); | ||
609 | } | ||
610 | |||
611 | |||
612 | /* | ||
613 | * the first element of cur_cases is in position one. The result is | ||
614 | * the same array, but ordered and starting in position zero | ||
615 | */ | ||
616 | static void cases_reorder(int32 *cur_cases, int32 *correct_cases, int32 ncases) | ||
617 | { | ||
618 | int32 cur_case,pos,tmp_num,c,ind; | ||
619 | |||
620 | for (c=1; c<=ncases; c++) { | ||
621 | tmp_num = 0; | ||
622 | for (ind=1; ind<=ncases; ind++) { | ||
623 | cur_case = cur_cases[ind]; | ||
624 | if (tmp_num < cur_case) { | ||
625 | pos = ind; | ||
626 | tmp_num = cur_case; | ||
627 | } | ||
628 | } | ||
629 | cur_cases[pos] = 0; | ||
630 | correct_cases[ncases-c] = tmp_num; | ||
631 | } | ||
632 | |||
633 | return; | ||
634 | } | ||
635 | |||
636 | /* | ||
637 | * Restoring orignal configuration of the system | ||
638 | */ | ||
639 | static void restore_configuration(slv_system_t server, | ||
640 | struct gl_list_t *bollist) | ||
641 | |||
642 | { | ||
643 | int32 *cur_cases, *correct_cases; | ||
644 | int32 ncases; | ||
645 | |||
646 | cur_cases = cases_matching(bollist,&ncases); | ||
647 | correct_cases = create_array(ncases,int32); | ||
648 | cases_reorder(cur_cases,correct_cases,ncases); | ||
649 | set_active_rels_in_subregion(server,correct_cases,ncases,bollist); | ||
650 | set_active_vars_in_subregion(server); | ||
651 | destroy_array(cur_cases); | ||
652 | destroy_array(correct_cases); | ||
653 | } | ||
654 | |||
655 | |||
656 | /* | ||
657 | * Get the list of boolean variables in the problem which are | ||
658 | * associated with a WHEN | ||
659 | */ | ||
660 | static struct gl_list_t *get_list_of_booleans(slv_system_t server, | ||
661 | SlvClientToken asys) | ||
662 | { | ||
663 | slv9_system_t sys; | ||
664 | struct dis_discrete **bvlist; | ||
665 | struct dis_discrete *cur_dis; | ||
666 | struct gl_list_t *boolvars; | ||
667 | dis_filter_t dfilter; | ||
668 | int32 numdvf, numdvs, d, dcount; | ||
669 | |||
670 | sys = SLV9(asys); | ||
671 | check_system(sys); | ||
672 | |||
673 | bvlist = sys->mdvlist; | ||
674 | if(bvlist == NULL ) { | ||
675 | FPRINTF(ASCERR,"ERROR: (slv9) get_list_of_booleans.\n"); | ||
676 | FPRINTF(ASCERR," Master discrete var list was never set.\n"); | ||
677 | return NULL; | ||
678 | } | ||
679 | numdvs = slv_get_num_master_dvars(server); | ||
680 | |||
681 | dfilter.matchbits = (DIS_INWHEN | DIS_BOOLEAN); | ||
682 | dfilter.matchvalue = (DIS_INWHEN | DIS_BOOLEAN); | ||
683 | numdvf = slv_count_master_dvars(server,&dfilter); | ||
684 | |||
685 | if (numdvf == 0) { | ||
686 | FPRINTF(ASCERR,"ERROR: (slv9) get_list_of_booleans.\n"); | ||
687 | FPRINTF(ASCERR," No boolean variables in the problem \n"); | ||
688 | return NULL; | ||
689 | } | ||
690 | |||
691 | sys->bool_mindex = (int32 *)(ascmalloc(numdvf*sizeof(int32))); | ||
692 | boolvars = gl_create(numdvf); | ||
693 | |||
694 | dcount = 0; | ||
695 | for (d=0; d<numdvs; d++) { | ||
696 | cur_dis = bvlist[d]; | ||
697 | if (dis_apply_filter(cur_dis,&(dfilter))) { | ||
698 | gl_append_ptr(boolvars,cur_dis); | ||
699 | sys->bool_mindex[dcount] = d; | ||
700 | dcount++; | ||
701 | } | ||
702 | } | ||
703 | |||
704 | return boolvars; | ||
705 | } | ||
706 | |||
707 | |||
708 | /* | ||
709 | * Get the eligible var list for each alternative | ||
710 | * Return: | ||
711 | * 1 means everything went right | ||
712 | * 0 means the analysis has failed with the current parititioning | ||
713 | * -1 means a memory problem has occurred | ||
714 | */ | ||
715 | static int32 get_eligible_set(slv_system_t server,struct gl_list_t *disvars, | ||
716 | int32 *terminate) | ||
717 | { | ||
718 | struct var_variable **vslist; | ||
719 | struct var_variable **vmlist; | ||
720 | struct var_variable *mvar, *svar; | ||
721 | var_filter_t vfilter; | ||
722 | int32 *cur_cases; | ||
723 | int32 *correct_cases; | ||
724 | int32 *vars; | ||
725 | int32 v, count, ind; | ||
726 | int32 ncases; | ||
727 | int32 mnum; | ||
728 | int32 status,dof; | ||
729 | |||
730 | vslist = slv_get_solvers_var_list(server); | ||
731 | vmlist = slv_get_master_var_list(server); | ||
732 | mnum = slv_get_num_master_vars(server); | ||
733 | for (v=0; v<mnum; v++) { | ||
734 | mvar = vmlist[v]; | ||
735 | var_set_eligible_in_subregion(mvar,FALSE); | ||
736 | } | ||
737 | |||
738 | cur_cases = cases_matching(disvars,&ncases); | ||
739 | correct_cases = create_array(ncases,int32); | ||
740 | cases_reorder(cur_cases,correct_cases,ncases); | ||
741 | set_active_rels_in_subregion(server,correct_cases,ncases,disvars); | ||
742 | set_active_vars_in_subregion(server); | ||
743 | destroy_array(cur_cases); | ||
744 | destroy_array(correct_cases); | ||
745 | |||
746 | #if DEBUG_CONSISTENCY | ||
747 | FPRINTF(ASCERR,"Analyzing alternative:\n"); | ||
748 | #endif /* DEBUG_CONSISTENCY */ | ||
749 | |||
750 | if (!slvDOF_status(server,(&status),(&dof))) { | ||
751 | FPRINTF(ASCERR,"ERROR in combinatorial search\n"); | ||
752 | FPRINTF(ASCERR,"Combinatorial search aborted\n"); | ||
753 | return -1; | ||
754 | } else { | ||
755 | if (status == 3) { | ||
756 | #if DEBUG_CONSISTENCY | ||
757 | FPRINTF(ASCERR,"Alternative is structurally singular\n"); | ||
758 | #endif /* DEBUG_CONSISTENCY */ | ||
759 | (*terminate) = 0; | ||
760 | return 0; | ||
761 | } else { | ||
762 | if (status == 4) { | ||
763 | #if DEBUG_CONSISTENCY | ||
764 | FPRINTF(ASCERR,"Alternative is overspecified\n"); | ||
765 | #endif /* DEBUG_CONSISTENCY */ | ||
766 | (*terminate) = 0; | ||
767 | return 0; | ||
768 | } | ||
769 | } | ||
770 | } | ||
771 | |||
772 | if (status == 1) { | ||
773 | (*terminate) = 0; | ||
774 | #if DEBUG_CONSISTENCY | ||
775 | FPRINTF(ASCERR,"Alternative has % d degrees of freedom.\n", dof); | ||
776 | |||
777 | #endif /* DEBUG_CONSISTENCY */ | ||
778 | if (slvDOF_eligible(server,&(vars))) { | ||
779 | count = 0; | ||
780 | while (vars[count] != -1) { | ||
781 | ind = vars[count]; | ||
782 | svar = vslist[ind]; | ||
783 | v = var_mindex(svar); | ||
784 | mvar = vmlist[v]; | ||
785 | var_set_eligible_in_subregion(mvar,TRUE); | ||
786 | count++; | ||
787 | } | ||
788 | destroy_array(vars); | ||
789 | } | ||
790 | if (dof > count) { | ||
791 | #if DEBUG_CONSISTENCY | ||
792 | FPRINTF(ASCERR, | ||
793 | "Alternative does not have enough number of eligible vars\n"); | ||
794 | #endif /* DEBUG_CONSISTENCY */ | ||
795 | return 0; | ||
796 | } | ||
797 | } | ||
798 | |||
799 | if (status == 2) { | ||
800 | #if DEBUG_CONSISTENCY | ||
801 | FPRINTF(ASCERR,"Alternative is square.\n"); | ||
802 | #endif /* DEBUG_CONSISTENCY */ | ||
803 | } | ||
804 | |||
805 | vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR | ||
806 | | VAR_ELIGIBLE_IN_SUBREGION); | ||
807 | vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR); | ||
808 | |||
809 | for (v=0; v<mnum; v++) { | ||
810 | mvar = vmlist[v]; | ||
811 | if(var_apply_filter(mvar,&vfilter)) { | ||
812 | var_set_eligible(mvar,FALSE); | ||
813 | } | ||
814 | var_set_eligible_in_subregion(mvar,FALSE); | ||
815 | } | ||
816 | |||
817 | return 1; | ||
818 | } | ||
819 | |||
820 | /* | ||
821 | * Get the eligible set of variables for each of the alternatives generated | ||
822 | * by modifying the values of the boolean variables with the values stored | ||
823 | * during the solution process | ||
824 | * Return: | ||
825 | * 1 means everything went right | ||
826 | * 0 means the analysis has failed with the current partitioning | ||
827 | * -1 means a memory problem or wierdness has occurred | ||
828 | */ | ||
829 | static int32 do_search_alternatives(slv_system_t server, SlvClientToken asys, | ||
830 | struct gl_list_t *disvars, | ||
831 | int32 *terminate, int32 all_sub) | ||
832 | { | ||
833 | slv9_system_t sys; | ||
834 | struct dis_discrete *cur_dis; | ||
835 | struct subregionID *sub; | ||
836 | int32 *values; | ||
837 | int32 dlen, test; | ||
838 | int32 lens, lenv, v, s, d; | ||
839 | int32 result; | ||
840 | unsigned long visited, vID; | ||
841 | |||
842 | |||
843 | sys = SLV9(asys); | ||
844 | |||
845 | dlen = gl_length(disvars); | ||
846 | lenv = sys->subregions_visited.length; | ||
847 | lens = sys->subregion_list.length; | ||
848 | |||
849 | if (all_sub == 0) { /* current and previous subregion */ | ||
850 | for (v=lenv-2; v<lenv; v++) { | ||
851 | test = 0; | ||
852 | vID = sys->subregions_visited.visited[v]; | ||
853 | for (s=lens-1; s>=0; s--) { | ||
854 | sub = &(sys->subregion_list.sub_stack[s]); | ||
855 | visited = sub->ID_number; | ||
856 | if (vID == visited) { | ||
857 | values = sub->bool_values; | ||
858 | test = 1; | ||
859 | FPRINTF(ASCERR,"s = %d \n",s); | ||
860 | break; | ||
861 | } | ||
862 | } | ||
863 | |||
864 | if (test == 0) { | ||
865 | FPRINTF(ASCERR,"ERROR: (slv9) do_search_alternatives \n"); | ||
866 | FPRINTF(ASCERR," subregion not found \n"); | ||
867 | return -1; | ||
868 | } | ||
869 | #if DEBUG_CONSISTENCY | ||
870 | FPRINTF(ASCERR,"Alternative = %ul \n", vID); | ||
871 | #endif /* DEBUG_CONSISTENCY */ | ||
872 | for (d=0; d<dlen; d++) { | ||
873 | cur_dis = (struct dis_discrete *)(gl_fetch(disvars,d+1)); | ||
874 | if (values[d] == 1) { | ||
875 | dis_set_boolean_value(cur_dis,TRUE); | ||
876 | } else { | ||
877 | dis_set_boolean_value(cur_dis,FALSE); | ||
878 | } | ||
879 | } | ||
880 | result = get_eligible_set(server,disvars,terminate); | ||
881 | if (result != 1) { | ||
882 | return result; | ||
883 | } | ||
884 | } | ||
885 | |||
886 | } else { /* all visited subregions */ | ||
887 | |||
888 | for (s=lens-1; s>=0; s--) { | ||
889 | sub = &(sys->subregion_list.sub_stack[s]); | ||
890 | values = sub->bool_values; | ||
891 | vID = sub->ID_number; | ||
892 | #if DEBUG_CONSISTENCY | ||
893 | FPRINTF(ASCERR,"Alternative = %ul \n", vID); | ||
894 | #endif /* DEBUG_CONSISTENCY */ | ||
895 | for (d=0; d<dlen; d++) { | ||
896 | cur_dis = (struct dis_discrete *)(gl_fetch(disvars,d+1)); | ||
897 | if (values[d] == 1) { | ||
898 | dis_set_boolean_value(cur_dis,TRUE); | ||
899 | } else { | ||
900 | dis_set_boolean_value(cur_dis,FALSE); | ||
901 | } | ||
902 | } | ||
903 | result = get_eligible_set(server,disvars,terminate); | ||
904 | if (result != 1) { | ||
905 | return result; | ||
906 | } | ||
907 | } | ||
908 | } | ||
909 | |||
910 | return 1; | ||
911 | } | ||
912 | |||
913 | |||
914 | /* | ||
915 | * Perform consistency analysis for the visited/current-previous subregions. | ||
916 | * If all_subs is 1, the analysis takes in account all of the subregions | ||
917 | * visited by the solution algorithm at the current point if the solution | ||
918 | * procedure. If all_subs is 0, the analysis is only for the current | ||
919 | * and previous subregion. | ||
920 | */ | ||
921 | static int32 consistency(slv_system_t server, SlvClientToken asys, | ||
922 | struct gl_list_t *bollist, | ||
923 | int32 all_subs, int32 *terminate) | ||
924 | { | ||
925 | slv9_system_t sys; | ||
926 | struct var_variable **vmlist; | ||
927 | struct var_variable *mvar; | ||
928 | var_filter_t vfilter; | ||
929 | int32 *globeli; | ||
930 | int32 dlen; | ||
931 | int32 mnum, v, elnum; | ||
932 | int32 result; | ||
933 | int32 iter; | ||
934 | |||
935 | sys = SLV9(asys); | ||
936 | check_system(sys); | ||
937 | |||
938 | /* | ||
939 | * Initializing eligible bit for variables | ||
940 | */ | ||
941 | vmlist = slv_get_master_var_list(server); | ||
942 | mnum = slv_get_num_master_vars(server); | ||
943 | for (v=0; v<mnum; v++) { | ||
944 | mvar = vmlist[v]; | ||
945 | var_set_eligible(mvar,TRUE); | ||
946 | } | ||
947 | |||
948 | dlen = gl_length(bollist); | ||
949 | |||
950 | #if DEBUG_CONSISTENCY | ||
951 | FPRINTF(ASCERR,"S e a r c h i n g \n"); | ||
952 | #endif /* DEBUG_CONSISTENCY */ | ||
953 | result = do_search_alternatives(server,asys,bollist,terminate,all_subs); | ||
954 | |||
955 | if (result != 1) { | ||
956 | #if DEBUG_CONSISTENCY | ||
957 | FPRINTF(ASCERR,"returning failed search after S e a r c h \n"); | ||
958 | #endif /* DEBUG_CONSISTENCY */ | ||
959 | return result; | ||
960 | } | ||
961 | |||
962 | /* | ||
963 | * Getting the "globally" eligible variables | ||
964 | */ | ||
965 | vfilter.matchbits = (VAR_INCIDENT | VAR_SVAR | VAR_ELIGIBLE | VAR_FIXED); | ||
966 | vfilter.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ELIGIBLE); | ||
967 | elnum = slv_count_master_vars(server,&vfilter); | ||
968 | |||
969 | if (elnum > 0) { | ||
970 | globeli = (int32 *)ascmalloc(elnum*sizeof(int32)); | ||
971 | elnum = 0; | ||
972 | for (v=0; v<mnum; v++) { | ||
973 | mvar = vmlist[v]; | ||
974 | if(var_apply_filter(mvar,&vfilter)) { | ||
975 | #if DEBUG_CONSISTENCY | ||
976 | FPRINTF(ASCERR,"Eligible index = %d \n",v); | ||
977 | #endif /* DEBUG_CONSISTENCY */ | ||
978 | globeli[elnum] = v; | ||
979 | elnum++; | ||
980 | } | ||
981 | } | ||
982 | } | ||
983 | |||
984 | /* | ||
985 | * Recursively analysis | ||
986 | */ | ||
987 | |||
988 | if ((*terminate) == 1) { | ||
989 | if (elnum != 0) { | ||
990 | #if DEBUG_CONSISTENCY | ||
991 | FPRINTF(ASCERR,"All alternatives are square but the \n"); | ||
992 | FPRINTF(ASCERR,"Eligible set is not null\n"); | ||
993 | #endif /* DEBUG_CONSISTENCY */ | ||
994 | destroy_array(globeli); | ||
995 | } | ||
996 | return 1; | ||
997 | } else { | ||
998 | if (elnum == 0) { | ||
999 | #if DEBUG_CONSISTENCY | ||
1000 | FPRINTF(ASCERR,"No globally eligible variables to be fixed.\n"); | ||
1001 | #endif /* DEBUG_CONSISTENCY */ | ||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
1005 | for (v=0; v<elnum; v++) { | ||
1006 | iter = 1; | ||
1007 | mvar = vmlist[globeli[v]]; | ||
1008 | var_set_fixed(mvar,TRUE); | ||
1009 | var_set_potentially_fixed(mvar,TRUE); | ||
1010 | #if DEBUG_CONSISTENCY | ||
1011 | FPRINTF(ASCERR,"Fixing index = %d \n",globeli[v]); | ||
1012 | FPRINTF(ASCERR,"N e s t e d S e a r c h \n"); | ||
1013 | #endif /* DEBUG_CONSISTENCY */ | ||
1014 | result = consistency(server,asys,bollist,all_subs,&iter); | ||
1015 | |||
1016 | if (result != 1) { | ||
1017 | #if DEBUG_CONSISTENCY | ||
1018 | FPRINTF(ASCERR,"%d eliminated\n",globeli[v]); | ||
1019 | #endif /* DEBUG_CONSISTENCY */ | ||
1020 | var_set_fixed(mvar,FALSE); | ||
1021 | var_set_potentially_fixed(mvar,FALSE); | ||
1022 | continue; | ||
1023 | } else { | ||
1024 | if (iter == 1) { | ||
1025 | (*terminate) = 1; | ||
1026 | #if DEBUG_CONSISTENCY | ||
1027 | FPRINTF(ASCERR,"%d Acepted \n",globeli[v]); | ||
1028 | #endif /* DEBUG_CONSISTENCY */ | ||
1029 | destroy_array(globeli); | ||
1030 | return 1; | ||
1031 | } else { | ||
1032 | var_set_fixed(mvar,FALSE); | ||
1033 | var_set_potentially_fixed(mvar,FALSE); | ||
1034 | continue; | ||
1035 | } | ||
1036 | } | ||
1037 | } | ||
1038 | destroy_array(globeli); | ||
1039 | #if DEBUG_CONSISTENCY | ||
1040 | FPRINTF(ASCERR,"returning 0 after nested search\n"); | ||
1041 | #endif /* DEBUG_CONSISTENCY */ | ||
1042 | return 0; | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | /* | ||
1048 | * Get a set of globally eligible variables. Eligible for all the subregions | ||
1049 | * visited, or for the previous and current subregions. | ||
1050 | */ | ||
1051 | static int32 get_globally_eligible(slv_system_t server, SlvClientToken asys, | ||
1052 | struct gl_list_t *bollist, | ||
1053 | int32 all_subs, int32 **eliset) | ||
1054 | { | ||
1055 | slv9_system_t sys; | ||
1056 | struct var_variable **vmlist; | ||
1057 | struct var_variable *mvar; | ||
1058 | var_filter_t vfilter; | ||
1059 | int32 dlen; | ||
1060 | int32 mnum, v, elnum; | ||
1061 | int32 terminate; | ||
1062 | int32 result; | ||
1063 | |||
1064 | sys = SLV9(asys); | ||
1065 | check_system(sys); | ||
1066 | /* | ||
1067 | * Initializing eligible bit for variables | ||
1068 | */ | ||
1069 | vmlist = slv_get_master_var_list(server); | ||
1070 | mnum = slv_get_num_master_vars(server); | ||
1071 | for (v=0; v<mnum; v++) { | ||
1072 | mvar = vmlist[v]; | ||
1073 | var_set_eligible(mvar,TRUE); | ||
1074 | } | ||
1075 | |||
1076 | dlen = gl_length(bollist); | ||
1077 | |||
1078 | /* | ||
1079 | * initializing | ||
1080 | */ | ||
1081 | *eliset = NULL; | ||
1082 | terminate = 1; | ||
1083 | |||
1084 | #if DEBUG_CONSISTENCY | ||
1085 | FPRINTF(ASCERR,"S e a r c h i n g \n"); | ||
1086 | #endif /* DEBUG_CONSISTENCY */ | ||
1087 | result = do_search_alternatives(server,asys,bollist,&terminate,all_subs); | ||
1088 | |||
1089 | if (result != 1) { | ||
1090 | if (terminate == 0) { | ||
1091 | #if DEBUG_CONSISTENCY | ||
1092 | FPRINTF(ASCERR,"ERROR: some alternatives are either singular or\n"); | ||
1093 | FPRINTF(ASCERR,"overspecified. All the alternatives have to be\n"); | ||
1094 | FPRINTF(ASCERR, | ||
1095 | "either square or underspecified to complete the analysis\n"); | ||
1096 | #endif /* DEBUG_CONSISTENCY */ | ||
1097 | } | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | /* | ||
1102 | * Getting the "globally" eligible variables | ||
1103 | */ | ||
1104 | vfilter.matchbits = (VAR_INCIDENT | VAR_SVAR | VAR_ELIGIBLE | VAR_FIXED); | ||
1105 | vfilter.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ELIGIBLE); | ||
1106 | elnum = slv_count_master_vars(server,&vfilter); | ||
1107 | |||
1108 | *eliset = (int32 *)ascmalloc((elnum+1)*sizeof(int32)); | ||
1109 | elnum = 0; | ||
1110 | for (v=0; v<mnum; v++) { | ||
1111 | mvar = vmlist[v]; | ||
1112 | if(var_apply_filter(mvar,&vfilter)) { | ||
1113 | #if DEBUG_CONSISTENCY | ||
1114 | FPRINTF(ASCERR,"Eligible index = %d \n",v); | ||
1115 | FPRINTF(ASCERR,"Variable : \n"); | ||
1116 | print_var_name(ASCERR,sys,mvar); | ||
1117 | #endif /* DEBUG_CONSISTENCY */ | ||
1118 | (*eliset)[elnum] = v; | ||
1119 | elnum++; | ||
1120 | } | ||
1121 | } | ||
1122 | (*eliset)[elnum] = -1; | ||
1123 | |||
1124 | if (elnum == 0) { | ||
1125 | if (terminate == 0) { | ||
1126 | #if DEBUG_CONSISTENCY | ||
1127 | FPRINTF(ASCERR, | ||
1128 | "Some alternatives are underspecified, but there does\n"); | ||
1129 | FPRINTF(ASCERR,"not exist a set of eligible variables consistent \n"); | ||
1130 | FPRINTF(ASCERR,"with all the alternatives\n"); | ||
1131 | #endif /* DEBUG_CONSISTENCY */ | ||
1132 | } else { | ||
1133 | #if DEBUG_CONSISTENCY | ||
1134 | FPRINTF(ASCERR,"All alternatives are already square\n"); | ||
1135 | #endif /* DEBUG_CONSISTENCY */ | ||
1136 | } | ||
1137 | return 0; | ||
1138 | } else { | ||
1139 | if (terminate == 1) { | ||
1140 | #if DEBUG_CONSISTENCY | ||
1141 | FPRINTF(ASCERR,"All alternatives are square but the \n"); | ||
1142 | FPRINTF(ASCERR,"Eligible set is not null\n"); | ||
1143 | #endif /* DEBUG_CONSISTENCY */ | ||
1144 | } | ||
1145 | } | ||
1146 | return 1; | ||
1147 | } | ||
1148 | |||
1149 | |||
1150 | /* | ||
1151 | * Store and restore values of the boolean variables of the problem | ||
1152 | * and calls for the the set of globally eligible variables.If all_subs | ||
1153 | * is 1, the analysis takes in account all of the subregions visited | ||
1154 | * by the solution algorithm at the current point if the solution | ||
1155 | * procedure. If all_subs is 0, the analysis is only for the current | ||
1156 | * and previous subregion. | ||
1157 | */ | ||
1158 | static int32 consistent_eligible_set_for_subregions(slv_system_t server, | ||
1159 | SlvClientToken asys, | ||
1160 | int32 **vlist, | ||
1161 | int32 all_subs) | ||
1162 | { | ||
1163 | struct gl_list_t *blist; | ||
1164 | struct boolean_values bval; | ||
1165 | int32 result; | ||
1166 | |||
1167 | if (server==NULL || vlist == NULL) { | ||
1168 | FPRINTF(ASCERR, | ||
1169 | "consistent_eligible_set_for_subregions called with NULL.\n"); | ||
1170 | return 0; | ||
1171 | } | ||
1172 | |||
1173 | blist = get_list_of_booleans(server,asys); | ||
1174 | |||
1175 | if ( (blist == NULL) || (gl_length(blist) == 0) ) { | ||
1176 | FPRINTF(ASCERR,"ERROR: (slv9) consistent_eligible_set_for_subregions \n"); | ||
1177 | FPRINTF(ASCERR," List of boolean vars could not be found\n"); | ||
1178 | return 0; | ||
1179 | } | ||
1180 | |||
1181 | store_original_bool_values(blist,&(bval)); | ||
1182 | result = get_globally_eligible(server,asys,blist,all_subs,vlist); | ||
1183 | |||
1184 | restore_original_bool_values(blist,&(bval)); | ||
1185 | restore_configuration(server,blist); | ||
1186 | gl_destroy(blist); | ||
1187 | |||
1188 | if (result == 1) { | ||
1189 | return 1; | ||
1190 | } else { | ||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1194 | } | ||
1195 | |||
1196 | /* | ||
1197 | * Store and restore values of the boolean variables of the problem | ||
1198 | * and calls for the consistency analysis of the subregions.If all_subs | ||
1199 | * is 1, the analysis takes in account all of the subregions visited | ||
1200 | * by the solution algorithm at the current point if the solution | ||
1201 | * procedure. If all_subs is 0, the analysis is only for the current | ||
1202 | * and previous subregion. | ||
1203 | */ | ||
1204 | static int32 analyze_subregions(slv_system_t server,SlvClientToken asys, | ||
1205 | int32 **vlist, int32 all_subs) | ||
1206 | { | ||
1207 | slv9_system_t sys; | ||
1208 | struct var_variable ** vmlist; | ||
1209 | struct var_variable *mvar; | ||
1210 | struct gl_list_t *blist; | ||
1211 | struct boolean_values bval; | ||
1212 | var_filter_t vfilter; | ||
1213 | int32 mnum, elnum, v; | ||
1214 | int32 result; | ||
1215 | int32 terminate; | ||
1216 | |||
1217 | sys = SLV9(asys); | ||
1218 | check_system(sys); | ||
1219 | |||
1220 | if (server==NULL || vlist == NULL) { | ||
1221 | FPRINTF(ASCERR,"(slv9) analyze_subregions called with NULL.\n"); | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | blist = get_list_of_booleans(server,asys); | ||
1226 | if ( (blist == NULL) || (gl_length(blist) == 0) ) { | ||
1227 | FPRINTF(ASCERR,"ERROR: (slv9) analyze_subregions \n"); | ||
1228 | FPRINTF(ASCERR," List of boolean vars could not be found\n"); | ||
1229 | return 0; | ||
1230 | } | ||
1231 | |||
1232 | store_original_bool_values(blist,&(bval)); | ||
1233 | /* | ||
1234 | * initializing | ||
1235 | */ | ||
1236 | terminate = 1; | ||
1237 | (*vlist) = NULL; | ||
1238 | |||
1239 | vmlist = slv_get_master_var_list(server); | ||
1240 | mnum = slv_get_num_master_vars(server); | ||
1241 | |||
1242 | vfilter.matchbits = (VAR_POTENTIALLY_FIXED); | ||
1243 | vfilter.matchvalue = (VAR_POTENTIALLY_FIXED); | ||
1244 | |||
1245 | result = consistency(server,asys,blist,all_subs,&terminate); | ||
1246 | |||
1247 | if (result == 1) { | ||
1248 | /* | ||
1249 | * Getting the set of eligible variables | ||
1250 | */ | ||
1251 | elnum = slv_count_master_vars(server,&vfilter); | ||
1252 | *vlist = (int32 *)ascmalloc((elnum+1)*sizeof(int32)); | ||
1253 | elnum = 0; | ||
1254 | for (v=0; v<mnum; v++) { | ||
1255 | mvar = vmlist[v]; | ||
1256 | if(var_apply_filter(mvar,&vfilter)) { | ||
1257 | var_set_fixed(mvar,FALSE); | ||
1258 | var_set_potentially_fixed(mvar,FALSE); | ||
1259 | #if DEBUG_CONSISTENCY | ||
1260 | FPRINTF(ASCERR,"Variable in consistent set: \n"); | ||
1261 | print_var_name(ASCERR,sys,mvar); | ||
1262 | #endif /* DEBUG_CONSISTENCY */ | ||
1263 | (*vlist)[elnum] = v; | ||
1264 | elnum++; | ||
1265 | } | ||
1266 | } | ||
1267 | (*vlist)[elnum] = -1; | ||
1268 | |||
1269 | restore_original_bool_values(blist,&(bval)); | ||
1270 | restore_configuration(server,blist); | ||
1271 | gl_destroy(blist); | ||
1272 | return 1; | ||
1273 | } else { | ||
1274 | for (v=0; v<mnum; v++) { | ||
1275 | mvar = vmlist[v]; | ||
1276 | if(var_apply_filter(mvar,&vfilter)) { | ||
1277 | var_set_fixed(mvar,FALSE); | ||
1278 | var_set_potentially_fixed(mvar,FALSE); | ||
1279 | } | ||
1280 | } | ||
1281 | restore_original_bool_values(blist,&(bval)); | ||
1282 | restore_configuration(server,blist); | ||
1283 | gl_destroy(blist); | ||
1284 | return 0; | ||
1285 | } | ||
1286 | } | ||
1287 | |||
1288 | |||
1289 | /* | ||
1290 | * Finds the globally eligible set of variables only for the current and | ||
1291 | * previous subregions | ||
1292 | */ | ||
1293 | static int32 eligible_set_for_neighboring_subregions(slv_system_t server, | ||
1294 | SlvClientToken asys, | ||
1295 | int32 **vlist) | ||
1296 | { | ||
1297 | slv9_system_t sys; | ||
1298 | |||
1299 | sys = SLV9(asys); | ||
1300 | check_system(sys); | ||
1301 | |||
1302 | if( sys->mdvlist == NULL ) { | ||
1303 | FPRINTF(ASCERR,"ERROR: (slv9) eligible_set_for_neighboring_subregions\n"); | ||
1304 | FPRINTF(ASCERR," Discrete Variable list was never set.\n"); | ||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | if (!(sys->need_consistency_analysis)) { | ||
1309 | FPRINTF(ASCERR,"Globally eligible set not necessary\n"); | ||
1310 | FPRINTF(ASCERR,"All the subregions have the same structure \n"); | ||
1311 | return 0; | ||
1312 | } | ||
1313 | |||
1314 | if (consistent_eligible_set_for_subregions(server,asys,vlist,0)) { | ||
1315 | return 1; | ||
1316 | } | ||
1317 | |||
1318 | return 0; | ||
1319 | } | ||
1320 | |||
1321 | |||
1322 | /* | ||
1323 | * Perform the consistency analysis algorithm only for the current and | ||
1324 | * previous subregions | ||
1325 | */ | ||
1326 | static int32 consistency_for_neighboring_subregions(slv_system_t server, | ||
1327 | SlvClientToken asys, | ||
1328 | int32 **vlist) | ||
1329 | { | ||
1330 | slv9_system_t sys; | ||
1331 | |||
1332 | sys = SLV9(asys); | ||
1333 | check_system(sys); | ||
1334 | |||
1335 | if( sys->mdvlist == NULL ) { | ||
1336 | FPRINTF(ASCERR,"ERROR: (slv9) consistency_for_neighboring_subregions\n"); | ||
1337 | FPRINTF(ASCERR," Discrete Variable list was never set.\n"); | ||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1341 | if (!(sys->need_consistency_analysis)) { | ||
1342 | FPRINTF(ASCERR,"consistency_analysis is not required\n"); | ||
1343 | FPRINTF(ASCERR,"All the subregions have the same structure \n"); | ||
1344 | return 0; | ||
1345 | } | ||
1346 | |||
1347 | if (analyze_subregions(server,asys,vlist,0)) { | ||
1348 | return 1; | ||
1349 | } | ||
1350 | |||
1351 | return 0; | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | |||
1356 | /* | ||
1357 | * Consistency analysis for visisted subregions. This function | ||
1358 | * gets the subregions that the solution algorithm has visited and | ||
1359 | * analyzes them. | ||
1360 | */ | ||
1361 | static int32 eligible_set_for_subregions(slv_system_t server, | ||
1362 | SlvClientToken asys, | ||
1363 | int32 **vlist) | ||
1364 | { | ||
1365 | slv9_system_t sys; | ||
1366 | |||
1367 | sys = SLV9(asys); | ||
1368 | check_system(sys); | ||
1369 | |||
1370 | if( sys->mdvlist == NULL ) { | ||
1371 | FPRINTF(ASCERR,"ERROR: (slv9) eligible_set_for_subregions \n"); | ||
1372 | FPRINTF(ASCERR," Discrete Variable list was never set.\n"); | ||
1373 | return 0; | ||
1374 | } | ||
1375 | |||
1376 | if (!(sys->need_consistency_analysis)) { | ||
1377 | FPRINTF(ASCERR,"Globally eligible set not necessary \n"); | ||
1378 | FPRINTF(ASCERR,"All the subregions have the same structure \n"); | ||
1379 | return 0; | ||
1380 | } | ||
1381 | |||
1382 | if (consistent_eligible_set_for_subregions(server,asys,vlist,1)) { | ||
1383 | return 1; | ||
1384 | } | ||
1385 | |||
1386 | return 0; | ||
1387 | } | ||
1388 | |||
1389 | |||
1390 | /* | ||
1391 | * Consistency analysis for visisted subregions. This function | ||
1392 | * gets the subregions that the solution algorithm has visited and | ||
1393 | * analyzes them. | ||
1394 | */ | ||
1395 | static int32 consistency_analysis_for_subregions(slv_system_t server, | ||
1396 | SlvClientToken asys, | ||
1397 | int32 **vlist) | ||
1398 | { | ||
1399 | slv9_system_t sys; | ||
1400 | |||
1401 | sys = SLV9(asys); | ||
1402 | check_system(sys); | ||
1403 | |||
1404 | if( sys->mdvlist == NULL ) { | ||
1405 | FPRINTF(ASCERR,"ERROR: (slv9) consistency_analysis_for_subregions\n"); | ||
1406 | FPRINTF(ASCERR," Discrete Variable list was never set.\n"); | ||
1407 | return 0; | ||
1408 | } | ||
1409 | |||
1410 | if (!(sys->need_consistency_analysis)) { | ||
1411 | FPRINTF(ASCERR,"consistency_analysis is not required\n"); | ||
1412 | FPRINTF(ASCERR,"All the subregions have the same structure \n"); | ||
1413 | return 0; | ||
1414 | } | ||
1415 | |||
1416 | if (analyze_subregions(server,asys,vlist,1)) { | ||
1417 | return 1; | ||
1418 | } | ||
1419 | |||
1420 | return 0; | ||
1421 | } | ||
1422 | |||
1423 | |||
1424 | |||
1425 | /* | ||
1426 | * Handling of solution of the Logical Equations | ||
1427 | * --------------------------------------------------------- | ||
1428 | * This is made this way because it is a process which will be | ||
1429 | * required very often. | ||
1430 | */ | ||
1431 | |||
1432 | /* | ||
1433 | * Solution of the logical relations encountered in the system based on | ||
1434 | * the current values of the discrete variables. | ||
1435 | */ | ||
1436 | static void solve_logical_relations(slv_system_t server) | ||
1437 | { | ||
1438 | slv_set_client_token(server,token[LOGICAL_SOLVER]); | ||
1439 | slv_set_solver_index(server,solver_index[LOGICAL_SOLVER]); | ||
1440 | slv_presolve(server); | ||
1441 | #if SHOW_LOGICAL_DETAILS | ||
1442 | FPRINTF(ASCERR,"Solving Logical Relations\n"); | ||
1443 | #endif /* SHOW_LOGICAL_DETAILS */ | ||
1444 | slv_solve(server); | ||
1445 | } | ||
1446 | |||
1447 | |||
1448 | |||
1449 | /* | ||
1450 | * Handling the modification of parameters in external solvers | ||
1451 | * --------------------------------------------------------- | ||
1452 | */ | ||
1453 | |||
1454 | /* | ||
1455 | * different types of parameter values | ||
1456 | */ | ||
1457 | union param_value { | ||
1458 | int32 i; | ||
1459 | real64 r; | ||
1460 | int32 b; | ||
1461 | char *c; | ||
1462 | }; | ||
1463 | |||
1464 | |||
1465 | /* | ||
1466 | * Setting the value of a parameter in a subsidiary solver | ||
1467 | */ | ||
1468 | static void set_param_in_solver(slv_system_t server, int32 solver, | ||
1469 | enum parm_type types, char *param, | ||
1470 | union param_value *value) | ||
1471 | { | ||
1472 | slv_parameters_t p; | ||
1473 | int32 len,length; | ||
1474 | |||
1475 | slv_set_client_token(server,token[solver]); | ||
1476 | slv_set_solver_index(server,solver_index[solver]); | ||
1477 | slv_get_parameters(server,&p); | ||
1478 | length = p.num_parms; | ||
1479 | for (len = 0; len < length; len++) { | ||
1480 | if (p.parms[len].type == types) { | ||
1481 | switch (p.parms[len].type) { | ||
1482 | case bool_parm: | ||
1483 | if (strcmp(param,p.parms[len].name) == 0) { | ||
1484 | p.parms[len].info.b.value = value->b; | ||
1485 | } | ||
1486 | break; | ||
1487 | case real_parm: | ||
1488 | if (strcmp(param,p.parms[len].name) == 0) { | ||
1489 | p.parms[len].info.r.value = value->r; | ||
1490 | } | ||
1491 | break; | ||
1492 | case char_parm: | ||
1493 | if (strcmp(param,p.parms[len].name) == 0) { | ||
1494 | p.parms[len].info.c.value = value->c; | ||
1495 | } | ||
1496 | break; | ||
1497 | case int_parm: | ||
1498 | if (strcmp(param,p.parms[len].name) == 0) { | ||
1499 | p.parms[len].info.i.value = value->i; | ||
1500 | } | ||
1501 | break; | ||
1502 | default: | ||
1503 | break; | ||
1504 | } | ||
1505 | } | ||
1506 | } | ||
1507 | return; | ||
1508 | } | ||
1509 | |||
1510 | |||
1511 | /* | ||
1512 | * Analysis of Discrete Variables | ||
1513 | * ------------------------------- | ||
1514 | */ | ||
1515 | |||
1516 | /* | ||
1517 | * Compare current values of the discrete variables with their previous values | ||
1518 | * in order to know if some of them have changed. | ||
1519 | */ | ||
1520 | static int32 some_dis_vars_changed(slv_system_t server, SlvClientToken asys) | ||
1521 | { | ||
1522 | struct dis_discrete **dv, *cur_dis; | ||
1523 | int32 numdvs, ind; | ||
1524 | slv9_system_t sys; | ||
1525 | |||
1526 | sys = SLV9(asys); | ||
1527 | check_system(sys); | ||
1528 | |||
1529 | if( sys->dvlist == NULL ) { | ||
1530 | FPRINTF(ASCERR,"ERROR: (slv9) some_dis_vars_changed\n"); | ||
1531 | FPRINTF(ASCERR," Discrete variable list was never set.\n"); | ||
1532 | return 0; | ||
1533 | } | ||
1534 | |||
1535 | dv = sys->dvlist; | ||
1536 | numdvs = slv_get_num_solvers_dvars(server); | ||
1537 | for( ind = 0; ind < numdvs; ind++ ) { | ||
1538 | cur_dis = dv[ind]; | ||
1539 | #if SHOW_LOGICAL_DETAILS | ||
1540 | FPRINTF(ASCERR,"Boundary index = %d \n",ind); | ||
1541 | FPRINTF(ASCERR,"Current Value = %d\n",dis_value(cur_dis)); | ||
1542 | FPRINTF(ASCERR,"Previous Value = %d\n",dis_previous_value(cur_dis)); | ||
1543 | #endif /* SHOW_LOGICAL_DETAILS */ | ||
1544 | if ((dis_kind(cur_dis)==e_dis_boolean_t ) && dis_inwhen(cur_dis) ) { | ||
1545 | if (dis_value(cur_dis) != dis_previous_value(cur_dis)) { | ||
1546 | return 1; | ||
1547 | } | ||
1548 | } | ||
1549 | } | ||
1550 | return 0; | ||
1551 | } | ||
1552 | |||
1553 | /* | ||
1554 | * Compare the original value of a discrete boolean variable (before | ||
1555 | * perturbation of boundaries) with its values after a solution | ||
1556 | * of the logical relations with some perturbed values for boundaries. | ||
1557 | * If those values are different, the bit VAL_MODIFIED is set to | ||
1558 | * TRUE. This will give us the boolean variable which will change as a | ||
1559 | * consequence of a boundary crossing. | ||
1560 | */ | ||
1561 | static void search_for_modified_dvars(struct dis_discrete **dv, | ||
1562 | int32 numdvs, | ||
1563 | struct boolean_values *bval) | ||
1564 | { | ||
1565 | struct dis_discrete *cur_dis; | ||
1566 | int32 d; | ||
1567 | int32 orig_value; | ||
1568 | |||
1569 | for (d=0; d<numdvs; d++) { | ||
1570 | cur_dis = dv[d]; | ||
1571 | if(dis_inwhen(cur_dis) && dis_boolean(cur_dis)) { | ||
1572 | orig_value = bval->cur_val[d]; | ||
1573 | if (orig_value != dis_value(cur_dis)) { | ||
1574 | dis_set_val_modified(cur_dis,TRUE); | ||
1575 | } | ||
1576 | } | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1580 | |||
1581 | /* | ||
1582 | * Analysis of Boundaries | ||
1583 | * ---------------------------- | ||
1584 | */ | ||
1585 | |||
1586 | /* | ||
1587 | * Evaluates the current status (satisfied? , at zero?) of a boundary | ||
1588 | * and sets its flags accordingly. At the same time, it updates the | ||
1589 | * residual of the relation included in the boundary (see | ||
1590 | * bndman_calc_satisfied). | ||
1591 | */ | ||
1592 | |||
1593 | static void update_boundaries(slv_system_t server, SlvClientToken asys) | ||
1594 | { | ||
1595 | struct bnd_boundary **bp; | ||
1596 | int32 numbnds, ind, value; | ||
1597 | slv9_system_t sys; | ||
1598 | |||
1599 | sys = SLV9(asys); | ||
1600 | check_system(sys); | ||
1601 | |||
1602 | if( sys->blist == NULL ) { | ||
1603 | FPRINTF(ASCERR,"ERROR: (slv9) update_boundaries.\n"); | ||
1604 | FPRINTF(ASCERR," Boundary list was never set.\n"); | ||
1605 | return; | ||
1606 | } | ||
1607 | |||
1608 | bp = sys->blist; | ||
1609 | numbnds = slv_get_num_solvers_bnds(server); | ||
1610 | |||
1611 | for( ind = 0; ind < numbnds; ++ind ) { | ||
1612 | value = bnd_status_cur(bp[ind]); | ||
1613 | bnd_set_pre_status(bp[ind],value); | ||
1614 | value = bndman_calc_satisfied(bp[ind]); | ||
1615 | bnd_set_cur_status(bp[ind],value); | ||
1616 | if ( (bnd_status_cur(bp[ind]) != bnd_status_pre(bp[ind])) && | ||
1617 | bnd_kind(bp[ind]) == e_bnd_rel && !bnd_at_zero(bp[ind])) { | ||
1618 | bnd_set_crossed(bp[ind],TRUE); | ||
1619 | } else { | ||
1620 | bnd_set_crossed(bp[ind],FALSE); | ||
1621 | } | ||
1622 | if (bnd_kind(bp[ind]) == e_bnd_rel) { | ||
1623 | value = bndman_calc_at_zero(bp[ind]); | ||
1624 | bnd_set_at_zero(bp[ind],value); | ||
1625 | } else { | ||
1626 | bnd_set_at_zero(bp[ind],FALSE); | ||
1627 | } | ||
1628 | } | ||
1629 | } | ||
1630 | |||
1631 | |||
1632 | /* | ||
1633 | * Look for some boundary with the CROSSED bit active. If this boundary | ||
1634 | * is used in some logical relation, the function returns 1, else returns 0 | ||
1635 | */ | ||
1636 | static int32 some_boundaries_crossed(slv_system_t server, SlvClientToken asys) | ||
1637 | { | ||
1638 | struct bnd_boundary **bp, *cur_bnd; | ||
1639 | int32 numbnds, ind; | ||
1640 | slv9_system_t sys; | ||
1641 | |||
1642 | sys = SLV9(asys); | ||
1643 | check_system(sys); | ||
1644 | |||
1645 | if( sys->blist == NULL ) { | ||
1646 | FPRINTF(ASCERR,"ERROR: (slv9) some_boundaries_crossed\n"); | ||
1647 | FPRINTF(ASCERR," Boundary list was never set.\n"); | ||
1648 | return 0; | ||
1649 | } | ||
1650 | |||
1651 | bp = sys->blist; | ||
1652 | numbnds = slv_get_num_solvers_bnds(server); | ||
1653 | for( ind = 0; ind < numbnds; ++ind ) { | ||
1654 | cur_bnd = bp[ind]; | ||
1655 | if (bnd_crossed(cur_bnd) && bnd_in_logrel(cur_bnd)) { | ||
1656 | return 1; | ||
1657 | } | ||
1658 | } | ||
1659 | return 0; | ||
1660 | } | ||
1661 | |||
1662 | /* | ||
1663 | * Look for some boundary with the AT_ZERO bit active.If this boundary | ||
1664 | * is used in some logical relation, the function returns 1, else returns 0 | ||
1665 | */ | ||
1666 | static int32 some_boundaries_at_zero(slv_system_t server, SlvClientToken asys) | ||
1667 | { | ||
1668 | struct bnd_boundary **bp, *cur_bnd; | ||
1669 | int32 numbnds, ind; | ||
1670 | slv9_system_t sys; | ||
1671 | |||
1672 | sys = SLV9(asys); | ||
1673 | check_system(sys); | ||
1674 | |||
1675 | if( sys->blist == NULL ) { | ||
1676 | FPRINTF(ASCERR,"ERROR: (slv9) some_boundaries_at_zero\n"); | ||
1677 | FPRINTF(ASCERR," Boundary list was never set.\n"); | ||
1678 | return 0; | ||
1679 | } | ||
1680 | |||
1681 | bp = sys->blist; | ||
1682 | numbnds = slv_get_num_solvers_bnds(server); | ||
1683 | for( ind = 0; ind < numbnds; ++ind ) { | ||
1684 | cur_bnd = bp[ind]; | ||
1685 | if (bnd_at_zero(cur_bnd) && bnd_in_logrel(cur_bnd)) { | ||
1686 | return 1; | ||
1687 | } | ||
1688 | } | ||
1689 | return 0; | ||
1690 | } | ||
1691 | |||
1692 | /* | ||
1693 | * Perform the combinatorial perturbation of the boundaries which are | ||
1694 | * at their zero. That means: We are going to perform a combinatorial | ||
1695 | * search, changing the truth value of a SATISFIED term (for the | ||
1696 | * specified boundaries) ON and OFF, and finding the boolean variables | ||
1697 | * affected for those changes in value of the SATISFIED terms. | ||
1698 | */ | ||
1699 | static void do_perturbation_combinations(slv_system_t server, | ||
1700 | struct boolean_values *bval, | ||
1701 | struct bnd_boundary **bp, | ||
1702 | struct dis_discrete **dv, | ||
1703 | int32 numdvs,int32 *bndatzero, | ||
1704 | int32 ind, int32 numbndf) | ||
1705 | { | ||
1706 | slv_status_t status; | ||
1707 | int32 indpo; | ||
1708 | |||
1709 | if(ind<(numbndf-1)) { | ||
1710 | indpo = ind + 1; | ||
1711 | bnd_set_perturb(bp[bndatzero[ind]],TRUE); | ||
1712 | do_perturbation_combinations(server,bval,bp,dv,numdvs, | ||
1713 | bndatzero,indpo,numbndf); | ||
1714 | bnd_set_perturb(bp[bndatzero[ind]],FALSE); | ||
1715 | do_perturbation_combinations(server,bval,bp,dv,numdvs, | ||
1716 | bndatzero,indpo,numbndf); | ||
1717 | } else { | ||
1718 | if (ind < numbndf) { | ||
1719 | bnd_set_perturb(bp[bndatzero[ind]],TRUE); | ||
1720 | solve_logical_relations(server); | ||
1721 | slv_get_status(server,&status); | ||
1722 | if(!status.converged) { | ||
1723 | FPRINTF(ASCERR,"WARNING: \n"); | ||
1724 | FPRINTF(ASCERR,"(slv9) do_perturbation_combinations\n"); | ||
1725 | FPRINTF(ASCERR," Not convergence in logical solver \n"); | ||
1726 | } else { | ||
1727 | search_for_modified_dvars(dv,numdvs,bval); | ||
1728 | } | ||
1729 | bnd_set_perturb(bp[bndatzero[ind]],FALSE); | ||
1730 | solve_logical_relations(server); | ||
1731 | slv_get_status(server,&status); | ||
1732 | if(!status.converged) { | ||
1733 | FPRINTF(ASCERR,"WARNING: \n"); | ||
1734 | FPRINTF(ASCERR,"(slv9) do_perturbation_combinations\n"); | ||
1735 | FPRINTF(ASCERR," Not convergence in logical solver \n"); | ||
1736 | } else { | ||
1737 | search_for_modified_dvars(dv,numdvs,bval); | ||
1738 | } | ||
1739 | } else { | ||
1740 | FPRINTF(ASCERR,"ERROR: (slv9) do_perturbation_combinations\n"); | ||
1741 | FPRINTF(ASCERR," Wrong boundary index as argument\n"); | ||
1742 | } | ||
1743 | } | ||
1744 | return; | ||
1745 | } | ||
1746 | |||
1747 | |||
1748 | /* | ||
1749 | * Perform the combinatorial search of the subregions. That means: | ||
1750 | * We perform a combinatorial search, changing the value of the | ||
1751 | * discrete variables (given in disvars) TRUE and FALSE, and | ||
1752 | * finding which cases (in the WHENs) applies for each of the | ||
1753 | * combinations. | ||
1754 | */ | ||
1755 | static void do_dvar_values_combinations(struct gl_list_t *disvars, | ||
1756 | struct matching_cases *cases, | ||
1757 | int numdvf, int d, | ||
1758 | int *pos_cases) | ||
1759 | { | ||
1760 | struct dis_discrete *cur_dis; | ||
1761 | int32 *cur_cases; | ||
1762 | int32 ncases, dpo; | ||
1763 | |||
1764 | if(d < numdvf) { | ||
1765 | dpo = d + 1; | ||
1766 | cur_dis = (struct dis_discrete *)(gl_fetch(disvars,d)); | ||
1767 | dis_set_boolean_value(cur_dis,TRUE); | ||
1768 | do_dvar_values_combinations(disvars,cases,numdvf,dpo,pos_cases); | ||
1769 | dis_set_boolean_value(cur_dis,FALSE); | ||
1770 | do_dvar_values_combinations(disvars,cases,numdvf,dpo,pos_cases); | ||
1771 | } else { | ||
1772 | if (d == numdvf) { | ||
1773 | cur_dis = (struct dis_discrete *)(gl_fetch(disvars,d)); | ||
1774 | dis_set_boolean_value(cur_dis,TRUE); | ||
1775 | cur_cases = cases_matching(disvars,&ncases); | ||
1776 | cases[(*pos_cases)].case_list = cur_cases; | ||
1777 | cases[(*pos_cases)].ncases = ncases; | ||
1778 | cases[(*pos_cases)].diff_subregion = 1; | ||
1779 | (*pos_cases)++; | ||
1780 | dis_set_boolean_value(cur_dis,FALSE); | ||
1781 | cur_cases = cases_matching(disvars,&ncases); | ||
1782 | cases[(*pos_cases)].case_list = cur_cases; | ||
1783 | cases[(*pos_cases)].ncases = ncases; | ||
1784 | cases[(*pos_cases)].diff_subregion = 1; | ||
1785 | (*pos_cases)++; | ||
1786 | } else { | ||
1787 | FPRINTF(ASCERR,"ERROR: (slv9) do_dvar_values_combinations\n"); | ||
1788 | FPRINTF(ASCERR," Wrong discrete var index as argument\n"); | ||
1789 | } | ||
1790 | } | ||
1791 | return; | ||
1792 | } | ||
1793 | |||
1794 | |||
1795 | /* | ||
1796 | * Orders of the elements of each array of cases, | ||
1797 | * so that we can compare them easier. | ||
1798 | */ | ||
1799 | static void order_case(int32 *case_list, int32 *newcaselist, int ncases) | ||
1800 | { | ||
1801 | int32 cur_case,pos,tmp_num,c,ind; | ||
1802 | |||
1803 | for (c=1; c<=ncases; c++) { | ||
1804 | tmp_num = 0; | ||
1805 | for (ind=1; ind<=ncases; ind++) { | ||
1806 | cur_case = case_list[ind]; | ||
1807 | if (tmp_num < cur_case) { | ||
1808 | pos = ind; | ||
1809 | tmp_num = cur_case; | ||
1810 | } | ||
1811 | } | ||
1812 | case_list[pos] = 0; | ||
1813 | newcaselist[ncases-c] = tmp_num; | ||
1814 | } | ||
1815 | } | ||
1816 | |||
1817 | |||
1818 | |||
1819 | /* | ||
1820 | * Calls for the ordering of the elements of each array of cases, | ||
1821 | * so that we can compare them easier. | ||
1822 | */ | ||
1823 | static void order_cases(struct matching_cases *cases,int pos_cases) | ||
1824 | { | ||
1825 | int32 *caselist; | ||
1826 | int32 cur_ncase,c; | ||
1827 | int32 *newcaselist; | ||
1828 | |||
1829 | for (c=0; c<pos_cases;c++) { | ||
1830 | caselist = cases[c].case_list; | ||
1831 | cur_ncase = cases[c].ncases; | ||
1832 | if (cur_ncase > 1) { | ||
1833 | newcaselist = create_array(cur_ncase,int32); | ||
1834 | order_case(caselist,newcaselist,cur_ncase); | ||
1835 | cases[c].case_list = newcaselist; | ||
1836 | destroy_array(caselist); | ||
1837 | } else { | ||
1838 | if (cur_ncase == 1) { | ||
1839 | newcaselist = create_array(1,int32); | ||
1840 | newcaselist[0] = caselist[1]; | ||
1841 | cases[c].case_list = newcaselist; | ||
1842 | destroy_array(caselist); | ||
1843 | } | ||
1844 | } | ||
1845 | } | ||
1846 | |||
1847 | } | ||
1848 | |||
1849 | |||
1850 | |||
1851 | /* | ||
1852 | * Compare two arrays of cases (integer numbers). It returns 1 if they are | ||
1853 | * equal, else it returns 0. | ||
1854 | */ | ||
1855 | static int32 compare_case(int32 *cur_set, int32 *comp_set, int cur_ncases) | ||
1856 | { | ||
1857 | int32 cur_case, comp_case, ind; | ||
1858 | |||
1859 | for (ind=0; ind<cur_ncases; ind++) { | ||
1860 | cur_case = cur_set[ind]; | ||
1861 | comp_case = comp_set[ind]; | ||
1862 | if (cur_case != comp_case) { | ||
1863 | return 0; | ||
1864 | } | ||
1865 | } | ||
1866 | return 1; | ||
1867 | } | ||
1868 | |||
1869 | |||
1870 | /* | ||
1871 | * Compare the arrays of cases so that we can find the number of | ||
1872 | * different alternatives (subregions) | ||
1873 | */ | ||
1874 | static void compare_cases(struct matching_cases *cases,int pos_cases) | ||
1875 | { | ||
1876 | int32 *cur_set, *comp_set, cur_ncases, comp_ncases; | ||
1877 | int32 c,d; | ||
1878 | |||
1879 | for (c=0; c<pos_cases; c++) { | ||
1880 | cur_set = cases[c].case_list; | ||
1881 | cur_ncases = cases[c].ncases; | ||
1882 | if (cur_ncases == 0) { | ||
1883 | cases[c].diff_subregion = 0; | ||
1884 | continue; | ||
1885 | } | ||
1886 | for(d=0; d<c; d++) { | ||
1887 | comp_set = cases[d].case_list; | ||
1888 | comp_ncases = cases[d].ncases; | ||
1889 | if (cur_ncases != comp_ncases) { | ||
1890 | continue; | ||
1891 | } else { | ||
1892 | if (compare_case(cur_set,comp_set,cur_ncases)) { | ||
1893 | cases[c].diff_subregion = 0; | ||
1894 | break; | ||
1895 | } | ||
1896 | } | ||
1897 | } | ||
1898 | } | ||
1899 | } | ||
1900 | |||
1901 | |||
1902 | /* | ||
1903 | * Finds if my current point lies at a "real" boundary. By "real" | ||
1904 | * I mean a boundary which really causes a change in the | ||
1905 | * configuration. It returns 0 if the boundary at zero does not | ||
1906 | * affect the configuration. If the configuration is affected, | ||
1907 | * this function will find the number of subregions existing | ||
1908 | * for the current point as well as the cases (in WHENs) corresponding | ||
1909 | * to each of the subregions. At the end, the number of subregions is | ||
1910 | * n_subregions and the cases applying for each of them is stored | ||
1911 | * in the structure subregions. | ||
1912 | */ | ||
1913 | static int32 at_a_boundary(slv_system_t server, SlvClientToken asys, | ||
1914 | int32 *n_subregions, | ||
1915 | struct matching_cases **subregions, | ||
1916 | int32 *cur_subregion, | ||
1917 | struct gl_list_t *disvars) | ||
1918 | { | ||
1919 | slv9_system_t sys; | ||
1920 | struct bnd_boundary **bp, *cur_bnd; | ||
1921 | struct dis_discrete **dv, *cur_dis; | ||
1922 | struct boolean_values bval; | ||
1923 | dis_filter_t dfilter; | ||
1924 | bnd_filter_t bfilter; | ||
1925 | struct matching_cases *cases; | ||
1926 | int32 *bndatzero; | ||
1927 | int32 *dvarmodified; | ||
1928 | int32 *cur_cases; | ||
1929 | int32 *caselist, *newcaselist; | ||
1930 | int32 numbnds, numbndf, b, ind; | ||
1931 | int32 numdvs, numdvf, d; | ||
1932 | int32 cur_ncases, assign_cur_sub; | ||
1933 | int32 pos_cases, comb; | ||
1934 | char *param; | ||
1935 | union param_value u; | ||
1936 | |||
1937 | sys = SLV9(asys); | ||
1938 | check_system(sys); | ||
1939 | |||
1940 | if( sys->blist == NULL ) { | ||
1941 | FPRINTF(ASCERR,"ERROR: (slv9) at_a_boundary\n"); | ||
1942 | FPRINTF(ASCERR," Boundary list was never set.\n"); | ||
1943 | return 0; | ||
1944 | } | ||
1945 | |||
1946 | if( sys->dvlist == NULL ) { | ||
1947 | FPRINTF(ASCERR,"ERROR: (slv9) at_a_boundary\n"); | ||
1948 | FPRINTF(ASCERR," Discrete Variable list was never set.\n"); | ||
1949 | return 0; | ||
1950 | } | ||
1951 | |||
1952 | if (!some_boundaries_at_zero(server,asys)) { | ||
1953 | return 0; | ||
1954 | } | ||
1955 | |||
1956 | bp = sys->blist; | ||
1957 | numbnds = slv_get_num_solvers_bnds(server); | ||
1958 | bfilter.matchbits = (BND_AT_ZERO); | ||
1959 | bfilter.matchvalue = (BND_AT_ZERO); | ||
1960 | numbndf = slv_count_solvers_bnds(server,&bfilter); | ||
1961 | bndatzero = create_array(numbndf,int32); | ||
1962 | ind = 0; | ||
1963 | for (b=0; b<numbnds; b++) { | ||
1964 | cur_bnd = bp[b]; | ||
1965 | bnd_set_perturb(cur_bnd,FALSE); | ||
1966 | if (bnd_at_zero(cur_bnd)) { | ||
1967 | #if SHOW_BOUNDARY_ANALYSIS_DETAILS | ||
1968 | FPRINTF(ASCERR,"boundary at zero = %d\n",b); | ||
1969 | #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */ | ||
1970 | bndatzero[ind] = b; | ||
1971 | ind++; | ||
1972 | } | ||
1973 | } | ||
1974 | |||
1975 | dv = sys->dvlist; | ||
1976 | numdvs = slv_get_num_solvers_dvars(server); | ||
1977 | bval.cur_val = create_array(numdvs,int32); | ||
1978 | bval.pre_val = create_array(numdvs,int32); | ||
1979 | |||
1980 | for (d=0; d<numdvs; d++) { | ||
1981 | cur_dis = dv[d]; | ||
1982 | dis_set_val_modified(cur_dis,FALSE); | ||
1983 | bval.cur_val[d] = dis_value(cur_dis); | ||
1984 | bval.pre_val[d] = dis_previous_value(cur_dis); | ||
1985 | } | ||
1986 | |||
1987 | #if SHOW_BOUNDARY_ANALYSIS_DETAILS | ||
1988 | FPRINTF(ASCERR,"Executing combinatorial perturbation of boundaries\n"); | ||
1989 | #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */ | ||
1990 | |||
1991 | /* | ||
1992 | * Setting the value of the perturbation mode flag in the logical solver | ||
1993 | * to 1. | ||
1994 | * PERTURB_BOUNDARY is a boolean parameter of the logical solver | ||
1995 | * LRSlv. This parameter tells the solver whether it should change | ||
1996 | * the truth value of the SATISFIED terms or not (only for the | ||
1997 | * boundaries specified). This trick is important while finding | ||
1998 | * the number of subregions around a/several boundary(ies). | ||
1999 | */ | ||
2000 | param = "perturbboundaries"; | ||
2001 | u.b = 1; | ||
2002 | set_param_in_solver(server,LOGICAL_SOLVER,bool_parm,param,&u); | ||
2003 | |||
2004 | ind = 0; | ||
2005 | do_perturbation_combinations(server,&(bval),bp,dv,numdvs, | ||
2006 | bndatzero,ind,numbndf); | ||
2007 | /* | ||
2008 | * Setting the value of the perturbation mode flag in the logical solver | ||
2009 | * to 0. | ||
2010 | */ | ||
2011 | u.b = 0; | ||
2012 | set_param_in_solver(server,LOGICAL_SOLVER,bool_parm,param,&u); | ||
2013 | |||
2014 | destroy_array(bndatzero); | ||
2015 | |||
2016 | dfilter.matchbits = (DIS_VAL_MODIFIED); | ||
2017 | dfilter.matchvalue = (DIS_VAL_MODIFIED); | ||
2018 | numdvf = slv_count_solvers_dvars(server,&dfilter); | ||
2019 | |||
2020 | if (numdvf == 0) { | ||
2021 | FPRINTF(ASCERR,"Not really at a boundary\n"); | ||
2022 | for (d=0; d<numdvs; d++) { | ||
2023 | cur_dis = dv[d]; | ||
2024 | dis_set_boolean_value(cur_dis,bval.cur_val[d]); | ||
2025 | dis_set_value(cur_dis,bval.cur_val[d]); | ||
2026 | dis_set_previous_value(cur_dis,bval.pre_val[d]); | ||
2027 | } | ||
2028 | destroy_array(bval.cur_val); | ||
2029 | destroy_array(bval.pre_val); | ||
2030 | return 0; | ||
2031 | } | ||
2032 | |||
2033 | dvarmodified = create_array(numdvf,int32); | ||
2034 | ind = 0; | ||
2035 | for (d=0; d<numdvs; d++) { | ||
2036 | cur_dis = dv[d]; | ||
2037 | if(dis_val_modified(cur_dis)) { | ||
2038 | dvarmodified[ind] = d; | ||
2039 | gl_append_ptr(disvars,cur_dis); | ||
2040 | dis_set_val_modified(cur_dis,FALSE); | ||
2041 | ind++; | ||
2042 | } | ||
2043 | } | ||
2044 | |||
2045 | for (d=0; d<numdvs; d++) { | ||
2046 | cur_dis = dv[d]; | ||
2047 | dis_set_boolean_value(cur_dis,bval.cur_val[d]); | ||
2048 | dis_set_value(cur_dis,bval.cur_val[d]); | ||
2049 | dis_set_previous_value(cur_dis,bval.pre_val[d]); | ||
2050 | } | ||
2051 | |||
2052 | pos_cases = 1; | ||
2053 | for (d = 1; d<=numdvf; d++) { | ||
2054 | pos_cases = pos_cases * 2; | ||
2055 | } | ||
2056 | |||
2057 | cases = (struct matching_cases *) | ||
2058 | (ascmalloc((pos_cases)*sizeof(struct matching_cases))); | ||
2059 | |||
2060 | #if SHOW_BOUNDARY_ANALYSIS_DETAILS | ||
2061 | FPRINTF(ASCERR,"Executing combinatorial search for subregions \n"); | ||
2062 | #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */ | ||
2063 | |||
2064 | d = 1; | ||
2065 | comb = 0; | ||
2066 | do_dvar_values_combinations(disvars,cases,numdvf,d,&(comb)); | ||
2067 | |||
2068 | order_cases(cases,pos_cases); | ||
2069 | compare_cases(cases,pos_cases); | ||
2070 | |||
2071 | (*n_subregions) = 0; | ||
2072 | for(comb=0; comb<pos_cases;comb++) { | ||
2073 | if(cases[comb].diff_subregion) { | ||
2074 | (*n_subregions)++; | ||
2075 | } | ||
2076 | } | ||
2077 | |||
2078 | if ((*n_subregions)==0) { | ||
2079 | FPRINTF(ASCERR,"ERROR: at least one subregion must be found\n"); | ||
2080 | for (d=0; d<numdvs; d++) { | ||
2081 | cur_dis = dv[d]; | ||
2082 | dis_set_boolean_value(cur_dis,bval.cur_val[d]); | ||
2083 | dis_set_value(cur_dis,bval.cur_val[d]); | ||
2084 | dis_set_previous_value(cur_dis,bval.pre_val[d]); | ||
2085 | } | ||
2086 | destroy_array(bval.cur_val); | ||
2087 | destroy_array(bval.pre_val); | ||
2088 | for(comb=0; comb<pos_cases;comb++) { | ||
2089 | destroy_array(cases[comb].case_list); | ||
2090 | } | ||
2091 | destroy_array(cases); | ||
2092 | return 0; | ||
2093 | } | ||
2094 | |||
2095 | if ((*n_subregions)==1) { | ||
2096 | FPRINTF(ASCERR,"Not really at a boundary\n"); | ||
2097 | for (d=0; d<numdvs; d++) { | ||
2098 | cur_dis = dv[d]; | ||
2099 | dis_set_boolean_value(cur_dis,bval.cur_val[d]); | ||
2100 | dis_set_value(cur_dis,bval.cur_val[d]); | ||
2101 | dis_set_previous_value(cur_dis,bval.pre_val[d]); | ||
2102 | } | ||
2103 | destroy_array(bval.cur_val); | ||
2104 | destroy_array(bval.pre_val); | ||
2105 | for(comb=0; comb<pos_cases;comb++) { | ||
2106 | destroy_array(cases[comb].case_list); | ||
2107 | } | ||
2108 | destroy_array(cases); | ||
2109 | return 0; | ||
2110 | } | ||
2111 | |||
2112 | if ((*n_subregions) > 0) { | ||
2113 | (*subregions) = (struct matching_cases *) | ||
2114 | (ascmalloc(((*n_subregions))*sizeof(struct matching_cases))); | ||
2115 | (*n_subregions) = 0; | ||
2116 | for(comb=0; comb<pos_cases;comb++) { | ||
2117 | if(cases[comb].diff_subregion) { | ||
2118 | (*subregions)[(*n_subregions)].case_list = cases[comb].case_list; | ||
2119 | cases[comb].case_list = NULL; | ||
2120 | (*subregions)[(*n_subregions)].ncases = cases[comb].ncases; | ||
2121 | cases[comb].ncases = 0; | ||
2122 | (*subregions)[(*n_subregions)].diff_subregion = 1; | ||
2123 | (*n_subregions)++; | ||
2124 | } | ||
2125 | } | ||
2126 | } | ||
2127 | |||
2128 | for(comb=0; comb<pos_cases;comb++) { | ||
2129 | destroy_array(cases[comb].case_list); | ||
2130 | } | ||
2131 | destroy_array(cases); | ||
2132 | |||
2133 | |||
2134 | assign_cur_sub = 0; | ||
2135 | /* | ||
2136 | * Finding the subregion corresponding to the "original" configuration | ||
2137 | */ | ||
2138 | for (d=0; d<numdvs; d++) { | ||
2139 | cur_dis = dv[d]; | ||
2140 | dis_set_boolean_value(cur_dis,bval.cur_val[d]); | ||
2141 | dis_set_value(cur_dis,bval.cur_val[d]); | ||
2142 | dis_set_previous_value(cur_dis,bval.pre_val[d]); | ||
2143 | } | ||
2144 | cur_cases = cases_matching(disvars,&cur_ncases); | ||
2145 | caselist = cur_cases; | ||
2146 | if (cur_ncases > 1) { | ||
2147 | newcaselist = create_array(cur_ncases,int32); | ||
2148 | order_case(caselist,newcaselist,cur_ncases); | ||
2149 | cur_cases = newcaselist; | ||
2150 | destroy_array(caselist); | ||
2151 | } else { | ||
2152 | if (cur_ncases == 1) { | ||
2153 | newcaselist = create_array(1,int32); | ||
2154 | newcaselist[0] = caselist[1]; | ||
2155 | cur_cases = newcaselist; | ||
2156 | destroy_array(caselist); | ||
2157 | } | ||
2158 | } | ||
2159 | for(comb=0; comb<(*n_subregions);comb++) { | ||
2160 | if ((*subregions)[comb].ncases == cur_ncases) { | ||
2161 | if(compare_case((*subregions)[comb].case_list,cur_cases,cur_ncases)) { | ||
2162 | (*cur_subregion) = comb; | ||
2163 | assign_cur_sub = 1; | ||
2164 | break; | ||
2165 | } | ||
2166 | } | ||
2167 | } | ||
2168 | |||
2169 | if (!assign_cur_sub) { | ||
2170 | FPRINTF(ASCERR,"PANIC: original configuration not found\n"); | ||
2171 | } | ||
2172 | |||
2173 | destroy_array(cur_cases); | ||
2174 | destroy_array(dvarmodified); | ||
2175 | destroy_array(bval.cur_val); | ||
2176 | destroy_array(bval.pre_val); | ||
2177 | return 1; | ||
2178 | } | ||
2179 | |||
2180 | |||
2181 | /* | ||
2182 | * If some boundary(ies) has been crossed in the iterative scheme, | ||
2183 | * this function finds the boundary crossed (the first one, if many). | ||
2184 | * It returns the factor (less than 1) by which the step length has | ||
2185 | * to be multiplied son that the new point will lie precisely | ||
2186 | * at that boundary. This factor is found by using the method of | ||
2187 | * bisection | ||
2188 | */ | ||
2189 | static real64 return_to_first_boundary(slv_system_t server, | ||
2190 | SlvClientToken asys, | ||
2191 | struct real_values *rvalues, | ||
2192 | var_filter_t *vfilter) | ||
2193 | { | ||
2194 | slv9_system_t sys; | ||
2195 | struct bnd_boundary **bp, *cur_bnd; | ||
2196 | struct var_variable **incidences, **bnd_incidences; | ||
2197 | struct var_variable *cur_var; | ||
2198 | bnd_filter_t bfilter; | ||
2199 | struct boolean_values bval; | ||
2200 | real64 factor,fup,flo,newvalue; | ||
2201 | int32 *bndcrossed; | ||
2202 | int32 *inc_vars; | ||
2203 | int32 count,n_incidences,inc,conv_flag,still_crossed; | ||
2204 | int32 numbnds,numbndf,b,ind; | ||
2205 | int32 iter,n_iterations; | ||
2206 | FILE *lif; | ||
2207 | |||
2208 | sys = SLV9(asys); | ||
2209 | check_system(sys); | ||
2210 | lif = LIF(sys); | ||
2211 | |||
2212 | if( sys->blist == NULL ) { | ||
2213 | FPRINTF(ASCERR,"ERROR: (slv9) return_to_first_boundary\n"); | ||
2214 | FPRINTF(ASCERR," Boundary list was never set.\n"); | ||
2215 | return 1.0; | ||
2216 | } | ||
2217 | |||
2218 | if (!some_boundaries_crossed(server,asys)) { | ||
2219 | return 1.0; | ||
2220 | } | ||
2221 | |||
2222 | bp = sys->blist; | ||
2223 | numbnds = slv_get_num_solvers_bnds(server); | ||
2224 | bfilter.matchbits = (BND_CROSSED); | ||
2225 | bfilter.matchvalue = (BND_CROSSED); | ||
2226 | numbndf = slv_count_solvers_bnds(server,&bfilter); | ||
2227 | bndcrossed = create_array(numbndf,int32); | ||
2228 | bval.cur_val = create_array(numbndf,int32); | ||
2229 | bval.pre_val = create_array(numbndf,int32); | ||
2230 | ind = 0; | ||
2231 | for (b=0; b<numbnds; b++) { | ||
2232 | cur_bnd = bp[b]; | ||
2233 | if (bnd_crossed(cur_bnd)) { | ||
2234 | bndcrossed[ind] = b; | ||
2235 | bval.cur_val[ind] = bnd_status_cur(cur_bnd); | ||
2236 | bval.pre_val[ind] = bnd_status_pre(cur_bnd); | ||
2237 | ind++; | ||
2238 | } | ||
2239 | } | ||
2240 | |||
2241 | count = 0; | ||
2242 | for (b=0; b<numbndf; b++) { | ||
2243 | cur_bnd = bp[bndcrossed[b]]; | ||
2244 | n_incidences = bnd_n_real_incidences(cur_bnd); | ||
2245 | count = count + n_incidences; | ||
2246 | } | ||
2247 | |||
2248 | incidences = (struct var_variable **) | ||
2249 | ( ascmalloc((count)*sizeof(struct var_variable *))); | ||
2250 | inc_vars = create_array(count,int32); | ||
2251 | count = 0; | ||
2252 | for (b=0; b<numbndf; b++) { | ||
2253 | cur_bnd = bp[bndcrossed[b]]; | ||
2254 | bnd_incidences = bnd_real_incidence(cur_bnd); | ||
2255 | n_incidences = bnd_n_real_incidences(cur_bnd); | ||
2256 | #if SHOW_BOUNDARY_ANALYSIS_DETAILS | ||
2257 | FPRINTF(lif,"boundary crossed = %d\n",bndcrossed[b]); | ||
2258 | FPRINTF(lif,"previous boundary status = %d\n",bval.pre_val[b]); | ||
2259 | FPRINTF(lif,"current boundary status = %d\n",bval.cur_val[b]); | ||
2260 | #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */ | ||
2261 | for (inc=0; inc<n_incidences; inc++) { | ||
2262 | incidences[count] = bnd_incidences[inc]; | ||
2263 | inc_vars[count] = var_mindex(incidences[count]); | ||
2264 | count++; | ||
2265 | } | ||
2266 | } | ||
2267 | |||
2268 | /* bisection to find first boundary crossed */ | ||
2269 | fup = 1.0; | ||
2270 | flo = 0.0; | ||
2271 | conv_flag = 0; | ||
2272 | iter = 0; | ||
2273 | |||
2274 | /* | ||
2275 | * Maximum number of bisection iterations. This must be modified | ||
2276 | * so that it becomes a parameter to be defined by the user | ||
2277 | */ | ||
2278 | n_iterations = ITER_BIS_LIMIT; | ||
2279 | |||
2280 | #if SHOW_BOUNDARY_ANALYSIS_DETAILS | ||
2281 | for (inc=0; inc<count; inc++) { | ||
2282 | cur_var = incidences[inc]; | ||
2283 | if(var_apply_filter(cur_var,vfilter)) { | ||
2284 | FPRINTF(lif,"Variable "); | ||
2285 | print_var_name(lif,sys,cur_var); PUTC('\n',lif); | ||
2286 | FPRINTF(lif, | ||
2287 | "previous value = %f\n",rvalues->pre_values[inc_vars[inc]]); | ||
2288 | FPRINTF(lif,"current value = %f\n",rvalues->cur_values[inc_vars[inc]]); | ||
2289 | } | ||
2290 | } | ||
2291 | #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */ | ||
2292 | |||
2293 | while (conv_flag == 0) { | ||
2294 | iter++; | ||
2295 | if (iter>n_iterations) { | ||
2296 | FPRINTF(ASCERR,"ERROR: (slv9) return_to_first_boundary\n"); | ||
2297 | FPRINTF(ASCERR,"Could not find the first boundary crossed \n"); | ||
2298 | FPRINTF(ASCERR,"Returning the last factor calculated\n"); | ||
2299 | break; | ||
2300 | } | ||
2301 | still_crossed = 0; | ||
2302 | factor = ( fup + flo ) / 2.0; | ||
2303 | #if SHOW_BISECTION_DETAILS | ||
2304 | FPRINTF(lif,"fup = %f\n",fup); | ||
2305 | FPRINTF(lif,"flo = %f\n",flo); | ||
2306 | FPRINTF(lif,"factor = %f\n",factor); | ||
2307 | #endif /* SHOW_BISECTION_DETAILS */ | ||
2308 | for (inc=0; inc<count; inc++) { | ||
2309 | cur_var = incidences[inc]; | ||
2310 | if(var_apply_filter(cur_var,vfilter)) { | ||
2311 | newvalue = rvalues->pre_values[inc_vars[inc]] + factor * | ||
2312 | ( rvalues->cur_values[inc_vars[inc]] - | ||
2313 | rvalues->pre_values[inc_vars[inc]] ); | ||
2314 | var_set_value(cur_var,newvalue); | ||
2315 | #if SHOW_BISECTION_DETAILS | ||
2316 | FPRINTF(lif,"Variable "); | ||
2317 | print_var_name(lif,sys,cur_var); PUTC('\n',lif); | ||
2318 | FPRINTF(lif,"value after factor = %f\n",newvalue); | ||
2319 | #endif /* SHOW_BISECTION_DETAILS */ | ||
2320 | } | ||
2321 | } | ||
2322 | |||
2323 | update_boundaries(server,asys); | ||
2324 | for (b=0; b<numbndf; b++) { | ||
2325 | cur_bnd = bp[bndcrossed[b]]; | ||
2326 | #if SHOW_BISECTION_DETAILS | ||
2327 | FPRINTF(lif,"previous status = %d\n", bval.pre_val[b]); | ||
2328 | FPRINTF(lif,"status aftert factor = %d\n",bnd_status_cur(cur_bnd)); | ||
2329 | #endif /* SHOW_BISECTION_DETAILS */ | ||
2330 | if ( bnd_status_cur(cur_bnd) != bval.pre_val[b] ) { | ||
2331 | still_crossed = 1; | ||
2332 | } | ||
2333 | } | ||
2334 | #if SHOW_BISECTION_DETAILS | ||
2335 | FPRINTF(lif,"still_crossed = %d\n",still_crossed); | ||
2336 | #endif /* SHOW_BISECTION_DETAILS */ | ||
2337 | if (still_crossed) { | ||
2338 | fup = factor; | ||
2339 | } else { | ||
2340 | flo = factor; | ||
2341 | for (b=0; b<numbndf; b++) { | ||
2342 | cur_bnd = bp[bndcrossed[b]]; | ||
2343 | bnd_set_pre_status(cur_bnd,bval.pre_val[b]); | ||
2344 | bnd_set_cur_status(cur_bnd,bval.pre_val[b]); | ||
2345 | if (bnd_at_zero(cur_bnd)) { | ||
2346 | #if SHOW_BOUNDARY_ANALYSIS_DETAILS | ||
2347 | FPRINTF(ASCERR,"boundary at zero = %d\n",bndcrossed[b]); | ||
2348 | FPRINTF(lif,"factor = %f\n",factor); | ||
2349 | for (inc=0; inc<count; inc++) { | ||
2350 | cur_var = incidences[inc]; | ||
2351 | if(var_apply_filter(cur_var,vfilter)) { | ||
2352 | FPRINTF(lif,"Variable "); | ||
2353 | print_var_name(lif,sys,cur_var); PUTC('\n',lif); | ||
2354 | FPRINTF(lif,"value after factor = %f\n",var_value(cur_var)); | ||
2355 | } | ||
2356 | } | ||
2357 | #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */ | ||
2358 | conv_flag = 1; | ||
2359 | } | ||
2360 | } | ||
2361 | } | ||
2362 | } | ||
2363 | destroy_array(bndcrossed); | ||
2364 | destroy_array(inc_vars); | ||
2365 | destroy_array(bval.cur_val); | ||
2366 | destroy_array(bval.pre_val); | ||
2367 | destroy_array(incidences); | ||
2368 | |||
2369 | return factor; | ||
2370 | } | ||
2371 | |||
2372 | |||
2373 | /* | ||
2374 | * Storing values of real variables. | ||
2375 | * --------------------------------- | ||
2376 | * | ||
2377 | * We use the master list of variables since its order does not change | ||
2378 | * and it is given by the master index. We do not touch the master list, | ||
2379 | * we only use its order. | ||
2380 | */ | ||
2381 | |||
2382 | /* | ||
2383 | * Store the values of the var_variables before a newton-like iteration | ||
2384 | */ | ||
2385 | static void store_real_pre_values(slv_system_t server, | ||
2386 | struct real_values *rvalues) | ||
2387 | { | ||
2388 | struct var_variable **master; | ||
2389 | struct var_variable *var; | ||
2390 | int v, vlen; | ||
2391 | |||
2392 | master = slv_get_master_var_list(server); | ||
2393 | vlen = slv_get_num_master_vars(server); | ||
2394 | |||
2395 | rvalues->pre_values = create_array(vlen,real64); | ||
2396 | |||
2397 | for (v=0; v<vlen; v++) { | ||
2398 | var = master[v]; | ||
2399 | rvalues->pre_values[v] = var_value(var); | ||
2400 | } | ||
2401 | } | ||
2402 | |||
2403 | /* | ||
2404 | * Store the values of the var_variables after a newton-like iteration | ||
2405 | */ | ||
2406 | static void store_real_cur_values(slv_system_t server, | ||
2407 | struct real_values *rvalues) | ||
2408 | { | ||
2409 | struct var_variable **master; | ||
2410 | struct var_variable *var; | ||
2411 | int v, vlen; | ||
2412 | |||
2413 | master = slv_get_master_var_list(server); | ||
2414 | vlen = slv_get_num_master_vars(server); | ||
2415 | |||
2416 | rvalues->cur_values = create_array(vlen,real64); | ||
2417 | |||
2418 | for (v=0; v<vlen; v++) { | ||
2419 | var = master[v]; | ||
2420 | rvalues->cur_values[v] = var_value(var); | ||
2421 | } | ||
2422 | } | ||
2423 | |||
2424 | /* | ||
2425 | * After the length of the step has been modified so that the current point | ||
2426 | * lies at a boundary, the values of all the variables is updated so that | ||
2427 | * they all reduce the length of their step by the same factor. | ||
2428 | */ | ||
2429 | static void update_real_var_values(slv_system_t server, | ||
2430 | struct real_values *rvalues, | ||
2431 | var_filter_t *vfilter, real64 factor) | ||
2432 | { | ||
2433 | struct var_variable **master; | ||
2434 | struct var_variable *var; | ||
2435 | real64 newvalue; | ||
2436 | int v, vlen; | ||
2437 | |||
2438 | master = slv_get_master_var_list(server); | ||
2439 | vlen = slv_get_num_master_vars(server); | ||
2440 | |||
2441 | for (v=0; v<vlen; v++) { | ||
2442 | var = master[v]; | ||
2443 | if(var_apply_filter(var,vfilter)) { | ||
2444 | newvalue = rvalues->pre_values[v] + | ||
2445 | factor * (rvalues->cur_values[v] - rvalues->pre_values[v]); | ||
2446 | var_set_value(var,newvalue); | ||
2447 | } | ||
2448 | } | ||
2449 | destroy_array(rvalues->cur_values); | ||
2450 | destroy_array(rvalues->pre_values); | ||
2451 | } | ||
2452 | |||
2453 | |||
2454 | /* | ||
2455 | * Set the flagbit NONBASIC for all the variables in the list | ||
2456 | * to the value passed as argument | ||
2457 | */ | ||
2458 | static void set_nonbasic_status_in_var_list(slv_system_t server, | ||
2459 | uint32 value) | ||
2460 | { | ||
2461 | struct var_variable **master; | ||
2462 | struct var_variable *var; | ||
2463 | int v, vlen; | ||
2464 | |||
2465 | master = slv_get_master_var_list(server); | ||
2466 | vlen = slv_get_num_master_vars(server); | ||
2467 | |||
2468 | for (v=0; v<vlen; v++) { | ||
2469 | var = master[v]; | ||
2470 | var_set_nonbasic(var,value); | ||
2471 | } | ||
2472 | } | ||
2473 | |||
2474 | |||
2475 | /* | ||
2476 | * After the length of the step has been modified so that the current point | ||
2477 | * lies at a boundary, the residuals of the equations are updated. | ||
2478 | */ | ||
2479 | static void update_relations_residuals(slv_system_t server) | ||
2480 | { | ||
2481 | struct rel_relation **master; | ||
2482 | struct rel_relation *rel; | ||
2483 | rel_filter_t rfilter; | ||
2484 | real64 resid; | ||
2485 | int32 r, rlen, status; | ||
2486 | |||
2487 | master = slv_get_master_rel_list(server); | ||
2488 | rlen = slv_get_num_master_rels(server); | ||
2489 | |||
2490 | rfilter.matchbits = (REL_INCLUDED | REL_EQUALITY); | ||
2491 | rfilter.matchvalue = (REL_INCLUDED | REL_EQUALITY); | ||
2492 | |||
2493 | Asc_SignalHandlerPush(SIGFPE,SIG_IGN); | ||
2494 | for (r=0; r<rlen; r++) { | ||
2495 | rel = master[r]; | ||
2496 | if(rel_apply_filter(rel,&rfilter)) { | ||
2497 | resid = relman_eval(rel,&status,1); | ||
2498 | } | ||
2499 | } | ||
2500 | Asc_SignalHandlerPop(SIGFPE,SIG_IGN); | ||
2501 | } | ||
2502 | |||
2503 | |||
2504 | /* | ||
2505 | * Optimization subroutines for CONOPT | ||
2506 | * --------------------------------- | ||
2507 | */ | ||
2508 | |||
2509 | /* | ||
2510 | * COIRMS Based on the information provided in Coispz, CONOPT will | ||
2511 | * allocate the number of vectors into which the user can define | ||
2512 | * the details of the model. The details of the model are defined | ||
2513 | * here. | ||
2514 | * | ||
2515 | * COIRMS(lower, curr, upper, vsta, type,rhs, fv, esta, colsta, | ||
2516 | * rowno, value, nlflag, n, m, n1, nz, usrmem) | ||
2517 | * | ||
2518 | * lower - lower bounds on the variables | ||
2519 | * curr - intial values of the variables | ||
2520 | * upper - upper bounds on the variables | ||
2521 | * vsta - initial status of the variable(o nonbasic, 1 basic) | ||
2522 | * type - types of equations (0 equality,1 greater,2 less) | ||
2523 | * rhs - values of the right hand sides | ||
2524 | * fv - sum of the nonlinear terms in the initial point | ||
2525 | * esta - initial status of the slack in the constraint (nonbasic,basic) | ||
2526 | * colsta- start of column pointers | ||
2527 | * rowno - row or equation numbers of the nonzeros | ||
2528 | * value - values of the jacobian elements | ||
2529 | * nlflag- nonlinearity flags(0 nonzero constant,1 varying) | ||
2530 | * n - number of variables | ||
2531 | * m - number of constraints | ||
2532 | * n1 - n+1 | ||
2533 | * nz - number of jacobian elements | ||
2534 | * usrmem- user memory defined by conopt | ||
2535 | */ | ||
2536 | static void slv9_coirms(real64 *lower, real64 *curr, real64 *upper, | ||
2537 | int32 *vsta, int32 *type, real64 *rhs, real64 *fv, | ||
2538 | int32 *esta, int32 *colsta, int32 *rowno, | ||
2539 | real64 *value, int32 *nlflag, int32 *n, int32 *m, | ||
2540 | int32 *n1, int32 *nz, real64 *usrmem) | ||
2541 | { | ||
2542 | slv9_system_t sys; | ||
2543 | struct var_variable *var; | ||
2544 | struct var_variable **varlist; | ||
2545 | struct opt_matrix *coeff_matrix; | ||
2546 | static var_filter_t vfilter; | ||
2547 | real64 obj_val, deriv; | ||
2548 | real64 nominal, up, low, uplow; | ||
2549 | int32 num_var, n_subregions, c, num_eqns; | ||
2550 | int32 numnz, eq; | ||
2551 | int32 count, totvar; | ||
2552 | |||
2553 | /* | ||
2554 | * stop gcc whining about unused parameters | ||
2555 | */ | ||
2556 | (void)vsta; | ||
2557 | (void)esta; | ||
2558 | |||
2559 | sys = (slv9_system_t)usrmem; | ||
2560 | n_subregions = sys->subregions; | ||
2561 | coeff_matrix = sys->coeff_matrix; | ||
2562 | num_var = (*n) - n_subregions; | ||
2563 | num_eqns = num_var + 1; | ||
2564 | |||
2565 | vfilter.matchbits = (VAR_ACTIVE_AT_BND | VAR_INCIDENT | ||
2566 | | VAR_SVAR | VAR_FIXED); | ||
2567 | vfilter.matchvalue = (VAR_ACTIVE_AT_BND | VAR_INCIDENT | VAR_SVAR); | ||
2568 | varlist = sys->mvlist; | ||
2569 | totvar = sys->mvtot; | ||
2570 | |||
2571 | /* | ||
2572 | * Variables: Current Value, lower value and upper value. Note that for | ||
2573 | * this problem the variables are the vector of steps dx. So we "invent" | ||
2574 | * approximations for the bounds based on the bounds of the real | ||
2575 | * variables of the problem. The use of the parameter INFINITY is | ||
2576 | * Hack to keep CONOPT from complaining for large bounds. | ||
2577 | */ | ||
2578 | |||
2579 | count = 0; | ||
2580 | for (c=0; c<totvar; c++) { | ||
2581 | var = varlist[c]; | ||
2582 | if (var_apply_filter(var,&vfilter)) { | ||
2583 | nominal = var_nominal(var); | ||
2584 | low = var_lower_bound(var); | ||
2585 | up = var_upper_bound(var); | ||
2586 | uplow = fabs( up - low); | ||
2587 | lower[count] = -uplow > -INFINITY ? -uplow : -0.5*INFINITY; | ||
2588 | upper[count] = uplow < INFINITY ? uplow : 0.5*INFINITY; | ||
2589 | curr[count] = 0.5 * nominal; | ||
2590 | count++; | ||
2591 | } | ||
2592 | } | ||
2593 | /* alphas for each subregion */ | ||
2594 | for (c=count; c<(*n); c++) { | ||
2595 | lower[c] = 0.0; | ||
2596 | upper[c] = 1.0; | ||
2597 | curr[c] = 1.0; | ||
2598 | } | ||
2599 | |||
2600 | |||
2601 | /* | ||
2602 | * vsta not in use since STATOK, ipsz[14], is zero | ||
2603 | */ | ||
2604 | |||
2605 | /* | ||
2606 | * All the equations, but the last row (which is the objective), are | ||
2607 | * equalities. | ||
2608 | */ | ||
2609 | for (c = 0; c < (*m); c++) { | ||
2610 | type[c] = 0; | ||
2611 | } | ||
2612 | type[(*m)-1] = 3; | ||
2613 | |||
2614 | |||
2615 | /* | ||
2616 | * RHS. It is zero for all the equations except the summation of | ||
2617 | * alphas, whose RHS is one. | ||
2618 | */ | ||
2619 | for (c = 0; c < (*m); c++) { | ||
2620 | rhs[c] = 0; | ||
2621 | } | ||
2622 | rhs[(*m)-2] = 1.0; | ||
2623 | |||
2624 | /* | ||
2625 | * fv =0 for all linear relations. For the objective is the two | ||
2626 | * norm | ||
2627 | */ | ||
2628 | for (c = 0; c < (*m); c++) { | ||
2629 | fv[c] = 0; | ||
2630 | } | ||
2631 | obj_val = 0.0; | ||
2632 | for (c = 0; c<num_var; c++) { | ||
2633 | obj_val = obj_val + (curr[c] * curr[c]); | ||
2634 | } | ||
2635 | fv[(*m)-1] = obj_val; | ||
2636 | |||
2637 | /* | ||
2638 | * esta not used since STATOK is zero | ||
2639 | */ | ||
2640 | |||
2641 | |||
2642 | /* | ||
2643 | * For the following parameters, it is important ot see that: | ||
2644 | * 1) The values for the rows and nonzeros that conopt wants start | ||
2645 | * with 1, not with 0. | ||
2646 | * 2) The indeces of the arrays that we are using in the C side start | ||
2647 | * with 0. | ||
2648 | */ | ||
2649 | |||
2650 | /* | ||
2651 | * colsta | ||
2652 | */ | ||
2653 | |||
2654 | for (c=0; c<num_var; c++) { | ||
2655 | colsta[c] = 1 + 2 * c; | ||
2656 | } | ||
2657 | |||
2658 | for (c=num_var; c<(*n); c++) { | ||
2659 | colsta[c] = 2 * num_var + num_eqns * (c - num_var |