1 |
/* |
2 |
* SLV Utilities & Structures for ASCEND Solvers |
3 |
* by Ben Allan 1995 |
4 |
* SLV: Ascend Nonlinear Solver |
5 |
* by Karl Michael Westerberg |
6 |
* Created: 2/6/90 |
7 |
* Version: $Revision: 1.23 $ |
8 |
* Version control file: $RCSfile: slv_common.h,v $ |
9 |
* Date last modified: $Date: 1998/04/26 22:48:25 $ |
10 |
* Last modified by: $Author: ballan $ |
11 |
* |
12 |
* This file is part of the SLV solver. |
13 |
* |
14 |
* Copyright (C) 1995 Benjamin Allan 1995 |
15 |
* |
16 |
* The SLV solver is free software; you can redistribute |
17 |
* it and/or modify it under the terms of the GNU General Public License as |
18 |
* published by the Free Software Foundation; either version 2 of the |
19 |
* License, or (at your option) any later version. |
20 |
* |
21 |
* The SLV solver is distributed in hope that it will be |
22 |
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
23 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
24 |
* General Public License for more details. |
25 |
* |
26 |
* You should have received a copy of the GNU General Public License |
27 |
* along with the program; if not, write to the Free Software Foundation, |
28 |
* Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named |
29 |
* COPYING. COPYING is found in ../compiler. |
30 |
*/ |
31 |
|
32 |
/* |
33 |
* Contents: slv common utilities and definitions |
34 |
* |
35 |
* Authors: Ben Allan |
36 |
* based on the original slv.h by KW and JZ. |
37 |
* |
38 |
* Dates: 01/94 - original version |
39 |
* Description: |
40 |
* General C utility routines for slv/Slv class interfaces. Abstracted from |
41 |
* slvX.c January 1995. Ben Allan. |
42 |
* slv.h is the header for folks on the ASCEND end, and this is the one for |
43 |
* folks on the Slv math end. |
44 |
* Don't protoize this file for ASCEND types other than mtx, vec, and boolean |
45 |
* real64, and int32. |
46 |
* or we'll have you shot. In particular, not var and rel. People |
47 |
* who aren't supposed to know about var and rel include this. |
48 |
* |
49 |
* In particular, this header may be used without knowing about the ASCEND |
50 |
* compiler or any of its annoying insanities so long as you drag out |
51 |
* ascmalloc. |
52 |
* This does commit you to being able to stomach the mtx.h file, however, |
53 |
* even if you choose to ignore the contents of mtx. |
54 |
* Several functions, notably the print suite for rel/var names, |
55 |
* assume you are linking against something that does know about |
56 |
* ASCEND instances unless the SLV_INSTANCES flag is set to FALSE. |
57 |
* |
58 |
* The parameters and status struct definitions have been moved here, |
59 |
* being of general interest. |
60 |
* |
61 |
*/ |
62 |
#ifndef slv_common__already_included |
63 |
#define slv_common__already_included |
64 |
|
65 |
|
66 |
#undef SLV_INSTANCES |
67 |
#define SLV_INSTANCES TRUE |
68 |
/* SLV_INSTANCES should only be FALSE in a libasc.a free environment */ |
69 |
|
70 |
/* |
71 |
* Common data structures for Westerberg derived solvers. |
72 |
* |
73 |
*/ |
74 |
struct slv_output_data { |
75 |
FILE *more_important; /* NULL ==> no output */ |
76 |
FILE *less_important; /* NULL ==> no output */ |
77 |
}; |
78 |
/*KHACK THIS SHOULD BE REMOVED */ |
79 |
struct slv_tolerance_data { |
80 |
real64 drop; /* matrix entry drop tolerance during factorization */ |
81 |
real64 pivot; /* detect pivot too small, of those available */ |
82 |
real64 singular; /* detect matrix numerically singular */ |
83 |
real64 feasible; /* detect equality relations satisfied */ |
84 |
real64 rootfind; /* detect single equality relation satisfied */ |
85 |
real64 stationary; /* detect lagrange stationary */ |
86 |
real64 termination; /* detect progress diminished */ |
87 |
}; |
88 |
|
89 |
struct slv_sub_parameters { |
90 |
/* arrays of parametric data */ |
91 |
int32 *iap; |
92 |
real64 *rap; |
93 |
char* *cap; |
94 |
void* *vap; |
95 |
/* symbolic parameter names */ |
96 |
char* *ianames; |
97 |
char* *ranames; |
98 |
char* *canames; |
99 |
char* *vanames; |
100 |
/* longer explanations of the parameter data */ |
101 |
char* *iaexpln; |
102 |
char* *raexpln; |
103 |
char* *caexpln; |
104 |
char* *vaexpln; |
105 |
/* lengths of arrays above */ |
106 |
int32 ilen; /* len of iap,ianames, and iaexpln */ |
107 |
int32 rlen; /* likewise */ |
108 |
int32 clen; /* likewise */ |
109 |
int32 vlen; /* likewise */ |
110 |
}; |
111 |
|
112 |
struct slv_block_cost { |
113 |
int32 size,iterations,funcs,jacs,reorder_method; |
114 |
double time, resid, functime, jactime; |
115 |
}; |
116 |
|
117 |
/* |
118 |
* 3 New parameter structures |
119 |
*/ |
120 |
struct slv_int_parameter { |
121 |
int32 value; |
122 |
int32 low; |
123 |
int32 high; |
124 |
}; |
125 |
|
126 |
struct slv_boolean_parameter { |
127 |
int32 value; |
128 |
int32 low; |
129 |
int32 high; |
130 |
}; |
131 |
|
132 |
struct slv_real_parameter { |
133 |
double value; |
134 |
double low; |
135 |
double high; |
136 |
}; |
137 |
|
138 |
struct slv_char_parameter { |
139 |
char *value; |
140 |
char **argv; |
141 |
int32 high; |
142 |
}; |
143 |
|
144 |
enum parm_type { |
145 |
int_parm, |
146 |
bool_parm, |
147 |
real_parm, |
148 |
char_parm |
149 |
}; |
150 |
|
151 |
union parm_arg |
152 |
{ |
153 |
char **argv; |
154 |
char *argc; /* huh? */ |
155 |
int32 argi; |
156 |
int32 argb; |
157 |
real64 argr; |
158 |
}; |
159 |
|
160 |
struct slv_parameter { |
161 |
enum parm_type type; |
162 |
int32 number; /* index in array */ |
163 |
int32 display; /* display page */ |
164 |
char *name; /* scripting short name */ |
165 |
char *interface_label;/* user interface label */ |
166 |
char *description; /* modest help string */ |
167 |
union { /* data */ |
168 |
struct slv_int_parameter i; |
169 |
struct slv_int_parameter b; |
170 |
struct slv_real_parameter r; |
171 |
struct slv_char_parameter c; |
172 |
} info; |
173 |
}; |
174 |
|
175 |
/* |
176 |
* Macros for parm_arg unions. |
177 |
* Sets appropriate member (u) of the union to the |
178 |
* value specified (i) and returns (u). |
179 |
* (u) should be one of val, lo, or hi. |
180 |
* These macros are used in calls to the |
181 |
* slv_define_parm function defined below. |
182 |
*/ |
183 |
|
184 |
#define U_p_int(u,i) ((((u).argi = (i))), (u)) |
185 |
#define U_p_bool(u,i) ((((u).argb = (i))), (u)) |
186 |
#define U_p_real(u,i) ((((u).argr = (i))), (u)) |
187 |
#define U_p_string(u,i) ((((u).argc = (i))), (u)) |
188 |
#define U_p_strings(u,i) ((((u).argv = (i))), (u)) |
189 |
|
190 |
/* |
191 |
* Macros for defining macros of types integer (IPARM), |
192 |
* boolean (BPARM), real (RPARM), and character (CPARM). |
193 |
* To use, send in a name (X) for the macro (in caps by convention) |
194 |
* and a slv_parameters_t pointer (P). The name (X) should be |
195 |
* defined as an element in an array of void pointers in the |
196 |
* module in which the macro is to be used. This macro uses the |
197 |
* current number of registered parameters to link the array of |
198 |
* _VOID_ _POINTERS_ to the correct parameters. If you want to create |
199 |
* a macro for a parameter, you should put the appropriate macro |
200 |
* creating macro IMEDIATELY after the call to slv_define_parm |
201 |
* for that parameter. |
202 |
* Local int make_macros; must be defined. |
203 |
*/ |
204 |
#define SLV_IPARM_MACRO(X,P) \ |
205 |
if (make_macros == 1) { \ |
206 |
(X) = &((P)->parms[(P)->num_parms-1].info.i.value); \ |
207 |
} |
208 |
#define SLV_BPARM_MACRO(X,P) \ |
209 |
if (make_macros == 1) { \ |
210 |
(X) = &((P)->parms[(P)->num_parms-1].info.b.value); \ |
211 |
} |
212 |
#define SLV_RPARM_MACRO(X,P) \ |
213 |
if (make_macros == 1) { \ |
214 |
(X) = &((P)->parms[(P)->num_parms-1].info.r.value); \ |
215 |
} |
216 |
#define SLV_CPARM_MACRO(X,P) \ |
217 |
if (make_macros == 1) { \ |
218 |
(X) = &((P)->parms[(P)->num_parms-1].info.c.value); \ |
219 |
} |
220 |
|
221 |
/* |
222 |
* slv_parameters_structure: holds the array of parameters |
223 |
* and keeps a count of how many it contains. |
224 |
* Also holds various other information which should |
225 |
* be turned into slv_parameters or moved elsewhere |
226 |
*/ |
227 |
typedef struct slv_parameters_structure { |
228 |
struct slv_output_data output; |
229 |
struct slv_tolerance_data tolerance; |
230 |
struct slv_parameter *parms; |
231 |
int32 num_parms; |
232 |
int32 dynamic_parms; /* set 1 if parms is dynamically allocated */ |
233 |
|
234 |
/* we wish the following were on the way out */ |
235 |
struct slv_sub_parameters sp; |
236 |
int whose; |
237 |
int32 ignore_bounds; |
238 |
int32 partition; |
239 |
|
240 |
/* the following are on the way out */ |
241 |
double time_limit; /* kill */ |
242 |
double rho; /* kill */ |
243 |
int32 iteration_limit; /* kill */ |
244 |
int32 factor_option; /* kill */ |
245 |
|
246 |
} slv_parameters_t; |
247 |
|
248 |
/* |
249 |
* slv_destroy_parms(p): Function for deallocating memory |
250 |
* dynamically allocated durring parameter creation. |
251 |
* if !(p->dynamic_parms), frees strings in p->parms but not p->parms. |
252 |
*/ |
253 |
|
254 |
extern void slv_destroy_parms(slv_parameters_t *); |
255 |
|
256 |
/* |
257 |
* slv_define_parm: Function for adding (defining) a new |
258 |
* parameter in your parameter structure. |
259 |
* err = slv_define_parm(p,type,interface_name, |
260 |
* interface_label,description, |
261 |
* value, lower_bound,upper_bound, |
262 |
* page); |
263 |
* |
264 |
* int32 err |
265 |
* slv_parameters_t *p |
266 |
* enum parm_type type |
267 |
* char *interface_name |
268 |
* char *interface_label |
269 |
* char *description |
270 |
* union parm_arg value |
271 |
* union parm_arg lower_bound |
272 |
* union parm_arg upper_bound |
273 |
* int32 page |
274 |
* |
275 |
* Returns err = -1 if p is NULL or called with unsupported type. |
276 |
* Returns err = number of registered parameters otherwise. |
277 |
* Supported types are int_parm, bool_parm,real_parm, and char_parm. |
278 |
* interface name should be a very short but descriptive name that |
279 |
* the interface can use to identify the parameter. The interface label |
280 |
* should be a short text string to be displayed on the interface. |
281 |
* The description should be a slightly more detailed string to be |
282 |
* displayed upon request a la balloon help. |
283 |
* The value, lower_bound, and upper_bound fields should be filled |
284 |
* using the appropriate parm_arg union macros defined above. |
285 |
* page should indicate the parameter page number that the parameter |
286 |
* is to be displayed on. By convention page is set to -1 for parameters |
287 |
* which are not to be displayed on the interface. |
288 |
*/ |
289 |
extern int32 slv_define_parm(slv_parameters_t *, |
290 |
enum parm_type, |
291 |
char *, |
292 |
char *, |
293 |
char *, |
294 |
union parm_arg, |
295 |
union parm_arg, |
296 |
union parm_arg, |
297 |
int32); |
298 |
|
299 |
/* PARM VALUES |
300 |
* Resetting the value of a parameter can be done directly |
301 |
* except for string parameters which must be set with |
302 |
* slv_set_char_parameter(stringpointer,charvalue); |
303 |
* slv_set_char_parameter does not keep the charvalue string you pass it. |
304 |
*/ |
305 |
extern void slv_set_char_parameter(char **cptr, char *newvalue); |
306 |
|
307 |
/* |
308 |
* When used together the above structures, functions, and macros |
309 |
* allow us to define all of a solver's parameters in one file and |
310 |
* notify the interface of these parameters upon startup (dynamic |
311 |
* interface construction). The parameters can be defined in any order. |
312 |
* The only bookkeeping needed is associated with the macros. You must |
313 |
* have an array of void pointers large enough for all of the macros |
314 |
* you define and you must give each of the macros you define a unique |
315 |
* element of this array. Here is an example using a real parameter |
316 |
* and a character parameter. (The int and bool are similar to the real). |
317 |
* |
318 |
* ---------- START EXAMPLE CODE ---------- |
319 |
* |
320 |
* (* these 4 macros can be defined anywhere more or less so long as it |
321 |
* is before the calls to slv_define_parm. *) |
322 |
* #define REAL_PTR (sys->parm_array[0]) |
323 |
* #define REAL ((*(real64 *)REAL_PTR)) |
324 |
* #define CHAR_PTR (sys->parm_array[1]) |
325 |
* #define CHAR ((*(char **)CHAR_PTR)) |
326 |
* |
327 |
* #define PA_SIZE 2 |
328 |
* struct example { |
329 |
* struct slv_parameters_t p; |
330 |
* void *parm_array[PA_SIZE]; |
331 |
* struct slv_parameter padata[PA_SIZE]; |
332 |
* } e; |
333 |
* ... |
334 |
* e.p.parms = padata; |
335 |
* e.p.dynamic_parms = 0; |
336 |
* |
337 |
* static char *character_names[] = { |
338 |
* "name_one","name_two" |
339 |
* } |
340 |
* (* fill padata with appropriate info *) |
341 |
* slv_define_parm(&(e.p), real_parm, |
342 |
* "r_parm","real parameter" , |
343 |
* "this is an example of a real parameter" , |
344 |
* U_p_real(val,25),U_p_real(lo,0),U_p_real(hi,100),1); |
345 |
* (* now assign the element of e.parm_array from somewhere in padata *) |
346 |
* SLV_RPARM_MACRO(REAL_PTR,parameters); |
347 |
* |
348 |
* (* fill padata with appropriate info *) |
349 |
* slv_define_parm(&(e.p), char_parm, |
350 |
* "c_parm", "character parameter", |
351 |
* "this is an example of a character parameter", |
352 |
* U_p_string(val,character_names[0]), |
353 |
* U_p_strings(lo,character_names), |
354 |
* U_p_int(hi,sizeof(character_names)/sizeof(char *)),1); |
355 |
* (* now assign the element of e.parm_array that matches. *) |
356 |
* SLV_CPARM_MACRO(CHAR_PTR,parameters); |
357 |
* |
358 |
* Resetting the value of a parameter can be done directly |
359 |
* except for string parameters which should be set with, for example, |
360 |
* slv_set_char_parameter(CHAR_PTR,newvalue); |
361 |
* or outside a solver where there is no sys->parm_array: |
362 |
* slv_set_char_parameter(&(p.parms[i].info.c.value),argv[j]); |
363 |
* |
364 |
* ---------- END OF EXAMPLE CODE ---------- |
365 |
*/ |
366 |
|
367 |
/* |
368 |
* Every registered client should have a slv_parameters_t somewhere in it. |
369 |
* |
370 |
* The following is a list of parameters (those parameters that can be |
371 |
* modified during solve without calling slv_presolve are marked with |
372 |
* "$$$"). It should be noted that some solvers may not be conformable |
373 |
* to some of the parameters. Default values are subject to change via |
374 |
* experimentation. |
375 |
* |
376 |
* output.more_important (default stdout): $$$ |
377 |
* output.less_important (default NULL): $$$ |
378 |
* All output from the solver is written to one of these two files |
379 |
* (except bug messages which are written to stderr). Common values |
380 |
* are NULL (==> no file) and stdout. The more important messages |
381 |
* go to output.more_important and less important messages go to |
382 |
* output.less_important. To shut the solver up, set both files to |
383 |
* NULL. |
384 |
* |
385 |
* tolerance.drop (default 1e-16): |
386 |
* tolerance.pivot (default 0.1): |
387 |
* tolerance.singular (default 1e-12): |
388 |
* tolerance.feasible (default 1e-8): |
389 |
* tolerance.rootfind (default 1e-12): |
390 |
* tolerance.stationary (default 1e-8): |
391 |
* tolerance.termination (default 1e-12): |
392 |
* These define the criterion for selecting pivotable relations, |
393 |
* whether the equations are satisfied, if a local minimum has been |
394 |
* found, or if no further reduction in the augmented lagrange merit |
395 |
* phi can be achieved. |
396 |
* - During jacobian reduction, each equation pivot selected must be |
397 |
* at least a certain fraction given by TOLERANCE.PIVOT of the largest |
398 |
* available. |
399 |
* Also, the largest value in the row must exceed TOLERANCE.SINGULAR |
400 |
* in order to be considered independent. |
401 |
* - The absolute value of each unscaled equation residual is compared |
402 |
* with TOLERANCE.FEASIBLE in order to determine convergence of the |
403 |
* equality constraints during Newton iteration. |
404 |
* - The absolute value of each unscaled equation residual is compared |
405 |
* with TOLERANCE.ROOTFIND in order to determine convergence of the |
406 |
* constraint during rootfinding of single equations. |
407 |
* - Detection of a minimum requires the stationary condition of the |
408 |
* lagrange to be less than TOLERANCE.STATIONARY. |
409 |
* - If the directional derivative of phi along the negative gradient |
410 |
* direction using the suggested iteration step length falls below |
411 |
* TOLERANCE.TERMINATION, iteration is ceased. |
412 |
* - TOLERANCE.DROP is the smallest number magnitude to be allowed |
413 |
* in the Jacobian matrix during factorization. Default is optimistic. |
414 |
* |
415 |
* time_limit (default 30.0): $$$ |
416 |
* This defines the time limit expressed as cpu seconds per block. |
417 |
* If the solver requires more time than this in any given block, |
418 |
* then it will stop. |
419 |
* |
420 |
* iteration_limit (default 100): $$$ |
421 |
* This defines the maximum number of iterations attempted in a given |
422 |
* block. The solver will stop after this many iterations if it fails |
423 |
* to converge. |
424 |
* |
425 |
* factor_option (default 0): |
426 |
* This sets the number of the linear factorization to suggest. |
427 |
* This does not map directly to linsol numbering of any sort. |
428 |
* The map is: 0 <==> RANKI, 1 <==> RANKI_JZ, 2+ <==> ?. |
429 |
* The solver is free to ignore this suggestion. |
430 |
* In fact, the specific solver is free to define the meaning of factor |
431 |
* option depending on what linear packages it can talk to. |
432 |
* |
433 |
* partition (default TRUE): |
434 |
* Specifies whether or not the system will be partitioned into blocks |
435 |
* or not. If not, then the system will be considered as one large |
436 |
* block. |
437 |
* |
438 |
* ignore_bounds (default FALSE): |
439 |
* Specifies whether or not bounds will be considered during solving. |
440 |
* WARNING: if this flag is set, there will be no guarantees that the |
441 |
* solution will lie in bounds. Suggested use might be to set this |
442 |
* flag to TRUE, solve, reset this flag to FALSE, and resolve. |
443 |
* More often than not, in fact, ignore bounds will lead to floating |
444 |
* point exceptions, halting the solution process. |
445 |
* |
446 |
* rho (default 1.0): |
447 |
* Used as a scalar pre-multiplier of the penalty term quantified by one |
448 |
* half the two norm of the equality constraint residuals in an |
449 |
* augmented lagrange merit function. |
450 |
* |
451 |
* sp.ia/ra/ca/vap (defaults NULL, READ ONLY): |
452 |
* Is a set of pointers to arrays (int/double/(char*)/void*). |
453 |
* The values of the pointers themselves should not be modified, |
454 |
* though the values pointed at may be modified. Note that this is |
455 |
* _direct_ modification and will take effect immediately, not on |
456 |
* the next call to slv_set_parameters. When the engine gets around |
457 |
* to looking at the values in these arrays is engine dependent. |
458 |
* NULL is the expected value for some or all of these array |
459 |
* pointers, depending on the engine. The sizes of these arrays are |
460 |
* specific to each solver's interface. As being of interest (at |
461 |
* compile time) to both the slvI.c file and the GUI/CLUI, the |
462 |
* sizes of the arrays to be pointed to are part of the slvI.h file. |
463 |
* The implementor of each slvI.c should take care to use as much of |
464 |
* the slv_parameters_t as possible before passing data through the |
465 |
* arrays provided in the sub_parameters. This will make for a |
466 |
* minimal amount of work when adding an engine to the GUI/CLUI. |
467 |
* To further aid reusability/sanity preservation, slvI.h should |
468 |
* be appended with proper defines for subscripting these arrays. |
469 |
* |
470 |
* sp.i/r/c/vlen (defaults 0, READ ONLY) |
471 |
* lengths of the sub_parameter arrays. |
472 |
* |
473 |
* sp.ia/ra/ca/vanames (defaults NULL, READONLY) |
474 |
* symbolic names for the corresponding entries in ia/ra/ca/vap. |
475 |
* |
476 |
* sp.ia/ra/ca/vaexpln (defaults NULL, READONLY) |
477 |
* longer explanations for the corresponding entries in ia/ra/ca/vap. |
478 |
* |
479 |
* whose (default 0=>slv0, READ ONLY) |
480 |
* This tells where a parameter set came from, since the default |
481 |
* action of slv_get_parameters is to return a copy of slv0's |
482 |
* parameters if the parameters asked for don't exist because |
483 |
* the solver in question wasn't built/linked. |
484 |
*/ |
485 |
|
486 |
struct slv__block_status_structure { |
487 |
int32 number_of; |
488 |
int32 current_block; |
489 |
int32 current_reordered_block; |
490 |
int32 current_size; |
491 |
int32 previous_total_size; |
492 |
int32 previous_total_size_vars; |
493 |
int32 iteration; |
494 |
int32 funcs; |
495 |
int32 jacs; |
496 |
double cpu_elapsed; |
497 |
double functime; |
498 |
double jactime; |
499 |
real64 residual; |
500 |
}; |
501 |
|
502 |
typedef struct slv_status_structure { |
503 |
uint32 ok : 1; |
504 |
uint32 over_defined : 1; |
505 |
uint32 under_defined : 1; |
506 |
uint32 struct_singular : 1; |
507 |
uint32 ready_to_solve : 1; |
508 |
uint32 converged : 1; |
509 |
uint32 diverged : 1; |
510 |
uint32 inconsistent : 1; |
511 |
uint32 calc_ok : 1; |
512 |
uint32 iteration_limit_exceeded : 1; |
513 |
uint32 time_limit_exceeded : 1; |
514 |
uint32 panic :1; |
515 |
int32 iteration; |
516 |
int32 costsize; |
517 |
double cpu_elapsed; |
518 |
struct slv_block_cost *cost; |
519 |
struct slv__block_status_structure block; |
520 |
} slv_status_t; |
521 |
|
522 |
/* |
523 |
* The following is a list of statuses and their meanings. Statuses |
524 |
* cannot be written to, and thus there is no notion of default value. |
525 |
* |
526 |
* ok: |
527 |
* Specifies whether or not everything is "ok". It is a shorthand for |
528 |
* testing all of the other flags. |
529 |
* |
530 |
* over_defined: |
531 |
* under_defined: |
532 |
* struct_singular: |
533 |
* Specifies whether the system is over-defined, under-defined, or |
534 |
* structurally singular. These fields are set by slv_presolve where |
535 |
* the structural analysis is performed. It should be noted that |
536 |
* over_defined and under_defined are mutually exclusive and both |
537 |
* imply struct_singular, although a system can be structurally |
538 |
* singular without being over-defined or under-defined. |
539 |
* |
540 |
* ready_to_solve: |
541 |
* Specifies whether the system is ready to solve. In other words, is |
542 |
* slv_iterate or slv_solve legal? This flag is FALSE before |
543 |
* slv_presolve or after the system has converged or the solver has |
544 |
* given up for whatever reason. |
545 |
* |
546 |
* converged: |
547 |
* This flag is set whenever the entire system has converged. The |
548 |
* convergence will be genuine (all relations satisfied within |
549 |
* tolerance, all bounds satisfied, all calculations defined, etc.). |
550 |
* |
551 |
* diverged: |
552 |
* This flag is set whenever the solver has truly given up (i.e. given |
553 |
* up for any reason not covered below). |
554 |
* |
555 |
* inconsistent: |
556 |
* The solver has concluded unambiguously (e.g. by symbolic |
557 |
* manipulation) that the system is inconsistent. |
558 |
* |
559 |
* calc_ok: |
560 |
* Specifies whether or not there were any calculation errors in |
561 |
* computing the residuals at the current point. |
562 |
* |
563 |
* iteration_limit_exceeded: |
564 |
* Specifies whether or not the iteration count was exceeded or not. |
565 |
* |
566 |
* time_limit_exceeded: |
567 |
* Specifies whether or not the cpu time limit was exceeded. |
568 |
* |
569 |
* panic: |
570 |
* Specifies whether or not the user called a halt interactively; |
571 |
* |
572 |
* iteration: |
573 |
* Total number of iterations so far. Total iteration count is reset to |
574 |
* zero whenever slv_presolve or slv_resolve is called. |
575 |
* |
576 |
* cpu_elapsed: |
577 |
* Total number of cpu seconds elapsed. Total cpu time elapsed is reset |
578 |
* to zero whenever slv_presolve or slv_resolve is called. |
579 |
* |
580 |
* block.number_of: |
581 |
* Number of blocks in system. |
582 |
* |
583 |
* block.current_block: |
584 |
* Block number of the current block that the solver is working on. |
585 |
* It is assumed that all previous blocks have already converged. |
586 |
* |
587 |
* block.current_size: |
588 |
* Number of variables/relations in the current block. |
589 |
* |
590 |
* block.previous_total_size: |
591 |
* Total size of previous blocks (= number of variables/relations |
592 |
* already converged). |
593 |
* |
594 |
* block.iteration: |
595 |
* Number of iterations so far in the current block. |
596 |
* |
597 |
* block.functime: |
598 |
* Number of cpu seconds elapsed getting residuals from whereever. |
599 |
* |
600 |
* block.jactime: |
601 |
* Number of cpu seconds elapsed getting jacobians from whereever. |
602 |
* |
603 |
* block.cpu_elapsed: |
604 |
* Number of cpu seconds elapsed so far in the current block. |
605 |
* |
606 |
* block.residual: |
607 |
* Current residual (RMS value) for the current block. |
608 |
* |
609 |
* cost (READ ONLY) |
610 |
* This is a pointer to first of an array which is costsize long of |
611 |
* slv_block_cost structures. This is to collect data for the |
612 |
* comparison of algorithms. All solvers should have at least |
613 |
* one of these, though the interface will check for null before |
614 |
* reading the data. The block_cost structure contains: |
615 |
* size (how big is the block, in terms of variables) |
616 |
* iterations (how many iterations to convergence/divergence) |
617 |
* funcs (how many function evaluations were made?) |
618 |
* jacs (how many jacobian evaluations were made?) |
619 |
* time (how much cpu total time elapsed while in the block?) |
620 |
* functime (time spent in function evaluations) |
621 |
* jactime (time spent in jacobian evaluations, stuffing) |
622 |
* (for those codes where a function evaluation is |
623 |
* a byproduct of gradient evaluation, the func cost |
624 |
* will be billed here.) |
625 |
* The interpretation of these data are somewhat up to the coder. |
626 |
* |
627 |
* costsize |
628 |
* This is how big the cost array is. It should in general be the |
629 |
* number of blocks in the system plus 1 so that all the unincluded |
630 |
* relations can be billed to the blocks+1th cost if they are |
631 |
* evaluated. |
632 |
* |
633 |
*/ |
634 |
|
635 |
/* |
636 |
* a dense vector class of some utility and the functions for it. |
637 |
*/ |
638 |
struct vector_data { |
639 |
real64 norm2; /* 2-norm of vector squared */ |
640 |
mtx_range_t *rng; /* Pointer to range */ |
641 |
real64 *vec; /* NULL => uninitialized */ |
642 |
boolean accurate; /* ? is vector currently accurate */ |
643 |
}; |
644 |
|
645 |
/* |
646 |
* vector_data operations. Copyvector, innerproduct, and squarenorm |
647 |
* could stand to be optimized. mtx_product needs attention: does it |
648 |
* go into mtx? |
649 |
* |
650 |
* slv_zero_vector(struct vector_data *vec); |
651 |
* Assign vector entries between vec->rng.low and vec->rng.high to 0.0. |
652 |
* |
653 |
* slv_copy_vector(struct vector_data *vec1,struct vector_data *vec2); |
654 |
* Copy data [vec1->rng.low .. vec1->rng.high] to vec2 starting |
655 |
* at position vec2->rng.low. |
656 |
* |
657 |
* slv_inner_product(struct vector_data *vec1,struct vector_data *vec2); |
658 |
* Dot [vec1->rng.low .. vec1->rng.high] with vec2 starting at |
659 |
* position vec2->rng.low. |
660 |
* |
661 |
* slv_square_norm(struct vector_data *vec); |
662 |
* Dot [vec->rng.low .. vec->rng.high] with itself and store the |
663 |
* result in vec->norm2. |
664 |
* |
665 |
* slv_matrix_product(mtx,vec,prod,scale,transpose) |
666 |
* mtx_matrix_t mtx; |
667 |
* struct vector_data *vec,*prod; |
668 |
* real64 scale; |
669 |
* boolean transpose; |
670 |
* |
671 |
* Stores prod := (scale)*(mtx)(vec) or (scale)*(mtx-transpose)(vec). |
672 |
* vec and prod must be completely different. |
673 |
* If (!transpose) vec->vec is assumed indexed by current col and |
674 |
* prod->vec is indexed by current row of mtx. |
675 |
* If (transpose) vec->vec is assumed indexed by current row and |
676 |
* prod->vec is indexed by current col of mtx. |
677 |
* |
678 |
* slv_write_vector(file,vec) |
679 |
* Write the values in the range of the vector to file fp along with |
680 |
* a few other doodads. |
681 |
* |
682 |
* If we get brave, we will consider replacing the cores of these |
683 |
* routines with blas calls. We aren't just overeager to go mixed |
684 |
* language call nuts yet, however. |
685 |
*/ |
686 |
extern void slv_zero_vector(struct vector_data *); |
687 |
extern void slv_copy_vector(struct vector_data *,struct vector_data *); |
688 |
extern real64 slv_inner_product(struct vector_data *, |
689 |
struct vector_data *); |
690 |
extern real64 slv_square_norm(struct vector_data *); |
691 |
extern void slv_matrix_product(mtx_matrix_t, struct vector_data *, |
692 |
struct vector_data *, real64, boolean); |
693 |
void slv_write_vector(FILE *, struct vector_data *); |
694 |
|
695 |
/* |
696 |
* Misc. BLAS-like functions. |
697 |
*/ |
698 |
/* |
699 |
* sum=slv_dot(len, a1, a2); |
700 |
* Dot product of 2 arrays of real64. Loop unrolled. |
701 |
* Takes advantage of identical vectors. |
702 |
* real64 *a1, *a2, sum; |
703 |
* int32 len; |
704 |
* |
705 |
* Used inside slv_inner_product, so no need to use specially |
706 |
* if you are using the vector_data type. |
707 |
*/ |
708 |
real64 slv_dot(int32, const real64 *, const real64 *); |
709 |
|
710 |
/* |
711 |
* General input/output routines |
712 |
* ----------------------------- |
713 |
*/ |
714 |
|
715 |
/* |
716 |
* FILE pointer macros. |
717 |
* fp = MIF(sys) |
718 |
* fp = LIF(sys) |
719 |
* fp = PMIF(sys) |
720 |
* fp = PLIF(sys) |
721 |
* or fprintf(MIF(sys),"stuff",data...); |
722 |
* Use of these is requested on grounds of readability but not required. |
723 |
* MIF and LIF are macros, which means any specific solver interface |
724 |
* to ASCEND can use them, since all interfaces are supposed to |
725 |
* support a parameters structure p somewhere in a larger system |
726 |
* structure (sys) they keep privately. |
727 |
* Use the PMIF or PLIF flavors if the parameters sys->p is a pointer |
728 |
* rather than a in-struct member. |
729 |
* |
730 |
* slv_get_output_file(fp) takes a file pointer, and if it is null |
731 |
* returns a pointer to /dev/null. |
732 |
* If you are in environment that doesn't have something like |
733 |
* /dev/null, you'd better be damn sure your sys->p.output.*_important |
734 |
* is not NULL. |
735 |
*/ |
736 |
extern FILE *slv_get_output_file(); |
737 |
#define MIF(sys) slv_get_output_file( (sys)->p.output.more_important ) |
738 |
#define LIF(sys) slv_get_output_file( (sys)->p.output.less_important ) |
739 |
#define PMIF(sys) slv_get_output_file( (sys)->p->output.more_important ) |
740 |
#define PLIF(sys) slv_get_output_file( (sys)->p->output.less_important ) |
741 |
|
742 |
/*------------------- begin compiler dependent functions -------------------*/ |
743 |
#if SLV_INSTANCES |
744 |
/* |
745 |
* void slv_print_obj_name(outfile,obj) [1/95: not yet implemented] |
746 |
* void slv_print_rel_name(outfile,sys,rel) |
747 |
* void slv_print_var_name(outfile,sys,var) |
748 |
* void slv_print_logrel_name(outfile,sys,lrel) |
749 |
* void slv_print_dis_name(outfile,sys,dvar) |
750 |
* |
751 |
* Prints appropriate name. If name can't be found by |
752 |
* *_make_name(*), the global index is printed by |
753 |
* default. |
754 |
* |
755 |
* void slv_print_obj_index(outfile,obj)[1/95: not yet implemented] |
756 |
* void slv_print_rel_sindex(outfile,rel)[1/95: not yet implemented] |
757 |
* void slv_print_var_sindex(outfile,var)[1/95: not yet implemented] |
758 |
* void slv_print_logrel_sindex(outfile,lrel)[1/95: not yet implemented] |
759 |
* void slv_print_dis_sindex(outfile,dvar)[1/95: not yet implemented] |
760 |
* |
761 |
* To print the local index of a ***, call slv_print_***_index(); |
762 |
* |
763 |
* FILE *outfile; |
764 |
* obj_objective_t obj; |
765 |
* struct rel_relation *rel; |
766 |
* struct var_variable *var; |
767 |
* struct logrel_relation *lrel; |
768 |
* struct dis_discrete *dvar; |
769 |
* slv_system_t sys; |
770 |
* |
771 |
*/ |
772 |
extern void slv_print_obj_name(); |
773 |
extern void slv_print_rel_name(FILE *,slv_system_t,struct rel_relation *); |
774 |
extern void slv_print_var_name(FILE *,slv_system_t,struct var_variable *); |
775 |
extern void slv_print_logrel_name(FILE *,slv_system_t, |
776 |
struct logrel_relation *); |
777 |
extern void slv_print_dis_name(FILE *,slv_system_t,struct dis_discrete *); |
778 |
|
779 |
extern void slv_print_obj_index(); |
780 |
extern void slv_print_rel_sindex(FILE *,struct rel_relation *); |
781 |
extern void slv_print_var_sindex(FILE *,struct var_variable *); |
782 |
extern void slv_print_logrel_sindex(FILE *,struct logrel_relation *); |
783 |
extern void slv_print_dis_sindex(FILE *,struct dis_discrete *); |
784 |
|
785 |
/* |
786 |
* int slv_direct_solve(server,rel,var,file,epsilon,ignore_bounds,scaled) |
787 |
* struct rel_relation *rel; |
788 |
* struct var_variable *var; |
789 |
* boolean ignore_bounds; |
790 |
* real64 epsilon; |
791 |
* |
792 |
* Attempt to directly solve the given relation (equality constraint) for |
793 |
* the given variable, leaving the others fixed. Returns an integer |
794 |
* signifying the status as one of the following three: |
795 |
* |
796 |
* 0 ==> Unable to determine anything. |
797 |
* Not symbolically invertible. |
798 |
* 1 ==> Solution(s) found. |
799 |
* Variable value set to first found if more than one. |
800 |
* -1 ==> No solution found. |
801 |
* Function invertible, but no solution exists satisfying |
802 |
* var bounds (if active) and the epsilon given. |
803 |
* |
804 |
* The variable bounds will be upheld, unless ignore_bounds=FALSE. |
805 |
* Residual testing will be against epsilon and either scaled or |
806 |
* unscaled residual according to scaled (no scale <- 0).. |
807 |
* If file != NULL and there are leftover possible solutions, we |
808 |
* will write about them to file. |
809 |
*/ |
810 |
extern int slv_direct_solve(slv_system_t, struct rel_relation *, |
811 |
struct var_variable *, FILE *, real64, int, int); |
812 |
|
813 |
/* |
814 |
* int slv_direct_log_solve(server,lrel,dvar,file,perturb,insts) |
815 |
* struct logrel_relation *lrel; |
816 |
* struct dis_discrete *dvar; |
817 |
* |
818 |
* Attempt to directly solve the given logrelation for the given |
819 |
* discrete variable, leaving the others fixed. Returns an integer |
820 |
* signifying the status as one of the following three: |
821 |
* |
822 |
* 0 ==> Unable to determine anything. Bad logrelation or dvar |
823 |
* 1 ==> Solution found. |
824 |
* 2 ==> More than one solution found. It does not modify the value |
825 |
* of dvar. Conflicting. |
826 |
* -1 ==> No solution found. Inconsistency |
827 |
* |
828 |
* If file != NULL and there are leftover possible solutions, we |
829 |
* will write about them to file. |
830 |
* The flag perturb and the gl_list are used to change the truth |
831 |
* value of some boundaries. This is sometimes useful in |
832 |
* conditional modeling. |
833 |
*/ |
834 |
extern int slv_direct_log_solve(slv_system_t, struct logrel_relation *, |
835 |
struct dis_discrete *, FILE *, int, |
836 |
struct gl_list_t *); |
837 |
|
838 |
#endif |
839 |
/*-------------------- END compiler dependent functions --------------------*/ |
840 |
|
841 |
/* |
842 |
* lnkmap functions: |
843 |
* slv_create_lnkmap(int32 m,int32 n,int32 hl,int32 *hi,int32 *hj) |
844 |
* slv_destroy_lnkmap(int32 **map) |
845 |
* slv_write_lnkmap(FILE *fp, int32 m, int32 **map) |
846 |
* slv_lnkmap_from_mtx(mtx_matrix_t mtx, int32 hl, int32 m) |
847 |
* |
848 |
* These create an odd compressed row mapping, given the hi and hj |
849 |
* subscript vectors. The primary utility of the lnkmap is that |
850 |
* it can be traversed rapidly when one wants to conditionally map a row of |
851 |
* a Harwell style (arbitrarily ordered) link representation |
852 |
* back into another representation where adding elements to a row |
853 |
* is easily done. |
854 |
* The actual format of the lnkmap is described in slv_create_lnkmap. |
855 |
* |
856 |
*/ |
857 |
|
858 |
/* |
859 |
* map=slv_create_lnkmap(m,n,hl,hi,hj); |
860 |
* map=slv_lnkmap_from_mtx(mtx,len,m) |
861 |
* int32 order, hl; |
862 |
* int32 *hi, *hj; |
863 |
* int32 **map; |
864 |
* m: the number of rows expected. the map returned will be this long. |
865 |
* n: the number of columns expected. |
866 |
* where rowindex and colindex refer to the data in hi,hj. |
867 |
* hl= length of hi and hj, or the number of nonzeros in mtx; |
868 |
* hi: the eqn indices of a C numbered sparse matrix list; |
869 |
* hj: the var indices of a C numbered sparse matrix list; |
870 |
* hi and hj should specify a unique incidence pattern, that is no |
871 |
* duplicate elements are allowed. |
872 |
* Empty rows and columns are allowed in the matrix. |
873 |
* |
874 |
* Builds a row biased mapping array from the hi,hj lists given. |
875 |
* The map returned has the following format: |
876 |
* map[i] is a vector describing the incidence in row i of the matrix. |
877 |
* Let vars=map[i], where vars is int32 *. |
878 |
* vars[0]=number of incidences in the relation. |
879 |
* For all 0<=k<vars[0] |
880 |
* vars[2*k+1]= original column index of some var in the eqn. |
881 |
* vars[2*k+2]= the lnk list index of element(i,vars[2*k+1]) |
882 |
* |
883 |
* The map should only be deallocated by destroy_lnkmap(map). |
884 |
* The memory allocation for a lnkmap is done efficiently. |
885 |
* destroy_lnkmap and write_lnkmap will tolerate NULL maps |
886 |
* as input. |
887 |
* Maps may be printed with |
888 |
* slv_write_lnkmap(fp,m,map); |
889 |
* FILE *fp, int32 m (same as was created), int32 **map |
890 |
*/ |
891 |
extern int32 **slv_create_lnkmap(int32,int32,int32,int32 *,int32 *); |
892 |
extern int32 **slv_lnkmap_from_mtx(mtx_matrix_t , int32 , int32 ); |
893 |
extern void slv_destroy_lnkmap(int32 **); |
894 |
extern void slv_write_lnkmap(FILE *, int,int32 **); |
895 |
|
896 |
#endif |