/[ascend]/trunk/base/generic/solver/slv9.c
ViewVC logotype

Contents of /trunk/base/generic/solver/slv9.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 804 - (show annotations) (download) (as text)
Fri Aug 4 05:54:34 2006 UTC (18 years, 2 months ago) by johnpye
File MIME type: text/x-csrc
File size: 165329 byte(s)
In slv9, made changes to keep CONOPT from complaining. CMSlv still not working as expected though.
Decreased required version of Bison to 2.0.
Switched search path for CONOPT on Linux to the CONOPT_PATH env var
(LD_LIBRARY_PATH was being interfered with when ASC_DEV=1).
Some other debug message changes.
1 /* ASCEND modelling environment
2 Copyright (C) 2006 Carnegie Mellon University
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 *//**
19 @file
20 Conditional Modeling Solver (CMSlv) module.
21 *//*
22 Conditional Modeling Solver
23 by Vicente Rico-Ramirez
24 Last in CVS: $Revision: 1.22 $ $Date: 2000/01/25 02:27:58 $ $Author: ballan $
25 */
26
27 #include <math.h>
28
29 #include <utilities/config.h>
30 #include <utilities/ascConfig.h>
31 #include <utilities/ascSignal.h>
32 #include <utilities/ascMalloc.h>
33 #include <general/tm_time.h>
34 #include <utilities/mem.h>
35 #include <compiler/compiler.h>
36 #include <compiler/instance_enum.h>
37 #include <general/list.h>
38 #include <compiler/fractions.h>
39 #include <compiler/dimen.h>
40 #include <compiler/functype.h>
41 #include <compiler/func.h>
42 #include "mtx.h"
43 #include "mtx_reorder.h"
44 #include "linsol.h"
45 #include "linsolqr.h"
46 #include "slv_types.h"
47 #include "var.h"
48 #include "rel.h"
49 #include "discrete.h"
50 #include "conditional.h"
51 #include "logrel.h"
52 #include "bnd.h"
53 #include "calc.h"
54 #include "relman.h"
55 #include "logrelman.h"
56 #include "bndman.h"
57 #include "cond_config.h"
58 #include "slv_common.h"
59 #include "slv_client.h"
60 #include "slv9.h"
61 #include "slv_stdcalls.h"
62 #include "slvDOF.h"
63
64 #ifdef ASC_WITH_CONOPT
65 # include <solver/conopt.h>
66 #else
67 # define MAX_INT MAXINT
68 # define MAX_REAL MAXDOUBLE
69 #endif
70
71 #if !defined(STATIC_CMSLV) && !defined(DYNAMIC_CMSLV)
72 int slv9_register(SlvFunctionsT *f)
73 {
74 UNUSED_PARAMETER(f);
75
76 ERROR_REPORTER_HERE(ASC_PROG_ERR,"CMSlv was not built in this copy of ASCEND");
77 return 1;
78 }
79 #else /* either STATIC_CMSLV or DYNAMIC_CMSLV is defined */
80
81 #ifdef DYNAMIC_CMSLV
82 /* do dynamic loading stuff. yeah, right */
83
84 #else /* following is used if STATIC_CMSLV is defined */
85
86
87 /*
88 * definitions to enable/disable the output of partial results in
89 * the solution of a problem
90 */
91 #define DEBUG FALSE
92 #define SHOW_LOGICAL_DETAILS FALSE
93 #define SHOW_BOUNDARY_ANALYSIS_DETAILS FALSE
94 #define SHOW_OPTIMIZATION_DETAILS FALSE
95 #define SHOW_BISECTION_DETAILS FALSE
96 #define SHOW_LINEAR_SEARCH_DETAILS FALSE
97 #define SHOW_LAGRANGE_DETAILS FALSE
98 #define DEBUG_CONSISTENCY FALSE
99 #define TEST_CONSISTENCY FALSE
100 #define USE_CONSISTENCY FALSE
101
102 /*
103 * system definitions
104 */
105 #define SLV9(s) ((slv9_system_t)(s))
106 #define SERVER (sys->slv)
107 #define slv9_PA_SIZE 26 /* MUST INCREMENT WHEN ADDING PARAMETERS */
108 #define LOGSOLVER_OPTION_PTR (sys->parm_array[0])
109 #define LOGSOLVER_OPTION ((*(char **)LOGSOLVER_OPTION_PTR))
110 #define NONLISOLVER_OPTION_PTR (sys->parm_array[1])
111 #define NONLISOLVER_OPTION ((*(char **)NONLISOLVER_OPTION_PTR))
112 #define OPTSOLVER_OPTION_PTR (sys->parm_array[2])
113 #define OPTSOLVER_OPTION ((*(char **)OPTSOLVER_OPTION_PTR))
114 #define TIME_LIMIT_PTR (sys->parm_array[3])
115 #define TIME_LIMIT ((*(int32 *)TIME_LIMIT_PTR))
116 #define ITER_LIMIT_PTR (sys->parm_array[4])
117 #define ITER_LIMIT ((*(int32 *)ITER_LIMIT_PTR))
118 #define ITER_BIS_LIMIT_PTR (sys->parm_array[5])
119 #define ITER_BIS_LIMIT ((*(int32 *)ITER_BIS_LIMIT_PTR))
120 #define TOO_SMALL_PTR (sys->parm_array[6])
121 #define TOO_SMALL ((*(real64 *)TOO_SMALL_PTR))
122 #define LINEAR_SEARCH_FACTOR_PTR (sys->parm_array[7])
123 #define LINEAR_SEARCH_FACTOR ((*(real64 *)LINEAR_SEARCH_FACTOR_PTR))
124 #define SHOW_MORE_IMPT_PTR (sys->parm_array[8])
125 #define SHOW_MORE_IMPT ((*(int32 *)SHOW_MORE_IMPT_PTR))
126 #define SHOW_LESS_IMPT_PTR (sys->parm_array[9])
127 #define SHOW_LESS_IMPT ((*(int32 *)SHOW_LESS_IMPT_PTR))
128 #define AUTO_RESOLVE_PTR (sys->parm_array[10])
129 #define AUTO_RESOLVE ((*(int32 *)AUTO_RESOLVE_PTR))
130 #define UNDEFINED_PTR (sys->parm_array[11])
131 #define UNDEFINED ((*(real64 *)UNDEFINED_PTR))
132 #define DOMLIM_PTR (sys->parm_array[12])
133 #define DOMLIM ((*(int32 *)DOMLIM_PTR))
134 #define OPT_ITER_LIMIT_PTR (sys->parm_array[13])
135 #define OPT_ITER_LIMIT ((*(int32 *)OPT_ITER_LIMIT_PTR))
136 #define INFINITY_PTR (sys->parm_array[14])
137 #define ASC_INFINITY ((*(real64 *)INFINITY_PTR))
138 #define OBJ_TOL_PTR (sys->parm_array[15])
139 #define OBJ_TOL ((*(real64 *)OBJ_TOL_PTR))
140 #define RTMAXJ_PTR (sys->parm_array[16])
141 #define RTMAXJ ((*(real64 *)RTMAXJ_PTR))
142 #define RHO_PTR (sys->parm_array[17])
143 #define RHO ((*(real64 *)RHO_PTR))
144
145
146 /*
147 * Client tokens of the different solvers: Conditional, Optimizer,
148 * Nonlinear, Logical. We will switch from one client token to
149 * another as the solution process occurs.
150 */
151 #define NUMBER_OF_CLIENTS 4
152 SlvClientToken token[NUMBER_OF_CLIENTS];
153 int32 solver_index[NUMBER_OF_CLIENTS];
154
155 /*
156 * indeces in arrays token and solver_index
157 */
158 #define CONDITIONAL_SOLVER 0
159 #define LOGICAL_SOLVER 1
160 #define NONLINEAR_SOLVER 2
161 #define OPTIMIZATION_SOLVER 3
162
163 /*
164 * Do we have an optimization problem ?. Global variable initialized
165 * to 0 (not optimizing)
166 */
167 static int32 g_optimizing = 0;
168
169 #if USE_CONSISTENCY
170 /*
171 * number of subregion visited during the solution of the conditional
172 * model.
173 */
174 static int32 g_subregions_visited;
175
176 #endif /* USE_CONSISTENCY */
177
178
179 /* auxiliar structures */
180 struct boolean_values {
181 int32 *pre_val; /* previous values of dis_discrete */
182 int32 *cur_val; /* current values of dis_discrete */
183 };
184
185 struct matching_cases {
186 int32 *case_list; /* list of cases */
187 int32 ncases; /* number of cases */
188 int32 diff_subregion; /* subregion ? */
189 };
190
191 struct real_values {
192 real64 *pre_values; /* previous values of var_variables */
193 real64 *cur_values; /* current values of var_variables */
194 };
195
196 struct opt_vector {
197 real64 *element; /* elements in colum of matrix */
198 };
199
200 struct opt_matrix {
201 struct opt_vector *cols; /* columns in matrix */
202 };
203
204 struct subregionID {
205 unsigned long ID_number;
206 int32 *bool_values;
207 };
208
209 struct ds_subregion_list {
210 int32 length,capacity;
211 struct subregionID *sub_stack;
212 };
213
214 struct ds_subregions_visited {
215 int32 length,capacity;
216 unsigned long *visited;
217 };
218
219 /*
220 * This solver's data structure (CMSlv)
221 */
222 struct slv9_system_structure {
223
224 /*
225 * Problem definition
226 */
227 slv_system_t slv; /* slv_system_t back-link */
228
229 struct rel_relation *obj; /* Objective function: NULL = none */
230 struct var_variable **vlist; /* Variable list (NULL terminated) */
231 struct rel_relation **rlist; /* Relation list (NULL terminated) */
232 struct dis_discrete **dvlist; /* Dis vars list (NULL terminated) */
233 struct logrel_relation **lrlist; /* Logrels list(NULL terminated)*/
234 struct bnd_boundary **blist; /* Variable list (NULL terminated) */
235 struct var_variable **mvlist;
236 struct dis_discrete **mdvlist; /* We will not touch the masters list,
237 * but they can provide very useful
238 * information to the conditional
239 * solver since the master index does
240 * not change.
241 */
242
243 /*
244 * for optimization at boundaries
245 */
246 struct opt_matrix *coeff_matrix; /* Matrix for optimization problem */
247 struct opt_vector *opt_var_values; /* Values of vars in opt problem */
248 int32 subregions; /* number of subregions at cur bnd */
249 mtx_matrix_t lin_mtx; /* Matrix to define the linear system
250 * for calculation of the lagrange
251 * multipliers
252 */
253 /*
254 * For search consistency analysis
255 */
256 struct ds_subregion_list subregion_list;
257 /*
258 * Information about the subregions
259 * visited during the solution of the
260 * conditional model
261 */
262 struct ds_subregions_visited subregions_visited;
263 /*
264 * ID number of the subregions
265 * visited
266 */
267 int32 *bool_mindex; /* master indices of boolean vars in
268 * the problem associated with WHENs
269 */
270 int32 need_consistency_analysis; /* Is the consistency analysis needed */
271
272
273 /*
274 * Solver information
275 */
276 int32 integrity; /* Has the system been created ? */
277 int32 presolved; /* Has the system been presolved ? */
278 slv_parameters_t p; /* Parameters */
279 slv_status_t s; /* Status (as of iteration end) */
280 int32 cap; /* Order of matrix/vectors */
281 int32 rank; /* Symbolic rank of problem */
282 int32 vused; /* Free and incident variables */
283 int32 vtot; /* length of varlist */
284 int32 mvtot; /* length of master varlist */
285 int32 rused; /* Included relations */
286 int32 rtot; /* length of rellist */
287 real64 clock; /* CPU time */
288 int32 nliter; /* iterations in nonlinear solver */
289
290 void *parm_array[slv9_PA_SIZE]; /* array of pointers to param values */
291 struct slv_parameter pa[slv9_PA_SIZE]; /* &pa[0] => sys->p.parms */
292
293 #ifdef ASC_WITH_CONOPT
294 /*
295 * Data for optimizer at boundaries (CONOPT)
296 */
297 struct conopt_data con;
298 #endif
299 };
300
301
302 /*
303 * Integrity checks
304 * ----------------
305 * check_system(sys)
306 */
307
308 #define OK ((int32)813029392)
309 #define DESTROYED ((int32)103289182)
310
311 /*
312 * Checks sys for NULL and for integrity.
313 */
314 static int check_system(slv9_system_t sys)
315 {
316 if( sys == NULL ) {
317 FPRINTF(ASCERR,"ERROR: (slv9) check_system\n");
318 FPRINTF(ASCERR," NULL system handle.\n");
319 return 1;
320 }
321
322 switch( sys->integrity ) {
323 case OK:
324 return 0;
325 case DESTROYED:
326 FPRINTF(ASCERR,"ERROR: (slv9) check_system\n");
327 FPRINTF(ASCERR," System was recently destroyed.\n");
328 return 1;
329 default:
330 FPRINTF(ASCERR,"ERROR: (slv9) check_system\n");
331 FPRINTF(ASCERR," System reused or never allocated.\n");
332 return 1;
333 }
334 }
335
336
337 /*
338 * General input/output routines
339 * -----------------------------
340 * print_var_name(out,sys,var)
341 */
342 #define print_var_name(a,b,c) slv_print_var_name((a),(b)->slv,(c))
343
344
345 /*
346 * Array operations
347 * ----------------
348 * destroy_array(p)
349 * create_array(len,type)
350 * create_zero_array(len,type)
351 */
352 #define destroy_array(p) \
353 if( (p) != NULL ) ascfree((p))
354 #define create_array(len,type) \
355 ((len) > 0 ? (type *)ascmalloc((len)*sizeof(type)) : NULL)
356 #define create_zero_array(len,type) \
357 ((len) > 0 ? (type *)asccalloc((len),sizeof(type)) : NULL)
358
359
360 /*
361 * Search Consistency Analysis during iterative process
362 * ---------------------------------------------------------
363 * The caller of this functions is in charge of
364 * defining the extension of the analysis by passing an integer
365 * which will tell us if 1) the analysis consider only the current
366 * and the previous alternatives or 2) the analysis consider all the
367 * alternatives visited at current the state of the solution
368 * algorithm.
369 */
370
371 /*
372 * Handling dynamic allocation of the structural information
373 */
374
375 #define alloc_array(nelts,type) \
376 ((nelts) > 0 ? (type *)ascmalloc((nelts)*sizeof(type)) : NULL)
377 #define copy_nums(from,too,nnums) \
378 asc_memcpy((from),(too),(nnums)*sizeof(int32))
379 #define copy_subregions(from,too,nsubs) \
380 asc_memcpy((from),(too),(nsubs)*sizeof(struct subregionID))
381
382 #if TEST_CONSISTENCY
383 /*
384 * Appends the subregion_visited into the list
385 */
386 static void append_subregion(struct ds_subregion_list *sl,
387 struct subregionID sub)
388 {
389 if( sl->length == sl->capacity ) {
390 int32 newcap;
391 struct subregionID *newlist;
392
393 newcap = sl->capacity + 10;
394 newlist = alloc_array(newcap,struct subregionID);
395 copy_subregions((char *)sl->sub_stack,(char *)newlist,sl->length);
396 if( sl->sub_stack != NULL ) {
397 ascfree(sl->sub_stack);
398 }
399 sl->sub_stack = newlist;
400 sl->capacity = newcap;
401 }
402
403 sl->sub_stack[sl->length++] = sub;
404 }
405
406 /*
407 * Appends the subregion_visited into the list
408 */
409 static void append_sub_visited(struct ds_subregions_visited *sv,
410 unsigned long sub_visited)
411 {
412 if( sv->length == sv->capacity ) {
413 int32 newcap;
414 unsigned long *newlist;
415
416 newcap = sv->capacity + 10;
417 newlist = alloc_array(newcap,unsigned long);
418 copy_nums((char *)sv->visited,(char *)newlist,sv->length);
419 if( sv->visited != NULL ) {
420 ascfree(sv->visited);
421 }
422 sv->visited = newlist;
423 sv->capacity = newcap;
424 }
425
426 sv->visited[sv->length++] = sub_visited;
427 }
428
429 static unsigned long powoftwo (int32 expo)
430 {
431 unsigned long val;
432 int32 c;
433
434 val = 1;
435 for (c=1; c<= expo; c++) {
436 val = val * 2;
437 }
438
439 return val;
440 }
441
442
443 /*
444 * Storage information (boolean values) about a subregion so that
445 * we can visit it later for interactive strucutral analysis
446 */
447 static void ID_and_storage_subregion_information(slv_system_t server,
448 SlvClientToken asys)
449 {
450 slv9_system_t sys;
451 struct dis_discrete **bvlist;
452 struct dis_discrete *cur_dis;
453 struct ds_subregion_list *sl;
454 struct ds_subregions_visited *sv;
455 struct subregionID *sub;
456 dis_filter_t dfilter;
457 unsigned long val, visited, sID;
458 int32 d, numdvs, numdvf, dcount;
459 int32 len, s, found;
460
461 sys = SLV9(asys);
462 check_system(sys);
463
464 bvlist = sys->mdvlist;
465 if(bvlist == NULL ) {
466 FPRINTF(ASCERR,"ERROR: ID_and_storage_subregion_information.\n");
467 FPRINTF(ASCERR," Master discrete var list was never set.\n");
468 return;
469 }
470 numdvs = slv_get_num_master_dvars(server);
471
472 dfilter.matchbits = (DIS_INWHEN | DIS_BOOLEAN);
473 dfilter.matchvalue = (DIS_INWHEN | DIS_BOOLEAN);
474 numdvf = slv_count_master_dvars(server,&dfilter);
475
476 if (numdvf > 0) {
477 sub = (struct subregionID *)(ascmalloc(sizeof(struct subregionID)));
478 sub->bool_values = (int32 *)(ascmalloc(numdvf*sizeof(int32)));
479 } else {
480 FPRINTF(ASCERR,"ERROR: ID_and_storage_subregion_information.\n");
481 FPRINTF(ASCERR," No boolean variables in the problem \n");
482 return;
483 }
484
485 dcount = 0;
486 val = 0;
487 for (d=0; d<numdvs; d++) {
488 cur_dis = bvlist[d];
489 if (dis_apply_filter(cur_dis,&dfilter)) {
490 sub->bool_values[dcount] = dis_value(cur_dis);
491 dcount++;
492 if (sub->bool_values[dcount - 1] == 1) {
493 val = val + powoftwo(numdvf - dcount);
494 }
495 }
496 }
497 if ( (val == 0 ) && (numdvf > 0) ) {
498 val = powoftwo(numdvf);
499 }
500 sub->ID_number = val;
501 #if DEBUG_CONSISTENCY
502 FPRINTF(ASCERR,"ID of alternative is %ul \n", val);
503 #endif /* DEBUG_CONSISTENCY */
504 visited = val;
505 found = 0;
506 len = sys->subregions_visited.length;
507 if (len > 0) {
508 for (s=0; s<len; s++) {
509 sID = sys->subregions_visited.visited[s];
510 if (visited == sID) {
511 found = 1;
512 break;
513 }
514 }
515 }
516
517 sv = &(sys->subregions_visited);
518 append_sub_visited(sv,visited);
519
520 if (found == 0) {
521 #if DEBUG_CONSISTENCY
522 FPRINTF(ASCERR,"Saving alternative\n");
523 #endif /* DEBUG_CONSISTENCY */
524 sl = &(sys->subregion_list);
525 append_subregion(sl,(*sub));
526 } else {
527 destroy_array(sub->bool_values);
528 ascfree(sub);
529 }
530
531 return;
532 }
533 #endif
534
535 /*
536 * Destroys subregion information
537 */
538 static void destroy_subregion_information(SlvClientToken asys)
539 {
540 slv9_system_t sys;
541 struct subregionID *sub;
542 int32 lens, s;
543
544 sys = SLV9(asys);
545 check_system(sys);
546
547 if (sys->subregions_visited.visited != NULL) {
548 destroy_array(sys->subregions_visited.visited);
549 }
550
551 lens = sys->subregion_list.length;
552 if (lens != 0) {
553 for (s=0; s<lens; s++) {
554 sub = &(sys->subregion_list.sub_stack[s]);
555 if (sub->bool_values != NULL) {
556 destroy_array(sub->bool_values);
557 }
558 }
559 }
560
561 if (sys->subregion_list.sub_stack != NULL) {
562 destroy_array(sys->subregion_list.sub_stack);
563 }
564
565 if (sys->bool_mindex != NULL) {
566 destroy_array(sys->bool_mindex);
567 }
568 }
569
570
571 #if 0 /** unused function eligible_set_for_neighboring_subregions */
572 /* might be used if DEBUG_CONSISTENCY on */
573
574 /*
575 * Storing original values of boolean variables
576 */
577 static void store_original_bool_values(struct gl_list_t *bollist,
578 struct boolean_values *bval)
579 {
580 struct dis_discrete *dvar;
581 int32 d, dlen;
582
583 dlen = gl_length(bollist);
584 bval->pre_val = create_array(dlen,int32);
585 bval->cur_val = create_array(dlen,int32);
586 for (d=1; d<=dlen; d++){
587 dvar = (struct dis_discrete *)gl_fetch(bollist,d);
588 bval->cur_val[d-1] = dis_value(dvar);
589 bval->pre_val[d-1] = dis_previous_value(dvar);
590 }
591 }
592
593 /*
594 * Restoring original values of boolean variables
595 */
596 static void restore_original_bool_values(struct gl_list_t *bollist,
597 struct boolean_values *bval)
598 {
599 struct dis_discrete *dvar;
600 int32 d, dlen;
601
602 dlen = gl_length(bollist);
603 for (d=1; d<=dlen; d++){
604 dvar = (struct dis_discrete *)gl_fetch(bollist,d);
605 dis_set_boolean_value(dvar,bval->cur_val[d-1]);
606 dis_set_value(dvar,bval->cur_val[d-1]);
607 dis_set_previous_value(dvar,bval->pre_val[d-1]);
608 }
609 destroy_array(bval->cur_val);
610 destroy_array(bval->pre_val);
611 }
612
613 #endif /* if 0 */
614
615 /*
616 * the first element of cur_cases is in position one. The result is
617 * the same array, but ordered and starting in position zero
618 */
619 static void cases_reorder(int32 *cur_cases, int32 *correct_cases, int32 ncases)
620 {
621 int32 cur_case,pos=0,tmp_num,c,ind;
622
623 for (c=1; c<=ncases; c++) {
624 tmp_num = 0;
625 for (ind=1; ind<=ncases; ind++) {
626 cur_case = cur_cases[ind];
627 if (tmp_num < cur_case) {
628 pos = ind;
629 tmp_num = cur_case;
630 }
631 }
632 cur_cases[pos] = 0;
633 correct_cases[ncases-c] = tmp_num;
634 }
635
636 return;
637 }
638
639 #if 0 /** unused function eligible_set_for_neighboring_subregions */
640 /* might appear if debug_consistency is true. */
641 /*
642 * Restoring orignal configuration of the system
643 */
644 static void restore_configuration(slv_system_t server,
645 struct gl_list_t *bollist)
646
647 {
648 int32 *cur_cases, *correct_cases;
649 int32 ncases;
650
651 cur_cases = cases_matching(bollist,&ncases);
652 correct_cases = create_array(ncases,int32);
653 cases_reorder(cur_cases,correct_cases,ncases);
654 set_active_rels_in_subregion(server,correct_cases,ncases,bollist);
655 set_active_vars_in_subregion(server);
656 destroy_array(cur_cases);
657 destroy_array(correct_cases);
658 }
659
660
661 /*
662 * Get the list of boolean variables in the problem which are
663 * associated with a WHEN
664 */
665 static struct gl_list_t *get_list_of_booleans(slv_system_t server,
666 SlvClientToken asys)
667 {
668 slv9_system_t sys;
669 struct dis_discrete **bvlist;
670 struct dis_discrete *cur_dis;
671 struct gl_list_t *boolvars;
672 dis_filter_t dfilter;
673 int32 numdvf, numdvs, d, dcount;
674
675 sys = SLV9(asys);
676 check_system(sys);
677
678 bvlist = sys->mdvlist;
679 if(bvlist == NULL ) {
680 FPRINTF(ASCERR,"ERROR: (slv9) get_list_of_booleans.\n");
681 FPRINTF(ASCERR," Master discrete var list was never set.\n");
682 return NULL;
683 }
684 numdvs = slv_get_num_master_dvars(server);
685
686 dfilter.matchbits = (DIS_INWHEN | DIS_BOOLEAN);
687 dfilter.matchvalue = (DIS_INWHEN | DIS_BOOLEAN);
688 numdvf = slv_count_master_dvars(server,&dfilter);
689
690 if (numdvf == 0) {
691 FPRINTF(ASCERR,"ERROR: (slv9) get_list_of_booleans.\n");
692 FPRINTF(ASCERR," No boolean variables in the problem \n");
693 return NULL;
694 }
695
696 sys->bool_mindex = (int32 *)(ascmalloc(numdvf*sizeof(int32)));
697 boolvars = gl_create(numdvf);
698
699 dcount = 0;
700 for (d=0; d<numdvs; d++) {
701 cur_dis = bvlist[d];
702 if (dis_apply_filter(cur_dis,&(dfilter))) {
703 gl_append_ptr(boolvars,cur_dis);
704 sys->bool_mindex[dcount] = d;
705 dcount++;
706 }
707 }
708
709 return boolvars;
710 }
711
712 #endif /* 0*/
713
714 /*
715 * Get the eligible var list for each alternative
716 * Return:
717 * 1 means everything went right
718 * 0 means the analysis has failed with the current parititioning
719 * -1 means a memory problem has occurred
720 */
721 static int32 get_eligible_set(slv_system_t server,struct gl_list_t *disvars,
722 int32 *terminate)
723 {
724 struct var_variable **vslist;
725 struct var_variable **vmlist;
726 struct var_variable *mvar, *svar;
727 var_filter_t vfilter;
728 int32 *cur_cases;
729 int32 *correct_cases;
730 int32 *vars;
731 int32 v, count=0, ind;
732 int32 ncases;
733 int32 mnum;
734 int32 status,dof;
735
736 vslist = slv_get_solvers_var_list(server);
737 vmlist = slv_get_master_var_list(server);
738 mnum = slv_get_num_master_vars(server);
739 for (v=0; v<mnum; v++) {
740 mvar = vmlist[v];
741 var_set_eligible_in_subregion(mvar,FALSE);
742 }
743
744 cur_cases = cases_matching(disvars,&ncases);
745 correct_cases = create_array(ncases,int32);
746 cases_reorder(cur_cases,correct_cases,ncases);
747 set_active_rels_in_subregion(server,correct_cases,ncases,disvars);
748 set_active_vars_in_subregion(server);
749 destroy_array(cur_cases);
750 destroy_array(correct_cases);
751
752 #if DEBUG_CONSISTENCY
753 FPRINTF(ASCERR,"Analyzing alternative:\n");
754 #endif /* DEBUG_CONSISTENCY */
755
756 if (!slvDOF_status(server,(&status),(&dof))) {
757 FPRINTF(ASCERR,"ERROR in combinatorial search\n");
758 FPRINTF(ASCERR,"Combinatorial search aborted\n");
759 return -1;
760 } else {
761 if (status == 3) {
762 #if DEBUG_CONSISTENCY
763 FPRINTF(ASCERR,"Alternative is structurally singular\n");
764 #endif /* DEBUG_CONSISTENCY */
765 (*terminate) = 0;
766 return 0;
767 } else {
768 if (status == 4) {
769 #if DEBUG_CONSISTENCY
770 FPRINTF(ASCERR,"Alternative is overspecified\n");
771 #endif /* DEBUG_CONSISTENCY */
772 (*terminate) = 0;
773 return 0;
774 }
775 }
776 }
777
778 if (status == 1) {
779 (*terminate) = 0;
780 #if DEBUG_CONSISTENCY
781 FPRINTF(ASCERR,"Alternative has % d degrees of freedom.\n", dof);
782
783 #endif /* DEBUG_CONSISTENCY */
784 if (slvDOF_eligible(server,&(vars))) {
785 count = 0;
786 while (vars[count] != -1) {
787 ind = vars[count];
788 svar = vslist[ind];
789 v = var_mindex(svar);
790 mvar = vmlist[v];
791 var_set_eligible_in_subregion(mvar,TRUE);
792 count++;
793 }
794 destroy_array(vars);
795 }
796 if (dof > count) {
797 #if DEBUG_CONSISTENCY
798 FPRINTF(ASCERR,
799 "Alternative does not have enough number of eligible vars\n");
800 #endif /* DEBUG_CONSISTENCY */
801 return 0;
802 }
803 }
804
805 if (status == 2) {
806 #if DEBUG_CONSISTENCY
807 FPRINTF(ASCERR,"Alternative is square.\n");
808 #endif /* DEBUG_CONSISTENCY */
809 }
810
811 vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR
812 | VAR_ELIGIBLE_IN_SUBREGION);
813 vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR);
814
815 for (v=0; v<mnum; v++) {
816 mvar = vmlist[v];
817 if(var_apply_filter(mvar,&vfilter)) {
818 var_set_eligible(mvar,FALSE);
819 }
820 var_set_eligible_in_subregion(mvar,FALSE);
821 }
822
823 return 1;
824 }
825
826 /*
827 * Get the eligible set of variables for each of the alternatives generated
828 * by modifying the values of the boolean variables with the values stored
829 * during the solution process
830 * Return:
831 * 1 means everything went right
832 * 0 means the analysis has failed with the current partitioning
833 * -1 means a memory problem or wierdness has occurred
834 */
835 static int32 do_search_alternatives(slv_system_t server, SlvClientToken asys,
836 struct gl_list_t *disvars,
837 int32 *terminate, int32 all_sub)
838 {
839 slv9_system_t sys;
840 struct dis_discrete *cur_dis;
841 struct subregionID *sub;
842 int32 *values = NULL;
843 int32 dlen, test;
844 int32 lens, lenv, v, s, d;
845 int32 result;
846 unsigned long visited, vID;
847
848
849 sys = SLV9(asys);
850
851 dlen = gl_length(disvars);
852 lenv = sys->subregions_visited.length;
853 lens = sys->subregion_list.length;
854
855 if (all_sub == 0) { /* current and previous subregion */
856 for (v=lenv-2; v<lenv; v++) {
857 test = 0;
858 vID = sys->subregions_visited.visited[v];
859 for (s=lens-1; s>=0; s--) {
860 sub = &(sys->subregion_list.sub_stack[s]);
861 visited = sub->ID_number;
862 if (vID == visited) {
863 values = sub->bool_values;
864 test = 1;
865 FPRINTF(ASCERR,"s = %d \n",s);
866 break;
867 }
868 }
869
870 if (test == 0) {
871 FPRINTF(ASCERR,"ERROR: (slv9) do_search_alternatives \n");
872 FPRINTF(ASCERR," subregion not found \n");
873 return -1;
874 }
875 #if DEBUG_CONSISTENCY
876 FPRINTF(ASCERR,"Alternative = %ul \n", vID);
877 #endif /* DEBUG_CONSISTENCY */
878 for (d=0; d<dlen; d++) {
879 assert(values != NULL); /* if null, test was 0 above and we returned, in theory */
880 cur_dis = (struct dis_discrete *)(gl_fetch(disvars,d+1));
881 if (values[d] == 1) {
882 dis_set_boolean_value(cur_dis,TRUE);
883 } else {
884 dis_set_boolean_value(cur_dis,FALSE);
885 }
886 }
887 result = get_eligible_set(server,disvars,terminate);
888 if (result != 1) {
889 return result;
890 }
891 }
892
893 } else { /* all visited subregions */
894
895 for (s=lens-1; s>=0; s--) {
896 sub = &(sys->subregion_list.sub_stack[s]);
897 values = sub->bool_values;
898 vID = sub->ID_number;
899 #if DEBUG_CONSISTENCY
900 FPRINTF(ASCERR,"Alternative = %ul \n", vID);
901 #endif /* DEBUG_CONSISTENCY */
902 for (d=0; d<dlen; d++) {
903 cur_dis = (struct dis_discrete *)(gl_fetch(disvars,d+1));
904 if (values[d] == 1) {
905 dis_set_boolean_value(cur_dis,TRUE);
906 } else {
907 dis_set_boolean_value(cur_dis,FALSE);
908 }
909 }
910 result = get_eligible_set(server,disvars,terminate);
911 if (result != 1) {
912 return result;
913 }
914 }
915 }
916
917 return 1;
918 }
919
920
921 /*
922 * Perform consistency analysis for the visited/current-previous subregions.
923 * If all_subs is 1, the analysis takes in account all of the subregions
924 * visited by the solution algorithm at the current point if the solution
925 * procedure. If all_subs is 0, the analysis is only for the current
926 * and previous subregion.
927 */
928 static int32 consistency(slv_system_t server, SlvClientToken asys,
929 struct gl_list_t *bollist,
930 int32 all_subs, int32 *terminate)
931 {
932 slv9_system_t sys;
933 struct var_variable **vmlist;
934 struct var_variable *mvar;
935 var_filter_t vfilter;
936 int32 *globeli = NULL;
937 int32 dlen;
938 int32 mnum, v, elnum;
939 int32 result;
940 int32 iter;
941
942 sys = SLV9(asys);
943 check_system(sys);
944
945 /*
946 * Initializing eligible bit for variables
947 */
948 vmlist = slv_get_master_var_list(server);
949 mnum = slv_get_num_master_vars(server);
950 for (v=0; v<mnum; v++) {
951 mvar = vmlist[v];
952 var_set_eligible(mvar,TRUE);
953 }
954
955 dlen = gl_length(bollist);
956
957 #if DEBUG_CONSISTENCY
958 FPRINTF(ASCERR,"S e a r c h i n g \n");
959 #endif /* DEBUG_CONSISTENCY */
960 result = do_search_alternatives(server,asys,bollist,terminate,all_subs);
961
962 if (result != 1) {
963 #if DEBUG_CONSISTENCY
964 FPRINTF(ASCERR,"returning failed search after S e a r c h \n");
965 #endif /* DEBUG_CONSISTENCY */
966 return result;
967 }
968
969 /*
970 * Getting the "globally" eligible variables
971 */
972 vfilter.matchbits = (VAR_INCIDENT | VAR_SVAR | VAR_ELIGIBLE | VAR_FIXED);
973 vfilter.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ELIGIBLE);
974 elnum = slv_count_master_vars(server,&vfilter);
975
976 if (elnum > 0) {
977 globeli = ASC_NEW_ARRAY(int32,elnum);
978 elnum = 0;
979 for (v=0; v<mnum; v++) {
980 mvar = vmlist[v];
981 if(var_apply_filter(mvar,&vfilter)) {
982 #if DEBUG_CONSISTENCY
983 FPRINTF(ASCERR,"Eligible index = %d \n",v);
984 #endif /* DEBUG_CONSISTENCY */
985 globeli[elnum] = v;
986 elnum++;
987 }
988 }
989 }
990
991 /*
992 * Recursively analysis
993 */
994
995 if ((*terminate) == 1) {
996 if (elnum != 0) {
997 #if DEBUG_CONSISTENCY
998 FPRINTF(ASCERR,"All alternatives are square but the \n");
999 FPRINTF(ASCERR,"Eligible set is not null\n");
1000 #endif /* DEBUG_CONSISTENCY */
1001 destroy_array(globeli);
1002 }
1003 return 1;
1004 } else {
1005 if (elnum == 0) {
1006 #if DEBUG_CONSISTENCY
1007 FPRINTF(ASCERR,"No globally eligible variables to be fixed.\n");
1008 #endif /* DEBUG_CONSISTENCY */
1009 return 0;
1010 }
1011
1012 for (v=0; v<elnum; v++) {
1013 iter = 1;
1014 mvar = vmlist[globeli[v]];
1015 var_set_fixed(mvar,TRUE);
1016 var_set_potentially_fixed(mvar,TRUE);
1017 #if DEBUG_CONSISTENCY
1018 FPRINTF(ASCERR,"Fixing index = %d \n",globeli[v]);
1019 FPRINTF(ASCERR,"N e s t e d S e a r c h \n");
1020 #endif /* DEBUG_CONSISTENCY */
1021 result = consistency(server,asys,bollist,all_subs,&iter);
1022
1023 if (result != 1) {
1024 #if DEBUG_CONSISTENCY
1025 FPRINTF(ASCERR,"%d eliminated\n",globeli[v]);
1026 #endif /* DEBUG_CONSISTENCY */
1027 var_set_fixed(mvar,FALSE);
1028 var_set_potentially_fixed(mvar,FALSE);
1029 continue;
1030 } else {
1031 if (iter == 1) {
1032 (*terminate) = 1;
1033 #if DEBUG_CONSISTENCY
1034 FPRINTF(ASCERR,"%d Acepted \n",globeli[v]);
1035 #endif /* DEBUG_CONSISTENCY */
1036 destroy_array(globeli);
1037 return 1;
1038 } else {
1039 var_set_fixed(mvar,FALSE);
1040 var_set_potentially_fixed(mvar,FALSE);
1041 continue;
1042 }
1043 }
1044 }
1045 destroy_array(globeli);
1046 #if DEBUG_CONSISTENCY
1047 FPRINTF(ASCERR,"returning 0 after nested search\n");
1048 #endif /* DEBUG_CONSISTENCY */
1049 return 0;
1050 }
1051 }
1052
1053 #if 0 /** unused function eligible_set_for_neighboring_subregions */
1054 /* might appear if debug_consistency is true. */
1055
1056 /*
1057 * Get a set of globally eligible variables. Eligible for all the subregions
1058 * visited, or for the previous and current subregions.
1059 */
1060 static int32 get_globally_eligible(slv_system_t server, SlvClientToken asys,
1061 struct gl_list_t *bollist,
1062 int32 all_subs, int32 **eliset)
1063 {
1064 slv9_system_t sys;
1065 struct var_variable **vmlist;
1066 struct var_variable *mvar;
1067 var_filter_t vfilter;
1068 int32 dlen;
1069 int32 mnum, v, elnum;
1070 int32 terminate;
1071 int32 result;
1072
1073 sys = SLV9(asys);
1074 check_system(sys);
1075 /*
1076 * Initializing eligible bit for variables
1077 */
1078 vmlist = slv_get_master_var_list(server);
1079 mnum = slv_get_num_master_vars(server);
1080 for (v=0; v<mnum; v++) {
1081 mvar = vmlist[v];
1082 var_set_eligible(mvar,TRUE);
1083 }
1084
1085 dlen = gl_length(bollist);
1086
1087 /*
1088 * initializing
1089 */
1090 *eliset = NULL;
1091 terminate = 1;
1092
1093 #if DEBUG_CONSISTENCY
1094 FPRINTF(ASCERR,"S e a r c h i n g \n");
1095 #endif /* DEBUG_CONSISTENCY */
1096 result = do_search_alternatives(server,asys,bollist,&terminate,all_subs);
1097
1098 if (result != 1) {
1099 if (terminate == 0) {
1100 #if DEBUG_CONSISTENCY
1101 FPRINTF(ASCERR,"ERROR: some alternatives are either singular or\n");
1102 FPRINTF(ASCERR,"overspecified. All the alternatives have to be\n");
1103 FPRINTF(ASCERR,
1104 "either square or underspecified to complete the analysis\n");
1105 #endif /* DEBUG_CONSISTENCY */
1106 }
1107 return 0;
1108 }
1109
1110 /*
1111 * Getting the "globally" eligible variables
1112 */
1113 vfilter.matchbits = (VAR_INCIDENT | VAR_SVAR | VAR_ELIGIBLE | VAR_FIXED);
1114 vfilter.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ELIGIBLE);
1115 elnum = slv_count_master_vars(server,&vfilter);
1116
1117 *eliset = (int32 *)ascmalloc((elnum+1)*sizeof(int32));
1118 elnum = 0;
1119 for (v=0; v<mnum; v++) {
1120 mvar = vmlist[v];
1121 if(var_apply_filter(mvar,&vfilter)) {
1122 #if DEBUG_CONSISTENCY
1123 FPRINTF(ASCERR,"Eligible index = %d \n",v);
1124 FPRINTF(ASCERR,"Variable : \n");
1125 print_var_name(ASCERR,sys,mvar);
1126 #endif /* DEBUG_CONSISTENCY */
1127 (*eliset)[elnum] = v;
1128 elnum++;
1129 }
1130 }
1131 (*eliset)[elnum] = -1;
1132
1133 if (elnum == 0) {
1134 if (terminate == 0) {
1135 #if DEBUG_CONSISTENCY
1136 FPRINTF(ASCERR,
1137 "Some alternatives are underspecified, but there does\n");
1138 FPRINTF(ASCERR,"not exist a set of eligible variables consistent \n");
1139 FPRINTF(ASCERR,"with all the alternatives\n");
1140 #endif /* DEBUG_CONSISTENCY */
1141 } else {
1142 #if DEBUG_CONSISTENCY
1143 FPRINTF(ASCERR,"All alternatives are already square\n");
1144 #endif /* DEBUG_CONSISTENCY */
1145 }
1146 return 0;
1147 } else {
1148 if (terminate == 1) {
1149 #if DEBUG_CONSISTENCY
1150 FPRINTF(ASCERR,"All alternatives are square but the \n");
1151 FPRINTF(ASCERR,"Eligible set is not null\n");
1152 #endif /* DEBUG_CONSISTENCY */
1153 }
1154 }
1155 return 1;
1156 }
1157
1158
1159
1160 /*
1161 * Store and restore values of the boolean variables of the problem
1162 * and calls for the the set of globally eligible variables.If all_subs
1163 * is 1, the analysis takes in account all of the subregions visited
1164 * by the solution algorithm at the current point if the solution
1165 * procedure. If all_subs is 0, the analysis is only for the current
1166 * and previous subregion.
1167 */
1168 static int32 consistent_eligible_set_for_subregions(slv_system_t server,
1169 SlvClientToken asys,
1170 int32 **vlist,
1171 int32 all_subs)
1172 {
1173 struct gl_list_t *blist;
1174 struct boolean_values bval;
1175 int32 result;
1176
1177 if (server==NULL || vlist == NULL) {
1178 FPRINTF(ASCERR,
1179 "consistent_eligible_set_for_subregions called with NULL.\n");
1180 return 0;
1181 }
1182
1183 blist = get_list_of_booleans(server,asys);
1184
1185 if ( (blist == NULL) || (gl_length(blist) == 0) ) {
1186 FPRINTF(ASCERR,"ERROR: (slv9) consistent_eligible_set_for_subregions \n");
1187 FPRINTF(ASCERR," List of boolean vars could not be found\n");
1188 return 0;
1189 }
1190
1191 store_original_bool_values(blist,&(bval));
1192 result = get_globally_eligible(server,asys,blist,all_subs,vlist);
1193
1194 restore_original_bool_values(blist,&(bval));
1195 restore_configuration(server,blist);
1196 gl_destroy(blist);
1197
1198 if (result == 1) {
1199 return 1;
1200 } else {
1201 return 0;
1202 }
1203
1204 }
1205
1206 /*
1207 * Store and restore values of the boolean variables of the problem
1208 * and calls for the consistency analysis of the subregions.If all_subs
1209 * is 1, the analysis takes in account all of the subregions visited
1210 * by the solution algorithm at the current point if the solution
1211 * procedure. If all_subs is 0, the analysis is only for the current
1212 * and previous subregion.
1213 */
1214 static int32 analyze_subregions(slv_system_t server,SlvClientToken asys,
1215 int32 **vlist, int32 all_subs)
1216 {
1217 slv9_system_t sys;
1218 struct var_variable ** vmlist;
1219 struct var_variable *mvar;
1220 struct gl_list_t *blist;
1221 struct boolean_values bval;
1222 var_filter_t vfilter;
1223 int32 mnum, elnum, v;
1224 int32 result;
1225 int32 terminate;
1226
1227 sys = SLV9(asys);
1228 check_system(sys);
1229
1230 if (server==NULL || vlist == NULL) {
1231 FPRINTF(ASCERR,"(slv9) analyze_subregions called with NULL.\n");
1232 return 0;
1233 }
1234
1235 blist = get_list_of_booleans(server,asys);
1236 if ( (blist == NULL) || (gl_length(blist) == 0) ) {
1237 FPRINTF(ASCERR,"ERROR: (slv9) analyze_subregions \n");
1238 FPRINTF(ASCERR," List of boolean vars could not be found\n");
1239 return 0;
1240 }
1241
1242 store_original_bool_values(blist,&(bval));
1243 /*
1244 * initializing
1245 */
1246 terminate = 1;
1247 (*vlist) = NULL;
1248
1249 vmlist = slv_get_master_var_list(server);
1250 mnum = slv_get_num_master_vars(server);
1251
1252 vfilter.matchbits = (VAR_POTENTIALLY_FIXED);
1253 vfilter.matchvalue = (VAR_POTENTIALLY_FIXED);
1254
1255 result = consistency(server,asys,blist,all_subs,&terminate);
1256
1257 if (result == 1) {
1258 /*
1259 * Getting the set of eligible variables
1260 */
1261 elnum = slv_count_master_vars(server,&vfilter);
1262 *vlist = (int32 *)ascmalloc((elnum+1)*sizeof(int32));
1263 elnum = 0;
1264 for (v=0; v<mnum; v++) {
1265 mvar = vmlist[v];
1266 if(var_apply_filter(mvar,&vfilter)) {
1267 var_set_fixed(mvar,FALSE);
1268 var_set_potentially_fixed(mvar,FALSE);
1269 #if DEBUG_CONSISTENCY
1270 FPRINTF(ASCERR,"Variable in consistent set: \n");
1271 print_var_name(ASCERR,sys,mvar);
1272 #endif /* DEBUG_CONSISTENCY */
1273 (*vlist)[elnum] = v;
1274 elnum++;
1275 }
1276 }
1277 (*vlist)[elnum] = -1;
1278
1279 restore_original_bool_values(blist,&(bval));
1280 restore_configuration(server,blist);
1281 gl_destroy(blist);
1282 return 1;
1283 } else {
1284 for (v=0; v<mnum; v++) {
1285 mvar = vmlist[v];
1286 if(var_apply_filter(mvar,&vfilter)) {
1287 var_set_fixed(mvar,FALSE);
1288 var_set_potentially_fixed(mvar,FALSE);
1289 }
1290 }
1291 restore_original_bool_values(blist,&(bval));
1292 restore_configuration(server,blist);
1293 gl_destroy(blist);
1294 return 0;
1295 }
1296 }
1297
1298
1299 /*
1300 * Finds the globally eligible set of variables only for the current and
1301 * previous subregions
1302 */
1303 static int32 eligible_set_for_neighboring_subregions(slv_system_t server,
1304 SlvClientToken asys,
1305 int32 **vlist)
1306 {
1307 slv9_system_t sys;
1308
1309 sys = SLV9(asys);
1310 check_system(sys);
1311
1312 if( sys->mdvlist == NULL ) {
1313 FPRINTF(ASCERR,"ERROR: (slv9) eligible_set_for_neighboring_subregions\n");
1314 FPRINTF(ASCERR," Discrete Variable list was never set.\n");
1315 return 0;
1316 }
1317
1318 if (!(sys->need_consistency_analysis)) {
1319 FPRINTF(ASCERR,"Globally eligible set not necessary\n");
1320 FPRINTF(ASCERR,"All the subregions have the same structure \n");
1321 return 0;
1322 }
1323
1324 if (consistent_eligible_set_for_subregions(server,asys,vlist,0)) {
1325 return 1;
1326 }
1327
1328 return 0;
1329 }
1330
1331
1332 /*
1333 * Perform the consistency analysis algorithm only for the current and
1334 * previous subregions
1335 */
1336 static int32 consistency_for_neighboring_subregions(slv_system_t server,
1337 SlvClientToken asys,
1338 int32 **vlist)
1339 {
1340 slv9_system_t sys;
1341
1342 sys = SLV9(asys);
1343 check_system(sys);
1344
1345 if( sys->mdvlist == NULL ) {
1346 FPRINTF(ASCERR,"ERROR: (slv9) consistency_for_neighboring_subregions\n");
1347 FPRINTF(ASCERR," Discrete Variable list was never set.\n");
1348 return 0;
1349 }
1350
1351 if (!(sys->need_consistency_analysis)) {
1352 FPRINTF(ASCERR,"consistency_analysis is not required\n");
1353 FPRINTF(ASCERR,"All the subregions have the same structure \n");
1354 return 0;
1355 }
1356
1357 if (analyze_subregions(server,asys,vlist,0)) {
1358 return 1;
1359 }
1360
1361 return 0;
1362 }
1363
1364
1365
1366 /*
1367 * Consistency analysis for visisted subregions. This function
1368 * gets the subregions that the solution algorithm has visited and
1369 * analyzes them.
1370 */
1371 static int32 eligible_set_for_subregions(slv_system_t server,
1372 SlvClientToken asys,
1373 int32 **vlist)
1374 {
1375 slv9_system_t sys;
1376
1377 sys = SLV9(asys);
1378 check_system(sys);
1379
1380 if( sys->mdvlist == NULL ) {
1381 FPRINTF(ASCERR,"ERROR: (slv9) eligible_set_for_subregions \n");
1382 FPRINTF(ASCERR," Discrete Variable list was never set.\n");
1383 return 0;
1384 }
1385
1386 if (!(sys->need_consistency_analysis)) {
1387 FPRINTF(ASCERR,"Globally eligible set not necessary \n");
1388 FPRINTF(ASCERR,"All the subregions have the same structure \n");
1389 return 0;
1390 }
1391
1392 if (consistent_eligible_set_for_subregions(server,asys,vlist,1)) {
1393 return 1;
1394 }
1395
1396 return 0;
1397 }
1398
1399
1400 /*
1401 * Consistency analysis for visisted subregions. This function
1402 * gets the subregions that the solution algorithm has visited and
1403 * analyzes them.
1404 */
1405 static int32 consistency_analysis_for_subregions(slv_system_t server,
1406 SlvClientToken asys,
1407 int32 **vlist)
1408 {
1409 slv9_system_t sys;
1410
1411 sys = SLV9(asys);
1412 check_system(sys);
1413
1414 if( sys->mdvlist == NULL ) {
1415 FPRINTF(ASCERR,"ERROR: (slv9) consistency_analysis_for_subregions\n");
1416 FPRINTF(ASCERR," Discrete Variable list was never set.\n");
1417 return 0;
1418 }
1419
1420 if (!(sys->need_consistency_analysis)) {
1421 FPRINTF(ASCERR,"consistency_analysis is not required\n");
1422 FPRINTF(ASCERR,"All the subregions have the same structure \n");
1423 return 0;
1424 }
1425
1426 if (analyze_subregions(server,asys,vlist,1)) {
1427 return 1;
1428 }
1429
1430 return 0;
1431 }
1432
1433 #endif /*#if 0 unused functions */
1434
1435
1436 /*
1437 * Handling of solution of the Logical Equations
1438 * ---------------------------------------------------------
1439 * This is made this way because it is a process which will be
1440 * required very often.
1441 */
1442
1443 /*
1444 * Solution of the logical relations encountered in the system based on
1445 * the current values of the discrete variables.
1446 */
1447 static void solve_logical_relations(slv_system_t server)
1448 {
1449 slv_set_client_token(server,token[LOGICAL_SOLVER]);
1450 slv_set_solver_index(server,solver_index[LOGICAL_SOLVER]);
1451 slv_presolve(server);
1452 #if SHOW_LOGICAL_DETAILS
1453 FPRINTF(ASCERR,"Solving Logical Relations\n");
1454 #endif /* SHOW_LOGICAL_DETAILS */
1455 slv_solve(server);
1456 }
1457
1458
1459
1460 /*
1461 * Handling the modification of parameters in external solvers
1462 * ---------------------------------------------------------
1463 */
1464
1465 /*
1466 * different types of parameter values
1467 */
1468 union param_value {
1469 int32 i;
1470 real64 r;
1471 int32 b;
1472 char *c;
1473 };
1474
1475
1476 /*
1477 * Setting the value of a parameter in a subsidiary solver
1478 */
1479 static void set_param_in_solver(slv_system_t server, int32 solver,
1480 enum parm_type types, char *param,
1481 union param_value *value)
1482 {
1483 slv_parameters_t p;
1484 int32 len,length;
1485
1486 slv_set_client_token(server,token[solver]);
1487 slv_set_solver_index(server,solver_index[solver]);
1488 slv_get_parameters(server,&p);
1489 length = p.num_parms;
1490 for (len = 0; len < length; len++) {
1491 if (p.parms[len].type == types) {
1492 switch (p.parms[len].type) {
1493 case bool_parm:
1494 if (strcmp(param,p.parms[len].name) == 0) {
1495 p.parms[len].info.b.value = value->b;
1496 }
1497 break;
1498 case real_parm:
1499 if (strcmp(param,p.parms[len].name) == 0) {
1500 p.parms[len].info.r.value = value->r;
1501 }
1502 break;
1503 case char_parm:
1504 if (strcmp(param,p.parms[len].name) == 0) {
1505 p.parms[len].info.c.value = value->c;
1506 }
1507 break;
1508 case int_parm:
1509 if (strcmp(param,p.parms[len].name) == 0) {
1510 p.parms[len].info.i.value = value->i;
1511 }
1512 break;
1513 default:
1514 break;
1515 }
1516 }
1517 }
1518 return;
1519 }
1520
1521
1522 /*
1523 * Analysis of Discrete Variables
1524 * -------------------------------
1525 */
1526
1527 /*
1528 * Compare current values of the discrete variables with their previous values
1529 * in order to know if some of them have changed.
1530 */
1531 static int32 some_dis_vars_changed(slv_system_t server, SlvClientToken asys)
1532 {
1533 struct dis_discrete **dv, *cur_dis;
1534 int32 numdvs, ind;
1535 slv9_system_t sys;
1536
1537 sys = SLV9(asys);
1538 check_system(sys);
1539
1540 if( sys->dvlist == NULL ) {
1541 FPRINTF(ASCERR,"ERROR: (slv9) some_dis_vars_changed\n");
1542 FPRINTF(ASCERR," Discrete variable list was never set.\n");
1543 return 0;
1544 }
1545
1546 dv = sys->dvlist;
1547 numdvs = slv_get_num_solvers_dvars(server);
1548 for( ind = 0; ind < numdvs; ind++ ) {
1549 cur_dis = dv[ind];
1550 #if SHOW_LOGICAL_DETAILS
1551 FPRINTF(ASCERR,"Boundary index = %d \n",ind);
1552 FPRINTF(ASCERR,"Current Value = %d\n",dis_value(cur_dis));
1553 FPRINTF(ASCERR,"Previous Value = %d\n",dis_previous_value(cur_dis));
1554 #endif /* SHOW_LOGICAL_DETAILS */
1555 if ((dis_kind(cur_dis)==e_dis_boolean_t ) && dis_inwhen(cur_dis) ) {
1556 if (dis_value(cur_dis) != dis_previous_value(cur_dis)) {
1557 return 1;
1558 }
1559 }
1560 }
1561 return 0;
1562 }
1563
1564 /*
1565 * Compare the original value of a discrete boolean variable (before
1566 * perturbation of boundaries) with its values after a solution
1567 * of the logical relations with some perturbed values for boundaries.
1568 * If those values are different, the bit VAL_MODIFIED is set to
1569 * TRUE. This will give us the boolean variable which will change as a
1570 * consequence of a boundary crossing.
1571 */
1572 static void search_for_modified_dvars(struct dis_discrete **dv,
1573 int32 numdvs,
1574 struct boolean_values *bval)
1575 {
1576 struct dis_discrete *cur_dis;
1577 int32 d;
1578 int32 orig_value;
1579
1580 for (d=0; d<numdvs; d++) {
1581 cur_dis = dv[d];
1582 if(dis_inwhen(cur_dis) && dis_boolean(cur_dis)) {
1583 orig_value = bval->cur_val[d];
1584 if (orig_value != dis_value(cur_dis)) {
1585 dis_set_val_modified(cur_dis,TRUE);
1586 }
1587 }
1588 }
1589 }
1590
1591
1592 /*
1593 * Analysis of Boundaries
1594 * ----------------------------
1595 */
1596
1597 /*
1598 * Evaluates the current status (satisfied? , at zero?) of a boundary
1599 * and sets its flags accordingly. At the same time, it updates the
1600 * residual of the relation included in the boundary (see
1601 * bndman_calc_satisfied).
1602 */
1603
1604 static void update_boundaries(slv_system_t server, SlvClientToken asys)
1605 {
1606 struct bnd_boundary **bp;
1607 int32 numbnds, ind, value;
1608 slv9_system_t sys;
1609
1610 sys = SLV9(asys);
1611 check_system(sys);
1612
1613 if( sys->blist == NULL ) {
1614 FPRINTF(ASCERR,"ERROR: (slv9) update_boundaries.\n");
1615 FPRINTF(ASCERR," Boundary list was never set.\n");
1616 return;
1617 }
1618
1619 bp = sys->blist;
1620 numbnds = slv_get_num_solvers_bnds(server);
1621
1622 for( ind = 0; ind < numbnds; ++ind ) {
1623 value = bnd_status_cur(bp[ind]);
1624 bnd_set_pre_status(bp[ind],value);
1625 value = bndman_calc_satisfied(bp[ind]);
1626 bnd_set_cur_status(bp[ind],value);
1627 if ( (bnd_status_cur(bp[ind]) != bnd_status_pre(bp[ind])) &&
1628 bnd_kind(bp[ind]) == e_bnd_rel && !bnd_at_zero(bp[ind])) {
1629 bnd_set_crossed(bp[ind],TRUE);
1630 } else {
1631 bnd_set_crossed(bp[ind],FALSE);
1632 }
1633 if (bnd_kind(bp[ind]) == e_bnd_rel) {
1634 value = bndman_calc_at_zero(bp[ind]);
1635 bnd_set_at_zero(bp[ind],value);
1636 } else {
1637 bnd_set_at_zero(bp[ind],FALSE);
1638 }
1639 }
1640 }
1641
1642
1643 /*
1644 * Look for some boundary with the CROSSED bit active. If this boundary
1645 * is used in some logical relation, the function returns 1, else returns 0
1646 */
1647 static int32 some_boundaries_crossed(slv_system_t server, SlvClientToken asys)
1648 {
1649 struct bnd_boundary **bp, *cur_bnd;
1650 int32 numbnds, ind;
1651 slv9_system_t sys;
1652
1653 sys = SLV9(asys);
1654 check_system(sys);
1655
1656 if( sys->blist == NULL ) {
1657 FPRINTF(ASCERR,"ERROR: (slv9) some_boundaries_crossed\n");
1658 FPRINTF(ASCERR," Boundary list was never set.\n");
1659 return 0;
1660 }
1661
1662 bp = sys->blist;
1663 numbnds = slv_get_num_solvers_bnds(server);
1664 for( ind = 0; ind < numbnds; ++ind ) {
1665 cur_bnd = bp[ind];
1666 if (bnd_crossed(cur_bnd) && bnd_in_logrel(cur_bnd)) {
1667 return 1;
1668 }
1669 }
1670 return 0;
1671 }
1672
1673 /*
1674 * Look for some boundary with the AT_ZERO bit active.If this boundary
1675 * is used in some logical relation, the function returns 1, else returns 0
1676 */
1677 static int32 some_boundaries_at_zero(slv_system_t server, SlvClientToken asys)
1678 {
1679 struct bnd_boundary **bp, *cur_bnd;
1680 int32 numbnds, ind;
1681 slv9_system_t sys;
1682
1683 sys = SLV9(asys);
1684 check_system(sys);
1685
1686 if( sys->blist == NULL ) {
1687 FPRINTF(ASCERR,"ERROR: (slv9) some_boundaries_at_zero\n");
1688 FPRINTF(ASCERR," Boundary list was never set.\n");
1689 return 0;
1690 }
1691
1692 bp = sys->blist;
1693 numbnds = slv_get_num_solvers_bnds(server);
1694 for( ind = 0; ind < numbnds; ++ind ) {
1695 cur_bnd = bp[ind];
1696 if (bnd_at_zero(cur_bnd) && bnd_in_logrel(cur_bnd)) {
1697 return 1;
1698 }
1699 }
1700 return 0;
1701 }
1702
1703 /*
1704 * Perform the combinatorial perturbation of the boundaries which are
1705 * at their zero. That means: We are going to perform a combinatorial
1706 * search, changing the truth value of a SATISFIED term (for the
1707 * specified boundaries) ON and OFF, and finding the boolean variables
1708 * affected for those changes in value of the SATISFIED terms.
1709 */
1710 static void do_perturbation_combinations(slv_system_t server,
1711 struct boolean_values *bval,
1712 struct bnd_boundary **bp,
1713 struct dis_discrete **dv,
1714 int32 numdvs,int32 *bndatzero,
1715 int32 ind, int32 numbndf)
1716 {
1717 slv_status_t status;
1718 int32 indpo;
1719
1720 if(ind<(numbndf-1)) {
1721 indpo = ind + 1;
1722 bnd_set_perturb(bp[bndatzero[ind]],TRUE);
1723 do_perturbation_combinations(server,bval,bp,dv,numdvs,
1724 bndatzero,indpo,numbndf);
1725 bnd_set_perturb(bp[bndatzero[ind]],FALSE);
1726 do_perturbation_combinations(server,bval,bp,dv,numdvs,
1727 bndatzero,indpo,numbndf);
1728 } else {
1729 if (ind < numbndf) {
1730 bnd_set_perturb(bp[bndatzero[ind]],TRUE);
1731 solve_logical_relations(server);
1732 slv_get_status(server,&status);
1733 if(!status.converged) {
1734 FPRINTF(ASCERR,"WARNING: \n");
1735 FPRINTF(ASCERR,"(slv9) do_perturbation_combinations\n");
1736 FPRINTF(ASCERR," Not convergence in logical solver \n");
1737 } else {
1738 search_for_modified_dvars(dv,numdvs,bval);
1739 }
1740 bnd_set_perturb(bp[bndatzero[ind]],FALSE);
1741 solve_logical_relations(server);
1742 slv_get_status(server,&status);
1743 if(!status.converged) {
1744 FPRINTF(ASCERR,"WARNING: \n");
1745 FPRINTF(ASCERR,"(slv9) do_perturbation_combinations\n");
1746 FPRINTF(ASCERR," Not convergence in logical solver \n");
1747 } else {
1748 search_for_modified_dvars(dv,numdvs,bval);
1749 }
1750 } else {
1751 FPRINTF(ASCERR,"ERROR: (slv9) do_perturbation_combinations\n");
1752 FPRINTF(ASCERR," Wrong boundary index as argument\n");
1753 }
1754 }
1755 return;
1756 }
1757
1758
1759 /*
1760 * Perform the combinatorial search of the subregions. That means:
1761 * We perform a combinatorial search, changing the value of the
1762 * discrete variables (given in disvars) TRUE and FALSE, and
1763 * finding which cases (in the WHENs) applies for each of the
1764 * combinations.
1765 */
1766 static void do_dvar_values_combinations(struct gl_list_t *disvars,
1767 struct matching_cases *cases,
1768 int numdvf, int d,
1769 int *pos_cases)
1770 {
1771 struct dis_discrete *cur_dis;
1772 int32 *cur_cases;
1773 int32 ncases, dpo;
1774
1775 if(d < numdvf) {
1776 dpo = d + 1;
1777 cur_dis = (struct dis_discrete *)(gl_fetch(disvars,d));
1778 dis_set_boolean_value(cur_dis,TRUE);
1779 do_dvar_values_combinations(disvars,cases,numdvf,dpo,pos_cases);
1780 dis_set_boolean_value(cur_dis,FALSE);
1781 do_dvar_values_combinations(disvars,cases,numdvf,dpo,pos_cases);
1782 } else {
1783 if (d == numdvf) {
1784 cur_dis = (struct dis_discrete *)(gl_fetch(disvars,d));
1785 dis_set_boolean_value(cur_dis,TRUE);
1786 cur_cases = cases_matching(disvars,&ncases);
1787 cases[(*pos_cases)].case_list = cur_cases;
1788 cases[(*pos_cases)].ncases = ncases;
1789 cases[(*pos_cases)].diff_subregion = 1;
1790 (*pos_cases)++;
1791 dis_set_boolean_value(cur_dis,FALSE);
1792 cur_cases = cases_matching(disvars,&ncases);
1793 cases[(*pos_cases)].case_list = cur_cases;
1794 cases[(*pos_cases)].ncases = ncases;
1795 cases[(*pos_cases)].diff_subregion = 1;
1796 (*pos_cases)++;
1797 } else {
1798 FPRINTF(ASCERR,"ERROR: (slv9) do_dvar_values_combinations\n");
1799 FPRINTF(ASCERR," Wrong discrete var index as argument\n");
1800 }
1801 }
1802 return;
1803 }
1804
1805
1806 /*
1807 * Orders of the elements of each array of cases,
1808 * so that we can compare them easier.
1809 */
1810 static void order_case(int32 *case_list, int32 *newcaselist, int ncases)
1811 {
1812 int32 cur_case,pos=0,tmp_num,c,ind;
1813
1814 for (c=1; c<=ncases; c++) {
1815 tmp_num = 0;
1816 for (ind=1; ind<=ncases; ind++) {
1817 cur_case = case_list[ind];
1818 if (tmp_num < cur_case) {
1819 pos = ind;
1820 tmp_num = cur_case;
1821 }
1822 }
1823 case_list[pos] = 0;
1824 newcaselist[ncases-c] = tmp_num;
1825 }
1826 }
1827
1828
1829
1830 /*
1831 * Calls for the ordering of the elements of each array of cases,
1832 * so that we can compare them easier.
1833 */
1834 static void order_cases(struct matching_cases *cases,int pos_cases)
1835 {
1836 int32 *caselist;
1837 int32 cur_ncase,c;
1838 int32 *newcaselist;
1839
1840 for (c=0; c<pos_cases;c++) {
1841 caselist = cases[c].case_list;
1842 cur_ncase = cases[c].ncases;
1843 if (cur_ncase > 1) {
1844 newcaselist = create_array(cur_ncase,int32);
1845 order_case(caselist,newcaselist,cur_ncase);
1846 cases[c].case_list = newcaselist;
1847 destroy_array(caselist);
1848 } else {
1849 if (cur_ncase == 1) {
1850 newcaselist = create_array(1,int32);
1851 newcaselist[0] = caselist[1];
1852 cases[c].case_list = newcaselist;
1853 destroy_array(caselist);
1854 }
1855 }
1856 }
1857
1858 }
1859
1860
1861
1862 /*
1863 * Compare two arrays of cases (integer numbers). It returns 1 if they are
1864 * equal, else it returns 0.
1865 */
1866 static int32 compare_case(int32 *cur_set, int32 *comp_set, int cur_ncases)
1867 {
1868 int32 cur_case, comp_case, ind;
1869
1870 for (ind=0; ind<cur_ncases; ind++) {
1871 cur_case = cur_set[ind];
1872 comp_case = comp_set[ind];
1873 if (cur_case != comp_case) {
1874 return 0;
1875 }
1876 }
1877 return 1;
1878 }
1879
1880
1881 /*
1882 * Compare the arrays of cases so that we can find the number of
1883 * different alternatives (subregions)
1884 */
1885 static void compare_cases(struct matching_cases *cases,int pos_cases)
1886 {
1887 int32 *cur_set, *comp_set, cur_ncases, comp_ncases;
1888 int32 c,d;
1889
1890 for (c=0; c<pos_cases; c++) {
1891 cur_set = cases[c].case_list;
1892 cur_ncases = cases[c].ncases;
1893 if (cur_ncases == 0) {
1894 cases[c].diff_subregion = 0;
1895 continue;
1896 }
1897 for(d=0; d<c; d++) {
1898 comp_set = cases[d].case_list;
1899 comp_ncases = cases[d].ncases;
1900 if (cur_ncases != comp_ncases) {
1901 continue;
1902 } else {
1903 if (compare_case(cur_set,comp_set,cur_ncases)) {
1904 cases[c].diff_subregion = 0;
1905 break;
1906 }
1907 }
1908 }
1909 }
1910 }
1911
1912
1913 /*
1914 * Finds if my current point lies at a "real" boundary. By "real"
1915 * I mean a boundary which really causes a change in the
1916 * configuration. It returns 0 if the boundary at zero does not
1917 * affect the configuration. If the configuration is affected,
1918 * this function will find the number of subregions existing
1919 * for the current point as well as the cases (in WHENs) corresponding
1920 * to each of the subregions. At the end, the number of subregions is
1921 * n_subregions and the cases applying for each of them is stored
1922 * in the structure subregions.
1923 */
1924 static int32 at_a_boundary(slv_system_t server, SlvClientToken asys,
1925 int32 *n_subregions,
1926 struct matching_cases **subregions,
1927 int32 *cur_subregion,
1928 struct gl_list_t *disvars)
1929 {
1930 slv9_system_t sys;
1931 struct bnd_boundary **bp, *cur_bnd;
1932 struct dis_discrete **dv, *cur_dis;
1933 struct boolean_values bval;
1934 dis_filter_t dfilter;
1935 bnd_filter_t bfilter;
1936 struct matching_cases *cases;
1937 int32 *bndatzero;
1938 int32 *dvarmodified;
1939 int32 *cur_cases;
1940 int32 *caselist, *newcaselist;
1941 int32 numbnds, numbndf, b, ind;
1942 int32 numdvs, numdvf, d;
1943 int32 cur_ncases, assign_cur_sub;
1944 int32 pos_cases, comb;
1945 char *param;
1946 union param_value u;
1947
1948 sys = SLV9(asys);
1949 check_system(sys);
1950
1951 if( sys->blist == NULL ) {
1952 FPRINTF(ASCERR,"ERROR: (slv9) at_a_boundary\n");
1953 FPRINTF(ASCERR," Boundary list was never set.\n");
1954 return 0;
1955 }
1956
1957 if( sys->dvlist == NULL ) {
1958 FPRINTF(ASCERR,"ERROR: (slv9) at_a_boundary\n");
1959 FPRINTF(ASCERR," Discrete Variable list was never set.\n");
1960 return 0;
1961 }
1962
1963 if (!some_boundaries_at_zero(server,asys)) {
1964 return 0;
1965 }
1966
1967 bp = sys->blist;
1968 numbnds = slv_get_num_solvers_bnds(server);
1969 bfilter.matchbits = (BND_AT_ZERO);
1970 bfilter.matchvalue = (BND_AT_ZERO);
1971 numbndf = slv_count_solvers_bnds(server,&bfilter);
1972 bndatzero = create_array(numbndf,int32);
1973 ind = 0;
1974 for (b=0; b<numbnds; b++) {
1975 cur_bnd = bp[b];
1976 bnd_set_perturb(cur_bnd,FALSE);
1977 if (bnd_at_zero(cur_bnd)) {
1978 #if SHOW_BOUNDARY_ANALYSIS_DETAILS
1979 FPRINTF(ASCERR,"boundary at zero = %d\n",b);
1980 #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */
1981 bndatzero[ind] = b;
1982 ind++;
1983 }
1984 }
1985
1986 dv = sys->dvlist;
1987 numdvs = slv_get_num_solvers_dvars(server);
1988 bval.cur_val = create_array(numdvs,int32);
1989 bval.pre_val = create_array(numdvs,int32);
1990
1991 for (d=0; d<numdvs; d++) {
1992 cur_dis = dv[d];
1993 dis_set_val_modified(cur_dis,FALSE);
1994 bval.cur_val[d] = dis_value(cur_dis);
1995 bval.pre_val[d] = dis_previous_value(cur_dis);
1996 }
1997
1998 #if SHOW_BOUNDARY_ANALYSIS_DETAILS
1999 FPRINTF(ASCERR,"Executing combinatorial perturbation of boundaries\n");
2000 #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */
2001
2002 /*
2003 * Setting the value of the perturbation mode flag in the logical solver
2004 * to 1.
2005 * PERTURB_BOUNDARY is a boolean parameter of the logical solver
2006 * LRSlv. This parameter tells the solver whether it should change
2007 * the truth value of the SATISFIED terms or not (only for the
2008 * boundaries specified). This trick is important while finding
2009 * the number of subregions around a/several boundary(ies).
2010 */
2011 param = "perturbboundaries";
2012 u.b = 1;
2013 set_param_in_solver(server,LOGICAL_SOLVER,bool_parm,param,&u);
2014
2015 ind = 0;
2016 do_perturbation_combinations(server,&(bval),bp,dv,numdvs,
2017 bndatzero,ind,numbndf);
2018 /*
2019 * Setting the value of the perturbation mode flag in the logical solver
2020 * to 0.
2021 */
2022 u.b = 0;
2023 set_param_in_solver(server,LOGICAL_SOLVER,bool_parm,param,&u);
2024
2025 destroy_array(bndatzero);
2026
2027 dfilter.matchbits = (DIS_VAL_MODIFIED);
2028 dfilter.matchvalue = (DIS_VAL_MODIFIED);
2029 numdvf = slv_count_solvers_dvars(server,&dfilter);
2030
2031 if (numdvf == 0) {
2032 FPRINTF(ASCERR,"Not really at a boundary\n");
2033 for (d=0; d<numdvs; d++) {
2034 cur_dis = dv[d];
2035 dis_set_boolean_value(cur_dis,bval.cur_val[d]);
2036 dis_set_value(cur_dis,bval.cur_val[d]);
2037 dis_set_previous_value(cur_dis,bval.pre_val[d]);
2038 }
2039 destroy_array(bval.cur_val);
2040 destroy_array(bval.pre_val);
2041 return 0;
2042 }
2043
2044 dvarmodified = create_array(numdvf,int32);
2045 ind = 0;
2046 for (d=0; d<numdvs; d++) {
2047 cur_dis = dv[d];
2048 if(dis_val_modified(cur_dis)) {
2049 dvarmodified[ind] = d;
2050 gl_append_ptr(disvars,cur_dis);
2051 dis_set_val_modified(cur_dis,FALSE);
2052 ind++;
2053 }
2054 }
2055
2056 for (d=0; d<numdvs; d++) {
2057 cur_dis = dv[d];
2058 dis_set_boolean_value(cur_dis,bval.cur_val[d]);
2059 dis_set_value(cur_dis,bval.cur_val[d]);
2060 dis_set_previous_value(cur_dis,bval.pre_val[d]);
2061 }
2062
2063 pos_cases = 1;
2064 for (d = 1; d<=numdvf; d++) {
2065 pos_cases = pos_cases * 2;
2066 }
2067
2068 cases = (struct matching_cases *)
2069 (ascmalloc((pos_cases)*sizeof(struct matching_cases)));
2070
2071 #if SHOW_BOUNDARY_ANALYSIS_DETAILS
2072 FPRINTF(ASCERR,"Executing combinatorial search for subregions \n");
2073 #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */
2074
2075 d = 1;
2076 comb = 0;
2077 do_dvar_values_combinations(disvars,cases,numdvf,d,&(comb));
2078
2079 order_cases(cases,pos_cases);
2080 compare_cases(cases,pos_cases);
2081
2082 (*n_subregions) = 0;
2083 for(comb=0; comb<pos_cases;comb++) {
2084 if(cases[comb].diff_subregion) {
2085 (*n_subregions)++;
2086 }
2087 }
2088
2089 if ((*n_subregions)==0) {
2090 FPRINTF(ASCERR,"ERROR: at least one subregion must be found\n");
2091 for (d=0; d<numdvs; d++) {
2092 cur_dis = dv[d];
2093 dis_set_boolean_value(cur_dis,bval.cur_val[d]);
2094 dis_set_value(cur_dis,bval.cur_val[d]);
2095 dis_set_previous_value(cur_dis,bval.pre_val[d]);
2096 }
2097 destroy_array(bval.cur_val);
2098 destroy_array(bval.pre_val);
2099 for(comb=0; comb<pos_cases;comb++) {
2100 destroy_array(cases[comb].case_list);
2101 }
2102 destroy_array(cases);
2103 return 0;
2104 }
2105
2106 if ((*n_subregions)==1) {
2107 FPRINTF(ASCERR,"Not really at a boundary\n");
2108 for (d=0; d<numdvs; d++) {
2109 cur_dis = dv[d];
2110 dis_set_boolean_value(cur_dis,bval.cur_val[d]);
2111 dis_set_value(cur_dis,bval.cur_val[d]);
2112 dis_set_previous_value(cur_dis,bval.pre_val[d]);
2113 }
2114 destroy_array(bval.cur_val);
2115 destroy_array(bval.pre_val);
2116 for(comb=0; comb<pos_cases;comb++) {
2117 destroy_array(cases[comb].case_list);
2118 }
2119 destroy_array(cases);
2120 return 0;
2121 }
2122
2123 if ((*n_subregions) > 0) {
2124 (*subregions) = (struct matching_cases *)
2125 (ascmalloc(((*n_subregions))*sizeof(struct matching_cases)));
2126 (*n_subregions) = 0;
2127 for(comb=0; comb<pos_cases;comb++) {
2128 if(cases[comb].diff_subregion) {
2129 (*subregions)[(*n_subregions)].case_list = cases[comb].case_list;
2130 cases[comb].case_list = NULL;
2131 (*subregions)[(*n_subregions)].ncases = cases[comb].ncases;
2132 cases[comb].ncases = 0;
2133 (*subregions)[(*n_subregions)].diff_subregion = 1;
2134 (*n_subregions)++;
2135 }
2136 }
2137 }
2138
2139 for(comb=0; comb<pos_cases;comb++) {
2140 destroy_array(cases[comb].case_list);
2141 }
2142 destroy_array(cases);
2143
2144
2145 assign_cur_sub = 0;
2146 /*
2147 * Finding the subregion corresponding to the "original" configuration
2148 */
2149 for (d=0; d<numdvs; d++) {
2150 cur_dis = dv[d];
2151 dis_set_boolean_value(cur_dis,bval.cur_val[d]);
2152 dis_set_value(cur_dis,bval.cur_val[d]);
2153 dis_set_previous_value(cur_dis,bval.pre_val[d]);
2154 }
2155 cur_cases = cases_matching(disvars,&cur_ncases);
2156 caselist = cur_cases;
2157 if (cur_ncases > 1) {
2158 newcaselist = create_array(cur_ncases,int32);
2159 order_case(caselist,newcaselist,cur_ncases);
2160 cur_cases = newcaselist;
2161 destroy_array(caselist);
2162 } else {
2163 if (cur_ncases == 1) {
2164 newcaselist = create_array(1,int32);
2165 newcaselist[0] = caselist[1];
2166 cur_cases = newcaselist;
2167 destroy_array(caselist);
2168 }
2169 }
2170 for(comb=0; comb<(*n_subregions);comb++) {
2171 if ((*subregions)[comb].ncases == cur_ncases) {
2172 if(compare_case((*subregions)[comb].case_list,cur_cases,cur_ncases)) {
2173 (*cur_subregion) = comb;
2174 assign_cur_sub = 1;
2175 break;
2176 }
2177 }
2178 }
2179
2180 if (!assign_cur_sub) {
2181 FPRINTF(ASCERR,"PANIC: original configuration not found\n");
2182 }
2183
2184 destroy_array(cur_cases);
2185 destroy_array(dvarmodified);
2186 destroy_array(bval.cur_val);
2187 destroy_array(bval.pre_val);
2188 return 1;
2189 }
2190
2191
2192 /*
2193 * If some boundary(ies) has been crossed in the iterative scheme,
2194 * this function finds the boundary crossed (the first one, if many).
2195 * It returns the factor (less than 1) by which the step length has
2196 * to be multiplied son that the new point will lie precisely
2197 * at that boundary. This factor is found by using the method of
2198 * bisection
2199 */
2200 static real64 return_to_first_boundary(slv_system_t server,
2201 SlvClientToken asys,
2202 struct real_values *rvalues,
2203 var_filter_t *vfilter)
2204 {
2205 slv9_system_t sys;
2206 struct bnd_boundary **bp, *cur_bnd;
2207 struct var_variable **incidences, **bnd_incidences;
2208 struct var_variable *cur_var;
2209 bnd_filter_t bfilter;
2210 struct boolean_values bval;
2211 real64 factor=0.0,fup,flo,newvalue;
2212 int32 *bndcrossed;
2213 int32 *inc_vars;
2214 int32 count,n_incidences,inc,conv_flag,still_crossed;
2215 int32 numbnds,numbndf,b,ind;
2216 int32 iter,n_iterations;
2217 FILE *lif;
2218
2219 sys = SLV9(asys);
2220 check_system(sys);
2221 lif = LIF(sys);
2222
2223 if( sys->blist == NULL ) {
2224 FPRINTF(ASCERR,"ERROR: (slv9) return_to_first_boundary\n");
2225 FPRINTF(ASCERR," Boundary list was never set.\n");
2226 return 1.0;
2227 }
2228
2229 if (!some_boundaries_crossed(server,asys)) {
2230 return 1.0;
2231 }
2232
2233 bp = sys->blist;
2234 numbnds = slv_get_num_solvers_bnds(server);
2235 bfilter.matchbits = (BND_CROSSED);
2236 bfilter.matchvalue = (BND_CROSSED);
2237 numbndf = slv_count_solvers_bnds(server,&bfilter);
2238 bndcrossed = create_array(numbndf,int32);
2239 bval.cur_val = create_array(numbndf,int32);
2240 bval.pre_val = create_array(numbndf,int32);
2241 ind = 0;
2242 for (b=0; b<numbnds; b++) {
2243 cur_bnd = bp[b];
2244 if (bnd_crossed(cur_bnd)) {
2245 bndcrossed[ind] = b;
2246 bval.cur_val[ind] = bnd_status_cur(cur_bnd);
2247 bval.pre_val[ind] = bnd_status_pre(cur_bnd);
2248 ind++;
2249 }
2250 }
2251
2252 count = 0;
2253 for (b=0; b<numbndf; b++) {
2254 cur_bnd = bp[bndcrossed[b]];
2255 n_incidences = bnd_n_real_incidences(cur_bnd);
2256 count = count + n_incidences;
2257 }
2258
2259 incidences = (struct var_variable **)
2260 ( ascmalloc((count)*sizeof(struct var_variable *)));
2261 inc_vars = create_array(count,int32);
2262 count = 0;
2263 for (b=0; b<numbndf; b++) {
2264 cur_bnd = bp[bndcrossed[b]];
2265 bnd_incidences = bnd_real_incidence(cur_bnd);
2266 n_incidences = bnd_n_real_incidences(cur_bnd);
2267 #if SHOW_BOUNDARY_ANALYSIS_DETAILS
2268 FPRINTF(lif,"boundary crossed = %d\n",bndcrossed[b]);
2269 FPRINTF(lif,"previous boundary status = %d\n",bval.pre_val[b]);
2270 FPRINTF(lif,"current boundary status = %d\n",bval.cur_val[b]);
2271 #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */
2272 for (inc=0; inc<n_incidences; inc++) {
2273 incidences[count] = bnd_incidences[inc];
2274 inc_vars[count] = var_mindex(incidences[count]);
2275 count++;
2276 }
2277 }
2278
2279 /* bisection to find first boundary crossed */
2280 fup = 1.0;
2281 flo = 0.0;
2282 conv_flag = 0;
2283 iter = 0;
2284
2285 /*
2286 * Maximum number of bisection iterations. This must be modified
2287 * so that it becomes a parameter to be defined by the user
2288 */
2289 n_iterations = ITER_BIS_LIMIT;
2290
2291 #if SHOW_BOUNDARY_ANALYSIS_DETAILS
2292 for (inc=0; inc<count; inc++) {
2293 cur_var = incidences[inc];
2294 if(var_apply_filter(cur_var,vfilter)) {
2295 FPRINTF(lif,"Variable ");
2296 print_var_name(lif,sys,cur_var); PUTC('\n',lif);
2297 FPRINTF(lif,
2298 "previous value = %f\n",rvalues->pre_values[inc_vars[inc]]);
2299 FPRINTF(lif,"current value = %f\n",rvalues->cur_values[inc_vars[inc]]);
2300 }
2301 }
2302 #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */
2303
2304 while (conv_flag == 0) {
2305 iter++;
2306 if (iter>n_iterations) {
2307 FPRINTF(ASCERR,"ERROR: (slv9) return_to_first_boundary\n");
2308 FPRINTF(ASCERR,"Could not find the first boundary crossed \n");
2309 FPRINTF(ASCERR,"Returning the last factor calculated\n");
2310 break;
2311 }
2312 still_crossed = 0;
2313 factor = ( fup + flo ) / 2.0;
2314 #if SHOW_BISECTION_DETAILS
2315 FPRINTF(lif,"fup = %f\n",fup);
2316 FPRINTF(lif,"flo = %f\n",flo);
2317 FPRINTF(lif,"factor = %f\n",factor);
2318 #endif /* SHOW_BISECTION_DETAILS */
2319 for (inc=0; inc<count; inc++) {
2320 cur_var = incidences[inc];
2321 if(var_apply_filter(cur_var,vfilter)) {
2322 newvalue = rvalues->pre_values[inc_vars[inc]] + factor *
2323 ( rvalues->cur_values[inc_vars[inc]] -
2324 rvalues->pre_values[inc_vars[inc]] );
2325 var_set_value(cur_var,newvalue);
2326 #if SHOW_BISECTION_DETAILS
2327 FPRINTF(lif,"Variable ");
2328 print_var_name(lif,sys,cur_var); PUTC('\n',lif);
2329 FPRINTF(lif,"value after factor = %f\n",newvalue);
2330 #endif /* SHOW_BISECTION_DETAILS */
2331 }
2332 }
2333
2334 update_boundaries(server,asys);
2335 for (b=0; b<numbndf; b++) {
2336 cur_bnd = bp[bndcrossed[b]];
2337 #if SHOW_BISECTION_DETAILS
2338 FPRINTF(lif,"previous status = %d\n", bval.pre_val[b]);
2339 FPRINTF(lif,"status aftert factor = %d\n",bnd_status_cur(cur_bnd));
2340 #endif /* SHOW_BISECTION_DETAILS */
2341 if ( bnd_status_cur(cur_bnd) != bval.pre_val[b] ) {
2342 still_crossed = 1;
2343 }
2344 }
2345 #if SHOW_BISECTION_DETAILS
2346 FPRINTF(lif,"still_crossed = %d\n",still_crossed);
2347 #endif /* SHOW_BISECTION_DETAILS */
2348 if (still_crossed) {
2349 fup = factor;
2350 } else {
2351 flo = factor;
2352 for (b=0; b<numbndf; b++) {
2353 cur_bnd = bp[bndcrossed[b]];
2354 bnd_set_pre_status(cur_bnd,bval.pre_val[b]);
2355 bnd_set_cur_status(cur_bnd,bval.pre_val[b]);
2356 if (bnd_at_zero(cur_bnd)) {
2357 #if SHOW_BOUNDARY_ANALYSIS_DETAILS
2358 FPRINTF(ASCERR,"boundary at zero = %d\n",bndcrossed[b]);
2359 FPRINTF(lif,"factor = %f\n",factor);
2360 for (inc=0; inc<count; inc++) {
2361 cur_var = incidences[inc];
2362 if(var_apply_filter(cur_var,vfilter)) {
2363 FPRINTF(lif,"Variable ");
2364 print_var_name(lif,sys,cur_var); PUTC('\n',lif);
2365 FPRINTF(lif,"value after factor = %f\n",var_value(cur_var));
2366 }
2367 }
2368 #endif /* SHOW_BOUNDARY_ANALYSIS_DETAILS */
2369 conv_flag = 1;
2370 }
2371 }
2372 }
2373 }
2374 destroy_array(bndcrossed);
2375 destroy_array(inc_vars);
2376 destroy_array(bval.cur_val);
2377 destroy_array(bval.pre_val);
2378 destroy_array(incidences);
2379
2380 return factor;
2381 }
2382
2383
2384 /*
2385 * Storing values of real variables.
2386 * ---------------------------------
2387 *
2388 * We use the master list of variables since its order does not change
2389 * and it is given by the master index. We do not touch the master list,
2390 * we only use its order.
2391 */
2392
2393 /*
2394 * Store the values of the var_variables before a newton-like iteration
2395 */
2396 static void store_real_pre_values(slv_system_t server,
2397 struct real_values *rvalues)
2398 {
2399 struct var_variable **master;
2400 struct var_variable *var;
2401 int v, vlen;
2402
2403 master = slv_get_master_var_list(server);
2404 vlen = slv_get_num_master_vars(server);
2405
2406 rvalues->pre_values = create_array(vlen,real64);
2407
2408 for (v=0; v<vlen; v++) {
2409 var = master[v];
2410 rvalues->pre_values[v] = var_value(var);
2411 }
2412 }
2413
2414 /*
2415 * Store the values of the var_variables after a newton-like iteration
2416 */
2417 static void store_real_cur_values(slv_system_t server,
2418 struct real_values *rvalues)
2419 {
2420 struct var_variable **master;
2421 struct var_variable *var;
2422 int v, vlen;
2423
2424 master = slv_get_master_var_list(server);
2425 vlen = slv_get_num_master_vars(server);
2426
2427 rvalues->cur_values = create_array(vlen,real64);
2428
2429 for (v=0; v<vlen; v++) {
2430 var = master[v];
2431 rvalues->cur_values[v] = var_value(var);
2432 }
2433 }
2434
2435 /*
2436 * After the length of the step has been modified so that the current point
2437 * lies at a boundary, the values of all the variables is updated so that
2438 * they all reduce the length of their step by the same factor.
2439 */
2440 static void update_real_var_values(slv_system_t server,
2441 struct real_values *rvalues,
2442 var_filter_t *vfilter, real64 factor)
2443 {
2444 struct var_variable **master;
2445 struct var_variable *var;
2446 real64 newvalue;
2447 int v, vlen;
2448
2449 master = slv_get_master_var_list(server);
2450 vlen = slv_get_num_master_vars(server);
2451
2452 for (v=0; v<vlen; v++) {
2453 var = master[v];
2454 if(var_apply_filter(var,vfilter)) {
2455 newvalue = rvalues->pre_values[v] +
2456 factor * (rvalues->cur_values[v] - rvalues->pre_values[v]);
2457 var_set_value(var,newvalue);
2458 }
2459 }
2460 destroy_array(rvalues->cur_values);
2461 destroy_array(rvalues->pre_values);
2462 }
2463
2464
2465 /*
2466 * Set the flagbit NONBASIC for all the variables in the list
2467 * to the value passed as argument
2468 */
2469 static void set_nonbasic_status_in_var_list(slv_system_t server,
2470 uint32 value)
2471 {
2472 struct var_variable **master;
2473 struct var_variable *var;
2474 int v, vlen;
2475
2476 master = slv_get_master_var_list(server);
2477 vlen = slv_get_num_master_vars(server);
2478
2479 for (v=0; v<vlen; v++) {
2480 var = master[v];
2481 var_set_nonbasic(var,value);
2482 }
2483 }
2484
2485
2486 /*
2487 * After the length of the step has been modified so that the current point
2488 * lies at a boundary, the residuals of the equations are updated.
2489 */
2490 static void update_relations_residuals(slv_system_t server)
2491 {
2492 struct rel_relation **master;
2493 struct rel_relation *rel;
2494 rel_filter_t rfilter;
2495 real64 resid;
2496 int32 r, rlen, status;
2497
2498 master = slv_get_master_rel_list(server);
2499 rlen = slv_get_num_master_rels(server);
2500
2501 rfilter.matchbits = (REL_INCLUDED | REL_EQUALITY);
2502 rfilter.matchvalue = (REL_INCLUDED | REL_EQUALITY);
2503
2504 Asc_SignalHandlerPush(SIGFPE,SIG_IGN);
2505 for (r=0; r<rlen; r++) {
2506 rel = master[r];
2507 if(rel_apply_filter(rel,&rfilter)) {
2508 resid = relman_eval(rel,&status,1);
2509 }
2510 }
2511 Asc_SignalHandlerPop(SIGFPE,SIG_IGN);
2512 }
2513
2514
2515 #ifdef ASC_WITH_CONOPT
2516 /*------------------------------------------------------------------------------
2517 CALLBACK ROUTINES FOR CONOPT
2518 */
2519
2520 /*
2521 * COIRMS Based on the information provided in Coispz, CONOPT will
2522 * allocate the number of vectors into which the user can define
2523 * the details of the model. The details of the model are defined
2524 * here.
2525 *
2526 * COIRMS(lower, curr, upper, vsta, type,rhs, fv, esta, colsta,
2527 * rowno, value, nlflag, n, m, nz, usrmem)
2528 *
2529 * lower - lower bounds on the variables
2530 * curr - intial values of the variables
2531 * upper - upper bounds on the variables
2532 * vsta - initial status of the variable(o nonbasic, 1 basic)
2533 * type - types of equations (0 equality,1 greater,2 less)
2534 * rhs - values of the right hand sides
2535 * fv - sum of the nonlinear terms in the initial point
2536 * esta - initial status of the slack in the constraint (nonbasic,basic)
2537 * colsta- start of column pointers
2538 * rowno - row or equation numbers of the nonzeros
2539 * value - values of the jacobian elements
2540 * nlflag- nonlinearity flags(0 nonzero constant,1 varying)
2541 * n - number of variables
2542 * m - number of constraints
2543 * nz - number of jacobian elements
2544 * usrmem- user memory defined by conopt
2545 */
2546 static int COI_CALL slv9_conopt_readmatrix(
2547 double *lower, double *curr, double *upper
2548 , int *vsta, int *type, double *rhs
2549 , int *esta, int *colsta, int *rowno
2550 , double *value, int *nlflag, int *n, int *m, int *nz
2551 , double *usrmem
2552 ){
2553 slv9_system_t sys;
2554 struct var_variable *var;
2555 struct var_variable **varlist;
2556 struct opt_matrix *coeff_matrix;
2557 static var_filter_t vfilter;
2558 real64 /*obj_val,*/ deriv;
2559 real64 nominal, up, low, uplow;
2560 int32 num_var, n_subregions, c, num_eqns;
2561 int32 numnz, eq;
2562 int32 count, totvar;
2563
2564 UNUSED_PARAMETER(vsta);
2565 UNUSED_PARAMETER(esta);
2566
2567 sys = (slv9_system_t)usrmem;
2568 n_subregions = sys->subregions;
2569 coeff_matrix = sys->coeff_matrix;
2570 num_var = (*n) - n_subregions;
2571 num_eqns = num_var + 1;
2572
2573 vfilter.matchbits = (VAR_ACTIVE_AT_BND | VAR_INCIDENT
2574 | VAR_SVAR | VAR_FIXED);
2575 vfilter.matchvalue = (VAR_ACTIVE_AT_BND | VAR_INCIDENT | VAR_SVAR);
2576 varlist = sys->mvlist;
2577 totvar = sys->mvtot;
2578
2579 /*
2580 * Variables: Current Value, lower value and upper value. Note that for
2581 * this problem the variables are the vector of steps dx. So we "invent"
2582 * approximations for the bounds based on the bounds of the real
2583 * variables of the problem. The use of the parameter ASC_INFINITY is
2584 * Hack to keep CONOPT from complaining for large bounds.
2585 */
2586
2587 count = 0;
2588 for (c=0; c<totvar; c++) {
2589 var = varlist[c];
2590 if (var_apply_filter(var,&vfilter)) {
2591 nominal = var_nominal(var);
2592 low = var_lower_bound(var);
2593 up = var_upper_bound(var);
2594 uplow = fabs( up - low);
2595 lower[count] = -uplow > -CONOPT_BOUNDLIMIT ? -uplow : -0.5*CONOPT_BOUNDLIMIT;
2596 upper[count] = uplow < CONOPT_BOUNDLIMIT ? uplow : 0.5*CONOPT_BOUNDLIMIT;
2597 curr[count] = 0.5 * nominal;
2598 count++;
2599 }
2600 }
2601 /* alphas for each subregion */
2602 for (c=count; c<(*n); c++) {
2603 lower[c] = 0.0;
2604 upper[c] = 1.0;
2605 curr[c] = 1.0;
2606 }
2607
2608
2609 /*
2610 * vsta not in use since STATOK, ipsz[14], is zero
2611 */
2612
2613 /*
2614 * All the equations, but the last row (which is the objective), are
2615 * equalities.
2616 */
2617 for (c = 0; c < (*m); c++) {
2618 type[c] = 0;
2619 }
2620 type[(*m)-1] = 3;
2621
2622
2623 /*
2624 * RHS. It is zero for all the equations except the summation of
2625 * alphas, whose RHS is one.
2626 */
2627 for (c = 0; c < (*m); c++) {
2628 rhs[c] = 0;
2629 }
2630 rhs[(*m)-2] = 1.0;
2631
2632 #ifdef DISUSED_CONOPT_PARAMETER
2633 /*
2634 * fv =0 for all linear relations. For the objective is the two
2635 * norm
2636 */
2637 for (c = 0; c < (*m); c++) {
2638 fv[c] = 0;
2639 }
2640 obj_val = 0.0;
2641 for (c = 0; c<num_var; c++) {
2642 obj_val = obj_val + (curr[c] * curr[c]);
2643 }
2644 fv[(*m)-1] = obj_val;
2645 #endif
2646
2647 /*
2648 * esta not used since STATOK is zero
2649 */
2650
2651
2652 /*
2653 * For the following parameters, it is important ot see that:
2654 * 1) The values for the rows and nonzeros that conopt wants start
2655 * with 1, not with 0.
2656 * 2) The indeces of the arrays that we are using in the C side start
2657 * with 0.
2658 */
2659
2660 /*
2661 * colsta
2662 */
2663
2664 for (c=0; c<num_var; c++) {
2665 colsta[c] = 2 * c;
2666 }
2667
2668 for (c=num_var; c<(*n); c++) {
2669 colsta[c] = 2 * num_var + num_eqns * (c - num_var);
2670 }
2671
2672 colsta[*n] = *nz; /** @TODO check this */
2673
2674 /*
2675 rowno, value and nlflag can be done in same loop. The use of the
2676 parameter RTMAXJ is really a Hack to keep CONOPT from complaining
2677 about large derivatives
2678 */
2679
2680 numnz = 0;
2681 CONSOLE_DEBUG("NUM_VAR = %d",num_var);
2682 for (c=0; c<num_var; c++) {
2683 CONSOLE_DEBUG("C = %d",c);
2684 rowno[numnz] = c;
2685 nlflag[numnz] = 0;
2686 value[numnz] = -1;
2687 numnz++;
2688 CONSOLE_DEBUG("NUMNZ = %d",numnz);
2689 rowno[numnz] = *m - 1;
2690 nlflag[numnz] = 1;
2691 CONSOLE_DEBUG("FOUND A NONLINEAR NONZERO");
2692 numnz++;
2693 CONSOLE_DEBUG("NUMNZ = %d",numnz);
2694 }
2695
2696 for (c=num_var; c<(*n); c++) {
2697 numnz = 2 * num_var + num_eqns * (c - num_var);
2698 for(eq = 0; eq<num_eqns-1; eq++) {
2699 rowno[numnz] = eq;
2700 nlflag[numnz] = 0;
2701 deriv = -1.0 * (coeff_matrix->cols[c - num_var].element[eq]);
2702 if (deriv > RTMAXJ ) {
2703 deriv = 0.5 * RTMAXJ;
2704 } else {
2705 if (deriv < -RTMAXJ ) {
2706 deriv = -0.5*RTMAXJ;
2707 }
2708 }
2709 value[numnz] = deriv;
2710 numnz++;
2711 }
2712 rowno[numnz] = num_eqns - 1;
2713 nlflag[numnz] = 0;
2714 value[numnz] = 1.0;
2715 }
2716
2717 return 0;
2718 }
2719
2720 #if 0 /* not in API any more */
2721 /*
2722 * COIFBL Defines the nonlinearities of the model by returning
2723 * numerical values. It works on a block of rows during each call.
2724 * COIFBL( x, g, otn, nto, from, to, jac, stcl, rnum, cnum, nl, strw,
2725 * llen, indx, mode, errcnt, n, m, n1, m1, nz, usrmem)
2726 *
2727 * x - punt of evaluation provided by conopt
2728 * g - vector of function values
2729 * otn - old to new permutation vector
2730 * nto - new to old permutation vector
2731 * from - range in permutation
2732 * to - range in permutation
2733 * jac - vector of jacobian values.
2734 * The following are vectors defining the jacobian structure
2735 * stcl - start of column pointers
2736 * rnum - row numbers
2737 * cnum - column numbers
2738 * nl - nonlinearity flags
2739 * strw - start row pointers
2740 * llen - count of linear jacobian elements
2741 * indx - pointers from the row-wise representation
2742 * mode - indicator of mode of evaluation
2743 * errcnt- number of function evaluation errors
2744 * n - umber of variables
2745 * m - number of constraints
2746 * n1 - n+1
2747 * m1 - m+1
2748 * nz - number of jacobian elements
2749 * usrmem- user memory defined by conopt
2750 */
2751 static void slv9_coifbl(real64 *x, real64 *g, int32 *otn, int32 *nto,
2752 int32 *from, int32 *to, real64 *jac, int32 *stcl,
2753 int32 *rnum, int32 *cnum, int32 *nl, int32 *strw,
2754 int32 *llen, int32 *indx, int32 *mode, int32 *errcnt,
2755 int32 *n, int32 *m, int32 *n1, int32 *m1,
2756 int32 *nz, real64 *usrmem)
2757 {
2758 /* non defined for this solver */
2759
2760 /* stop gcc whining about unused parameter */
2761 (void)x; (void)g; (void)otn; (void)nto; (void)from; (void)to;
2762 (void)jac; (void)stcl; (void)rnum; (void)cnum; (void)nl; (void)strw;
2763 (void)llen; (void)indx; (void)mode; (void)errcnt; (void)n; (void)m;
2764 (void)n1; (void)m1; (void)nz;
2765 (void)usrmem;
2766
2767 return;
2768 }
2769 #endif
2770
2771 /*
2772 * COIFDE Defines the nonlinearities of the model by returning
2773 * numerical values. It works on one row or equation at a time
2774 * COIFDE(x, g, jac, rowno, jcnm, mode, errcnt, newpt, n, nj, usrmem)
2775 *
2776 * x - punt of evaluation provided by conopt
2777 * g - function value
2778 * jac - jacobian values
2779 * rowno - number of the row for which nonlinearities will be eval
2780 * jcnm - list of column number fon the NL nonzeros
2781 * mode - indicator of mode of evaluation
2782 * errcnt - sum of number of func evaluation errors thus far
2783 * newpt - new point indicator
2784 * nj - number of nonlinear nonzero jacobian elements
2785 * n - number of variables
2786 * usrmem - user memory
2787 *
2788 * For the optimization problem at a boundary, this subroutine will
2789 * be called only of the objective function, constraint number m.
2790 *
2791 */
2792 static int COI_CALL slv9_conopt_fdeval(
2793 double *x, double *g, double *jac
2794 , int *rowno, int *jcnm, int *mode, int *ignerr
2795 , int *errcnt, int *newpt, int *n, int *nj
2796 , double *usrmem
2797 ){
2798 slv9_system_t sys;
2799 int32 num_vars, v;
2800 real64 obj, deriv;
2801
2802 UNUSED_PARAMETER(jcnm);
2803 UNUSED_PARAMETER(errcnt);
2804 UNUSED_PARAMETER(newpt);
2805 UNUSED_PARAMETER(n);
2806 UNUSED_PARAMETER(nj);
2807
2808 sys = (slv9_system_t)usrmem;
2809 num_vars = sys->con.n - sys->subregions;
2810
2811 if (*mode == 1 || *mode == 3) {
2812 if (*rowno == sys->con.m - 1){
2813 obj = 0.0;
2814 for (v=0; v<num_vars; v++) {
2815 obj = obj + (x[v] * x[v]);
2816 }
2817 *g = obj;
2818 } else {
2819 FPRINTF(ASCERR,"Wrong number of constraint in COIFDE");
2820 return 1;
2821 }
2822 }
2823
2824 /*
2825 * The use of the parameter RTMAXJ is really a Hack to keep CONOPT
2826 * from complaining about large derivatives.
2827 */
2828
2829 if (*mode == 2 || *mode == 3) {
2830 if (*rowno == sys->con.m - 1){
2831 for (v=0; v<num_vars; v++) {
2832 deriv = 2.0 * x[v];
2833 if (deriv > RTMAXJ ) {
2834 deriv = 0.5*RTMAXJ;
2835 } else {
2836 if (deriv < -RTMAXJ ) {
2837 deriv = -0.5*RTMAXJ;
2838 }
2839 }
2840 jac[v] = deriv;
2841 }
2842 } else {
2843 FPRINTF(ASCERR,"Wrong number of constraint in COIFDE");
2844 return 1;
2845 }
2846 }
2847
2848 return 0;
2849 }
2850
2851
2852 /*
2853 * COISTA Pass the solution from CONOPT to the modeler. It returns
2854 * completion status
2855 * COISTA(modsta, solsts, iter, objval, usrmem)
2856 *
2857 * modsta - model status
2858 * solsta - solver status
2859 * iter - number of iterations
2860 * objval - objective value
2861 * usrmem - user memory
2862 */
2863 static int COI_CALL slv9_conopt_status(int *modsta, int *solsta, int *iter
2864 , double *objval, double *usrmem
2865 ){
2866 slv9_system_t sys;
2867
2868 sys = (slv9_system_t)usrmem;
2869
2870 sys->con.modsta = *modsta;
2871 sys->con.solsta = *solsta;
2872 sys->con.iter = *iter;
2873 sys->con.obj = *objval;
2874
2875 return 0;
2876 }
2877
2878
2879 /*
2880 * COIRS Pass the solution from CONOPT to the modeler. It returns
2881 * solution values
2882 * COIRS(val, xmar, xbas, xsta, yval, ymar, ybas, ysta, n, m, usrmem)
2883 *
2884 * xval - the solution values of the variables
2885 * xmar - corresponding marginal values
2886 * xbas - basis indicator for column (at bound, basic, nonbasic)
2887 * xsta - status of column (normal, nonoptimal, infeasible,unbounded)
2888 * yval - values of the left hand side in all the rows
2889 * ymar - corresponding marginal values
2890 * ybas - basis indicator for row
2891 * ysta - status of row
2892 * n - number of variables
2893 * m - number of constraints
2894 * usrmem - user memory
2895 */
2896 static int COI_CALL slv9_conopt_solution(double *xval, double *xmar, int *xbas, int *xsta,
2897 double *yval, double *ymar, int *ybas, int * ysta,
2898 int *n, int *m, double *usrmem
2899 ){
2900 slv9_system_t sys;
2901 struct opt_vector *opt_var_values;
2902 int32 c;
2903 real64 value;
2904
2905 UNUSED_PARAMETER(xmar);UNUSED_PARAMETER(xbas);UNUSED_PARAMETER(xsta);
2906 UNUSED_PARAMETER(yval);UNUSED_PARAMETER(ymar);UNUSED_PARAMETER(ybas);
2907 UNUSED_PARAMETER(ysta);UNUSED_PARAMETER(m);
2908
2909 sys = (slv9_system_t)usrmem;
2910 opt_var_values = sys->opt_var_values;
2911
2912 for (c = 0; c < (*n); c++) {
2913 value = xval[c];
2914 opt_var_values->element[c] = value;
2915 }
2916
2917 return 0;
2918 }
2919
2920 #if 0
2921 /*
2922 * COIUSZ communicates and update of an existing model to CONOPT
2923 * COIUSZ(nintg, ipsz, nreal, rpsz, usrmem)
2924 *
2925 * nintg - number of positions in ipsz
2926 * ipsz - array describing problem size and options
2927 * nreal - number of positions in rpsz
2928 * rpsz - array of reals describing problem size and options
2929 * usrmem- user memory
2930 */
2931 static void slv9_coiusz(int32 *nintg, int32 *ipsz, int32 *nreal, real64 *rpsz,
2932 real64 *usrmem)
2933 {
2934 /* non defined for this solver */
2935
2936 /*
2937 * stop gcc whining about unused parameter
2938 */
2939 (void)nintg; (void)ipsz; (void)nreal; (void)rpsz;
2940 (void)usrmem;
2941
2942 return;
2943 }
2944 #endif
2945
2946 /*
2947 * COIOPT communicates non-default option values to CONOPT
2948 * COIOPT(name, rval, ival, lval, usrmem)
2949 * name - the name of a CONOPT CR-cell defined by the modeler
2950 * rval - the value to be assigned to name if the cells contains a real
2951 * ival - the value to be assigned to name if the cells contains an int
2952 * lval - the value to be assigned to name if the cells contains a log value
2953 * usrmem - user memory
2954 */
2955 static int COI_CALL slv9_conopt_option(
2956 int *NCALL, double *rval, int *ival, int *logical
2957 , double *usrmem, char *name, int lenname
2958 ){
2959 slv9_system_t sys;
2960 sys = (slv9_system_t)usrmem;
2961
2962 UNUSED_PARAMETER(logical);
2963
2964 name = memset(name,' ',8);
2965 while (sys->con.opt_count < slv9_PA_SIZE) {
2966 if (strlen(sys->p.parms[sys->con.opt_count].interface_label) == 6) {
2967 if (strncmp(sys->p.parms[sys->con.opt_count].interface_label,
2968 "R",1) == 0) {
2969 name = strncpy(name, sys->p.parms[sys->con.opt_count]. /* . break */
2970 interface_label,6);
2971 *rval = sys->p.parms[sys->con.opt_count].info.r.value;
2972 sys->con.opt_count++;
2973 return 0;
2974 } else if (strncmp(sys->p.parms[sys->con.opt_count]. /* . break */
2975 interface_label,"L",1) == 0) {
2976 name = strncpy(name,sys->p.parms[sys->con.opt_count]. /* . break */
2977 interface_label,6);
2978 *ival = sys->p.parms[sys->con.opt_count].info.i.value;
2979 sys->con.opt_count++;
2980 return 0;
2981 }
2982 }
2983 sys->con.opt_count++;
2984 }
2985
2986 /* sending blank to quit iterative calling */
2987 name = memset(name,' ',8);
2988 return 0;
2989 }
2990
2991
2992 #if 0 /* not in API any more */
2993 /*
2994 * COIPSZ communicates the model size and structure to CONOPT
2995 * COIPSZ(nintgr, ipsz, nreal, rpsz, usrmem)
2996 *
2997 * ningtr - number of positions in ipsz
2998 * ipsz - array describing problem size and options
2999 * nreal - number of positions in rpsz
3000 * rpsz - array of reals describing problem size and options
3001 * usrmem - user memory
3002 */
3003 static void slv9_coipsz(int32 *nintg, int32 *ipsz, int32 *nreal, real64 *rpsz,
3004 real64 *usrmem)
3005 {
3006 slv9_system_t sys;
3007
3008 /*
3009 * stop gcc whining about unused parameter
3010 */
3011 (void)nintg; (void)nreal;
3012
3013 sys = (slv9_system_t)usrmem;
3014 /*
3015 * Integer array
3016 */
3017 ipsz[F2C(1)] = sys->con.n; /* variables */
3018 ipsz[F2C(2)] = sys->con.m; /* constraints including objective */
3019 ipsz[F2C(3)] = sys->con.nz; /* non zeros in Jacobian */
3020 ipsz[F2C(4)] = sys->con.nz - (sys->con.m - 2); /* linear nonzeros */
3021 ipsz[F2C(5)] = sys->con.m - 2; /* nonlinear nonzeros */
3022 ipsz[F2C(6)] = -1; /* direction of optimization min */
3023 ipsz[F2C(7)] = sys->con.m; /* objective will be last row */
3024 ipsz[F2C(8)] = OPT_ITER_LIMIT; /* iteration limit */
3025 ipsz[F2C(9)] = DOMLIM; /* max number of error in func evals */
3026 ipsz[F2C(10)] = 0; /* output to file */
3027 ipsz[F2C(11)] = 1; /* progress info to screen */
3028 ipsz[F2C(12)] = 1; /* correct value of func in coirms */
3029 ipsz[F2C(13)] = 0; /* not correct value of jacs in coirms */
3030 ipsz[F2C(14)] = 0; /* status not known by modeler */
3031 ipsz[F2C(15)] = 0; /* function value include only NL terms */
3032 ipsz[F2C(16)] = 1; /* Objective is a constraint */
3033 ipsz[F2C(17)] = 0; /* sorted order for jacobian */
3034 ipsz[F2C(18)] = 0; /* append the log file after restarts */
3035 ipsz[F2C(19)] = 0; /* one subroutine call to coirms */
3036 ipsz[F2C(20)] = 0; /* eval subroutine is coifde */
3037 ipsz[F2C(21)] = 0; /* no debugging of derivatives */
3038 ipsz[F2C(22)] = 0; /* coifde not called for linear eqns */
3039 /*
3040 * skipping remainder of ipsz which are fortran io parameters
3041 */
3042
3043 /*
3044 * Real array
3045 */
3046 rpsz[F2C(1)] = ASC_INFINITY; /* infinity */
3047 rpsz[F2C(2)] = -ASC_INFINITY; /* -infinity */
3048 rpsz[F2C(3)] = UNDEFINED; /* undefined */
3049 rpsz[F2C(6)] = 0; /* work space allocated by conopt */
3050 rpsz[F2C(7)] = TIME_LIMIT; /* resource limit (time) */
3051 rpsz[F2C(8)] = 1; /* initial value for vars if none given */
3052
3053
3054 }
3055 #endif
3056
3057
3058 /**
3059 slv_conopt iterate calls conopt start, which calls coicsm
3060 to starts CONOPT. The use of conopt_start is a hack to avoid
3061 unresolved external during the linking of the CONOPT library.
3062
3063 @see conopt.h
3064 */
3065 static void slv_conopt_iterate(slv9_system_t sys){
3066 int n;
3067
3068 if(sys->con.cntvect == NULL){
3069 sys->con.cntvect = ASC_NEW_ARRAY(int,COIDEF_Size());
3070 }
3071
3072 COIDEF_Ini(sys->con.cntvect);
3073
3074 /*
3075 We pass pointer to sys as usrmem data.
3076 Cast back to slv9_system_t to access the information required
3077 */
3078 COIDEF_UsrMem(sys->con.cntvect,(double *)sys);
3079
3080 COIDEF_NumVar(sys->con.cntvect, &(sys->con.n));
3081 COIDEF_NumCon(sys->con.cntvect, &(sys->con.m)); /* include the obj fn */
3082 COIDEF_NumNZ(sys->con.cntvect, &(sys->con.nz));
3083 COIDEF_NumNlNz(sys->con.cntvect, &(sys->con.nlnz));
3084 COIDEF_OptDir(sys->con.cntvect, &(sys->con.optdir));
3085
3086 COIDEF_ObjCon(sys->con.cntvect, &(sys->con.objcon)); /* objective will be last row */
3087 COIDEF_Base(sys->con.cntvect, &(sys->con.base));
3088 COIDEF_ErrLim(sys->con.cntvect, &(DOMLIM));
3089 COIDEF_ItLim(sys->con.cntvect, &(OPT_ITER_LIMIT));
3090
3091 COIDEF_ReadMatrix(sys->con.cntvect, &slv9_conopt_readmatrix);
3092 COIDEF_FDEval(sys->con.cntvect, &slv9_conopt_fdeval);
3093 COIDEF_Option(sys->con.cntvect, &slv9_conopt_option);
3094 COIDEF_Solution(sys->con.cntvect, &slv9_conopt_solution);
3095 COIDEF_Status(sys->con.cntvect, &slv9_conopt_status);
3096 COIDEF_Message(sys->con.cntvect, &asc_conopt_message);
3097 COIDEF_ErrMsg(sys->con.cntvect, &asc_conopt_errmsg);
3098 COIDEF_Progress(sys->con.cntvect, &asc_conopt_progress);
3099
3100 /** @TODO implement the following options as well... */
3101 #if 0
3102 ipsz[F2C(10)] = 0; /* output to file */
3103 ipsz[F2C(11)] = 1; /* progress info to screen */
3104 ipsz[F2C(12)] = 1; /* correct value of func in coirms */
3105 ipsz[F2C(13)] = 0; /* not correct value of jacs in coirms */
3106 ipsz[F2C(14)] = 0; /* status not known by modeler */
3107 ipsz[F2C(15)] = 0; /* function value include only NL terms */
3108 ipsz[F2C(16)] = 1; /* Objective is a constraint */
3109 ipsz[F2C(17)] = 0; /* sorted order for jacobian */
3110 ipsz[F2C(18)] = 0; /* append the log file after restarts */
3111 ipsz[F2C(19)] = 0; /* one subroutine call to coirms */
3112 ipsz[F2C(20)] = 0; /* eval subroutine is coifde */
3113 ipsz[F2C(21)] = 0; /* no debugging of derivatives */
3114 ipsz[F2C(22)] = 0; /* coifde not called for linear eqns */
3115 /*
3116 * skipping remainder of ipsz which are fortran io parameters
3117 */
3118
3119 /*
3120 * Real array
3121 */
3122 rpsz[F2C(1)] = ASC_INFINITY; /* infinity */
3123 rpsz[F2C(2)] = -ASC_INFINITY; /* -infinity */
3124 rpsz[F2C(3)] = UNDEFINED; /* undefined */
3125 rpsz[F2C(6)] = 0; /* work space allocated by conopt */
3126 rpsz[F2C(7)] = TIME_LIMIT; /* resource limit (time) */
3127 rpsz[F2C(8)] = 1; /* initial value for vars if none given */
3128 #endif
3129
3130 /*
3131 * reset count on coiopt calls
3132 */
3133 sys->con.opt_count = 0;
3134
3135 /*
3136 * do not keep model in memory after solution
3137 */
3138 sys->con.kept = 0;
3139
3140 COI_Solve(sys->con.cntvect);
3141 /* conopt_start(&(sys->con.kept), usrmem, &(sys->con.lwork),
3142 sys->con.work, &(sys->con.maxusd), &(sys->con.curusd)); */
3143
3144 /*
3145 * We assume that we get convergence in optimization problem at
3146 * boundary
3147 */
3148 sys->con.optimized = 1;
3149 }
3150
3151 #endif /* ASC_WITH_CONOPT */
3152
3153 /*-------------------end of conopt callbacks----------------------------------*/
3154
3155
3156 /*
3157 * Creates an array of columns (containing an array of real elements
3158 * each) to storage the linear coefficient matrix of the optimization problem.
3159 * It also creates the arrays of reals required to storage the values
3160 * of the gradients of a subregion, which change depending on whether the
3161 * problem is a simulation or an optimization.
3162 */
3163 static void create_opt_matrix_and_vectors(int32 num_opt_eqns,
3164 int32 n_subregions,
3165 struct opt_matrix *coeff_matrix,
3166 struct opt_vector *opt_var_values,
3167 struct opt_vector *invariant,
3168 struct opt_vector *variant,
3169 struct opt_vector *gradient,
3170 struct opt_matrix *multipliers)
3171 {
3172 int32 c;
3173 int32 num_vars;
3174
3175 num_vars = num_opt_eqns - 1 + n_subregions;
3176
3177 coeff_matrix->cols = (struct opt_vector *)
3178 (ascmalloc(n_subregions*sizeof(struct opt_vector)));
3179
3180 if (g_optimizing) {
3181 multipliers->cols = (struct opt_vector *)
3182 (ascmalloc(n_subregions*sizeof(struct opt_vector)));
3183 }
3184
3185 for (c=0; c<n_subregions; c++) {
3186 coeff_matrix->cols[c].element =
3187 (real64 *)(ascmalloc(num_opt_eqns*sizeof(real64)));
3188 }
3189 opt_var_values->element = (real64 *)(ascmalloc(num_vars*sizeof(real64)));
3190
3191 if (g_optimizing) {
3192 gradient->element = (real64 *)(ascmalloc(num_opt_eqns*sizeof(real64)));
3193 } else {
3194 invariant->element = (real64 *)(ascmalloc(num_opt_eqns*sizeof(real64)));
3195 variant->element = (real64 *)(ascmalloc(num_opt_eqns*sizeof(real64)));
3196 }
3197 }
3198
3199
3200 /*
3201 * destroy the arrays created to storage the gradients for the optimization
3202 * problem
3203 */
3204 static void destroy_opt_matrix_and_vectors(int32 n_subregions,
3205 struct opt_matrix *coeff_matrix,
3206 struct opt_vector *opt_var_values,
3207 struct opt_vector *invariant,
3208 struct opt_vector *variant,
3209 struct opt_vector *gradient,
3210 struct opt_matrix *multipliers)
3211 {
3212 int32 c;
3213 for (c=0; c<n_subregions; c++) {
3214 destroy_array(coeff_matrix->cols[c].element);
3215 if (g_optimizing) {
3216 destroy_array(multipliers->cols[c].element);
3217 }
3218 }
3219 destroy_array(coeff_matrix->cols);
3220 destroy_array(opt_var_values->element);
3221 if (g_optimizing) {
3222 destroy_array(multipliers->cols);
3223 destroy_array(gradient->element);
3224 } else {
3225 destroy_array(invariant->element);
3226 destroy_array(variant->element);
3227 }
3228 }
3229
3230
3231
3232 /*
3233 * Set Factorization Options
3234 */
3235 static void set_factor_options (linsolqr_system_t lsys)
3236 {
3237 linsolqr_prep(lsys,linsolqr_fmethod_to_fclass(ranki_ba2));
3238 linsolqr_set_pivot_zero(lsys, 1e-12);
3239 linsolqr_set_drop_tolerance(lsys,1e-16);
3240 linsolqr_set_pivot_tolerance(lsys, 0.1);
3241 linsolqr_set_condition_tolerance(lsys, 0.1);
3242 }
3243
3244
3245 /*
3246 * Calculating the Lagrange Multipliers for each subregion
3247 *
3248 * We are assuming here that the matrix is structurally nonsingular
3249 * and than the rank is equal to the number of rows in the matrix.
3250 * Much more efficient checking must be done.
3251 */
3252 static void get_multipliers(SlvClientToken asys,
3253 int32 subregion,
3254 int32 nrel,
3255 real64 *grad_obj,
3256 struct opt_matrix *multipliers)
3257 {
3258 slv9_system_t sys;
3259 linsolqr_system_t lsys;
3260 mtx_region_t *newblocks, *oneblock;
3261 int32 rank;
3262 int32 c, cr, len, row;
3263 real64 *weights;
3264 real64 summ;
3265
3266 sys = SLV9(asys);
3267 check_system(sys);
3268
3269 mtx_output_assign(sys->lin_mtx,nrel,nrel);
3270 rank = mtx_symbolic_rank(sys->lin_mtx);
3271 mtx_partition(sys->lin_mtx);
3272 len = mtx_number_of_blocks(sys->lin_mtx);
3273 newblocks = ASC_NEW_ARRAY(mtx_region_t,len);
3274 if (newblocks == NULL) {
3275 mtx_destroy(sys->lin_mtx);
3276 return;
3277 }
3278 for (c = 0 ; c < len; c++) {
3279 mtx_block(sys->lin_mtx,c,&(newblocks[c]));
3280 }
3281 for (c = 0 ; c < len; c++) {
3282 mtx_reorder(sys->lin_mtx,&(newblocks[c]),mtx_SPK1);
3283 }
3284
3285 /* unifying block */
3286 oneblock = (mtx_region_t *)ascmalloc(sizeof(mtx_region_t));
3287 oneblock->row.low = oneblock->col.low = 0;
3288 oneblock->row.high = nrel-1;
3289 oneblock->col.high = nrel-1;
3290
3291 /*
3292 * Scaling of the linear system
3293 */
3294
3295 /*
3296 *Calculating weights
3297 */
3298 weights = ASC_NEW_ARRAY(real64,nrel);
3299 for (row=0; row<nrel; row++) {
3300 summ = mtx_sum_sqrs_in_row(sys->lin_mtx,row,&(oneblock->col));
3301 if (summ <= 0.0) {
3302 weights[row] = 1.0;
3303 } else {
3304 weights[row] = 1.0 / sqrt(summ);
3305 }
3306 #if DEBUG
3307 FPRINTF(ASCERR," weight of row %d = %f \n",row,summ);
3308 #endif /* DEBUG */
3309 }
3310
3311 /*
3312 * Dividing rows by weights
3313 */
3314 for (row=0; row<nrel; row++) {
3315 mtx_mult_row(sys->lin_mtx,row,weights[row],&(oneblock->col));
3316 }
3317
3318 /*
3319 * dividing rhs
3320 */
3321 for (row=0; row<nrel; row++) {
3322 grad_obj[mtx_row_to_org(sys->lin_mtx,row)] =
3323 grad_obj[mtx_row_to_org(sys->lin_mtx,row)] * weights[row];
3324 }
3325
3326 /*
3327 * End of scaling
3328 */
3329
3330 lsys = linsolqr_create();
3331 linsolqr_set_matrix(lsys,sys->lin_mtx);
3332
3333 for (cr=0; cr<nrel; cr++) {
3334 multipliers->cols[subregion].element[cr] = 0.0;
3335 }
3336
3337 set_factor_options(lsys);
3338 /* rhs for multipliers */
3339 linsolqr_add_rhs(lsys,grad_obj,FALSE);
3340 linsolqr_set_region(lsys,*oneblock);
3341 linsolqr_factor(lsys,ranki_ba2);
3342 linsolqr_solve(lsys,grad_obj);
3343 for (cr=0; cr<nrel; cr++) {
3344 multipliers->cols[subregion].element[cr] = linsolqr_var_value
3345 (lsys,grad_obj,cr);
3346 #if SHOW_LAGRANGE_DETAILS
3347 FPRINTF(ASCERR, " Row = %d \n",cr);
3348 FPRINTF(ASCERR,
3349 "Multiplier = %f \n",multipliers->cols[subregion].element[cr]);
3350 #endif /* SHOW_LAGRANGE_DETAILS */
3351 }
3352 linsolqr_set_matrix(lsys,NULL);
3353 mtx_destroy(sys->lin_mtx);
3354 linsolqr_destroy(lsys);
3355 destroy_array(newblocks);
3356 destroy_array(weights);
3357 ascfree(oneblock);
3358 }
3359
3360
3361 /*
3362 * Calculate the invariant part of the gradients of the subregions
3363 */
3364 static void get_gradient_in_subregion(slv_system_t server,
3365 SlvClientToken asys,
3366 int32 subregion,
3367 int32 num_opt_eqns,
3368 struct opt_vector *gradient,
3369 struct opt_matrix *multipliers)
3370 {
3371 slv9_system_t sys;
3372 struct rel_relation **rlist;
3373 struct var_variable **vlist;
3374 struct rel_relation *rel;
3375 struct var_variable *var;
3376 var_filter_t vfilter;
3377 rel_filter_t rfilter;
3378 mtx_coord_t coord;
3379 real64 *tmp_value;
3380 real64 *derivatives, resid;
3381 real64 *grad_obj, *func_val;
3382 real64 *f_red_grad;
3383 struct opt_matrix rel_red_grad;
3384 int32 *variables_master, *variables_solver, count;
3385 int32 nvar, nrel, ntotvar, ntotrel;
3386 int32 countrel,countvar,cr,cv,len,vind;
3387 int32 nvnb, countnbv;
3388 FILE *lif;
3389
3390 sys = SLV9(asys);
3391 check_system(sys);
3392 lif = LIF(sys);
3393
3394 rlist = slv_get_master_rel_list(server);
3395 vlist = slv_get_master_var_list(server);
3396 ntotvar = slv_get_num_master_vars(server);
3397 ntotrel = slv_get_num_master_rels(server);
3398 tmp_value = ASC_NEW_ARRAY(real64,ntotvar);
3399
3400 vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_NONBASIC
3401 | VAR_SVAR | VAR_FIXED);
3402 vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR);
3403 nvar = slv_count_master_vars(server,&vfilter);
3404
3405 rfilter.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE );
3406 rfilter.matchvalue =(REL_INCLUDED | REL_EQUALITY | REL_ACTIVE );
3407 nrel = slv_count_master_rels(server,&rfilter);
3408
3409 if (nrel != nvar) {
3410 FPRINTF(ASCERR," nrel = %d\n",nrel);
3411 FPRINTF(ASCERR," nvar = %d\n",nvar);
3412 FPRINTF(ASCERR,
3413 "PANIC: number relations does not match number of variables\n");
3414 }
3415
3416 /*
3417 * residual of the relations in the subregion
3418 */
3419 func_val = ASC_NEW_ARRAY(real64,nrel);
3420
3421 /*
3422 * Lagrange Multipliers of the subregion
3423 */
3424 multipliers->cols[subregion].element =
3425 (real64 *)(ascmalloc(nrel*sizeof(real64)));
3426 /*
3427 * Gradients of the objective function
3428 */
3429 grad_obj = ASC_NEW_ARRAY(real64,nvar);
3430
3431 /*
3432 * Matrix for solving linear system
3433 */
3434 sys->lin_mtx = mtx_create();
3435 mtx_set_order(sys->lin_mtx,nrel);
3436
3437 /*
3438 * Counting nonbasic variables
3439 */
3440 vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_NONBASIC
3441 | VAR_SVAR | VAR_FIXED);
3442 vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_NONBASIC
3443 | VAR_SVAR);
3444 nvnb = slv_count_master_vars(server,&vfilter);
3445
3446 /*
3447 * Information for reduced gradient
3448 */
3449 f_red_grad = ASC_NEW_ARRAY(real64,nvnb);
3450 rel_red_grad.cols = (struct opt_vector *)
3451 (ascmalloc(nvnb*sizeof(struct opt_vector)));
3452 for (cv=0; cv<nvnb; cv++) {
3453 rel_red_grad.cols[cv].element =
3454 (real64 *)(ascmalloc(nrel*sizeof(real64)));
3455 }
3456
3457 /*
3458 * Setting every sindex to -1
3459 */
3460 for (cv=0; cv<ntotvar; cv++) {
3461 var_set_sindex(vlist[cv],-1);
3462 }
3463 for (cr=0; cr<ntotrel; cr++) {
3464 rel_set_sindex(rlist[cr],-1);
3465 }
3466
3467 /*
3468 * Initializing values
3469 */
3470 for (cv=0; cv<ntotvar;cv++) {
3471 tmp_value[cv] = 0.0;
3472 }
3473 for (cv=0; cv<num_opt_eqns;cv++) {
3474 gradient->element[cv] = 0.0;
3475 }
3476
3477 for (cr=0; cr<nrel; cr++) {
3478 func_val[cr] = 0.0;
3479 multipliers->cols[subregion].element[cr] = 0.0;
3480 }
3481
3482 for (cv=0; cv<nvnb; cv++) {
3483 f_red_grad[cv] = 0.0;
3484 for (cr=0; cr<nrel; cr++) {
3485 rel_red_grad.cols[cv].element[cr] = 0.0;
3486 }
3487 }
3488
3489 for (cv=0; cv<nvar; cv++) {
3490 grad_obj[cv] = 0.0;
3491 }
3492
3493 /*
3494 * Calculate Values
3495 */
3496 vfilter.matchbits = (VAR_ACTIVE_AT_BND | VAR_INCIDENT
3497 | VAR_SVAR | VAR_FIXED);
3498 vfilter.matchvalue = (VAR_ACTIVE_AT_BND | VAR_INCIDENT | VAR_SVAR);
3499
3500 /*
3501 * List of relations
3502 */
3503 countrel = 0;
3504 countvar = 0;
3505 countnbv = 0;
3506 for (cr=0; cr<ntotrel; cr++) {
3507 rel = rlist[cr];
3508 if (rel_apply_filter(rel,&rfilter)) {
3509 rel_set_sindex(rel,countrel);
3510 coord.col = rel_sindex(rel);
3511 len = rel_n_incidences(rel);
3512 variables_master = ASC_NEW_ARRAY(int32,len);
3513 variables_solver = ASC_NEW_ARRAY(int32,len);
3514 derivatives = ASC_NEW_ARRAY(real64,len);
3515 relman_diff_grad(rel,&vfilter,derivatives,variables_master,
3516 variables_solver,&count,&resid,1);
3517 func_val[countrel] = resid;
3518 #if SHOW_LAGRANGE_DETAILS
3519 FPRINTF(ASCERR,"Equation = %d \n",coord.col);
3520 FPRINTF(ASCERR,"Residual = %f \n",resid);
3521 #endif /* SHOW_LAGRANGE_DETAILS */
3522 for (cv=0; cv<count;cv++) {
3523 var = vlist[variables_master[cv]];
3524 if (!var_nonbasic(var)) {
3525 tmp_value[variables_master[cv]] = tmp_value[variables_master[cv]] +
3526 derivatives[cv] * RHO * resid;
3527 if(var_active(var)) {
3528 coord.row = var_sindex(var);
3529 if (coord.row == -1) {
3530 var_set_sindex(var,countvar);
3531 coord.row = countvar;
3532 countvar++;
3533 }
3534 assert(coord.col >= 0 && coord.col < mtx_order(sys->lin_mtx));
3535 #if SHOW_LAGRANGE_DETAILS
3536 FPRINTF(ASCERR,"Coordinate row = %d \n",coord.row);
3537 FPRINTF(ASCERR,"Coordinate col = %d \n",coord.col);
3538 FPRINTF(ASCERR,"Derivative = %f \n",derivatives[cv]);
3539 #endif /* SHOW_LAGRANGE_DETAILS */
3540 mtx_fill_org_value(sys->lin_mtx,&coord,derivatives[cv]);
3541 }
3542 } else {
3543 if (var_sindex(var)== -1) {
3544 var_set_sindex(var,countnbv);
3545 countnbv++;
3546 }
3547 rel_red_grad.cols[var_sindex(var)].element[countrel] =
3548 derivatives[cv];
3549 #if SHOW_LAGRANGE_DETAILS
3550 FPRINTF(lif,"Nonbasic Variable ");
3551 print_var_name(lif,sys,var); PUTC('\n',lif);
3552 FPRINTF(ASCERR,"Derivative = %f \n",derivatives[cv]);
3553 #endif /* SHOW_LAGRANGE_DETAILS */
3554 }
3555 }
3556 destroy_array(variables_master);
3557 destroy_array(variables_solver);
3558 destroy_array(derivatives);
3559 countrel++;
3560 }
3561 }
3562
3563 /*
3564 * Objective function
3565 */
3566 rel = sys->obj;
3567 len = rel_n_incidences(rel);
3568 variables_master = ASC_NEW_ARRAY(int32,len);
3569 variables_solver = ASC_NEW_ARRAY(int32,len);
3570 derivatives = ASC_NEW_ARRAY(real64,len);
3571 relman_diff_grad(rel,&vfilter,derivatives,variables_master,
3572 variables_solver,&count,&resid,1);
3573 for (cv=0; cv<count;cv++) {
3574 var = vlist[variables_master[cv]];
3575 if (!var_nonbasic(var)) {
3576 #if SHOW_LAGRANGE_DETAILS
3577 FPRINTF(ASCERR,"Objective row = %d \n",var_sindex(var));
3578 FPRINTF(ASCERR,"Derivative = %f \n",derivatives[cv]);
3579 #endif /* SHOW_LAGRANGE_DETAILS */
3580 grad_obj[var_sindex(var)] = -1.0 * derivatives[cv];
3581 } else {
3582 #if SHOW_LAGRANGE_DETAILS
3583 FPRINTF(ASCERR,"Non Basic Variable = %d \n",var_sindex(var));
3584 FPRINTF(ASCERR,"Derivative in Objective = %f \n",derivatives[cv]);
3585 #endif /* SHOW_LAGRANGE_DETAILS */
3586 f_red_grad[var_sindex(var)] = derivatives[cv] ;
3587 }
3588 }
3589 destroy_array(variables_master);
3590 destroy_array(variables_solver);
3591 destroy_array(derivatives);
3592
3593 /*
3594 * Solving Linear System
3595 */
3596 get_multipliers(asys,subregion,nrel,grad_obj,multipliers);
3597
3598 countvar = 0;
3599 for (cv = 0; cv<ntotvar; cv++) {
3600