1 |
/* ASCEND modelling environment |
2 |
Copyright (C) 2006 Carnegie Mellon University |
3 |
Copyright (C) 1994 Joseph Zaher, Benjamin Andrew Allan |
4 |
Copyright (C) 1993 Joseph Zaher |
5 |
Copyright (C) 1990 Karl Michael Westerberg |
6 |
|
7 |
This program is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2, or (at your option) |
10 |
any later version. |
11 |
|
12 |
This program is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
16 |
|
17 |
You should have received a copy of the GNU General Public License |
18 |
along with this program; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place - Suite 330, |
20 |
Boston, MA 02111-1307, USA. |
21 |
*//** @file |
22 |
Relation manipulator module for the SLV solver. |
23 |
|
24 |
This module will provide supplemental operations for |
25 |
relations such as simplification, evaluation, and |
26 |
differentiation. |
27 |
|
28 |
Dates: 06/90 - original version |
29 |
06/93 - separated out exprman |
30 |
11/93 - added relman_calc_satisfied |
31 |
|
32 |
*//* |
33 |
by Karl Michael Westerberg and Joseph Zaher, 2/6/90 |
34 |
Last in CVS: $Revision: 1.29 $ $Date: 1998/04/23 23:56:24 $ $Author: ballan $ |
35 |
*/ |
36 |
|
37 |
#ifndef ASC_RELMAN_H |
38 |
#define ASC_RELMAN_H |
39 |
|
40 |
#include <ascend/general/platform.h> |
41 |
|
42 |
#include <ascend/linear/mtx.h> |
43 |
#include <ascend/general/ltmatrix.h> |
44 |
|
45 |
#include "var.h" |
46 |
#include "rel.h" |
47 |
|
48 |
/** @addtogroup solver Solver |
49 |
@{ |
50 |
*/ |
51 |
|
52 |
#define relman_is_linear(a,b) (FALSE) |
53 |
/**< |
54 |
* Determines whether or not the given relation is linear in |
55 |
* all of the variables which pass through the variable filter, treating |
56 |
* those variables which fail to pass as constants.<br><br> |
57 |
* |
58 |
* Example: |
59 |
* x1 + x2 >= 3 is a linear relation. |
60 |
*/ |
61 |
|
62 |
extern real64 relman_linear_coef(struct rel_relation *rel, |
63 |
struct var_variable *var, |
64 |
var_filter_t *filter); |
65 |
/**< |
66 |
* Computes the coefficient of the given variable in a linear |
67 |
* relation. If var=NULL, then the "RHS" is returned instead. More |
68 |
* nprecisely, "a[var]" is returned where:<br><br> |
69 |
* |
70 |
* rel : sum[variables v](a[v] * v) COMPARISON a[NULL]<br><br> |
71 |
* |
72 |
* It is assumed that the relation is linear, otherwise, |
73 |
* something will be returned, but it won't be very meaningful. |
74 |
*/ |
75 |
|
76 |
#if 0 |
77 |
extern void relman_simplify(struct rel_relation *rel, int opt_level); |
78 |
/**< NOT IMPLEMENTED |
79 |
* The left and right hand sides of the given relation are simplified |
80 |
* to the extent given by opt_level. The effect of varying values of |
81 |
* opt_level is given in the description for exprman_simplify(). |
82 |
*/ |
83 |
|
84 |
extern void relman_dissolve_vars(struct rel_relation *rel, var_filter_t *filter); |
85 |
/**< NOT IMPLEMENTED |
86 |
* Variables which pass through the filter are replaced in the |
87 |
* relation by their current values. |
88 |
*/ |
89 |
#endif |
90 |
|
91 |
extern void relman_decide_incidence(struct rel_relation *rel); |
92 |
/**< |
93 |
* Sets the incidence field of each variable which is found to be |
94 |
* incident in the relation rel to TRUE. If these variables make |
95 |
* up a subset of some larger variable list, it is important to first |
96 |
* set the incidence field of all of the variables to FALSE before |
97 |
* using this function in order to determine the unattached variables. |
98 |
*/ |
99 |
|
100 |
extern void relman_get_incidence(struct rel_relation *rel, |
101 |
var_filter_t *filter, |
102 |
mtx_matrix_t matrix); |
103 |
/**< |
104 |
* Upon return, coefficient (rel_n,var_n) (using original row and column |
105 |
* numbers) is non-zero if and only if the relation rel with index rel_n |
106 |
* depends on a variable with index var_n. |
107 |
*/ |
108 |
|
109 |
ASC_DLLSPEC real64 relman_eval(struct rel_relation *rel, int32 *calc_okp, int safe); |
110 |
/**< |
111 |
The residual of the relation is calculated and returned. In addition |
112 |
to returning the residual, the residual field of the relation is |
113 |
updated. The residual field of the relation is not updated when an error |
114 |
occurs. |
115 |
|
116 |
@param safe If set nonzero, "safe" functions are used for evaluation (means |
117 |
that overflows, divide by zero, etc are avoided) |
118 |
@param calc_ok (returned) status of the calculation. 0=error, else ok. |
119 |
@return residual (= LHS - RHS, regardless of comparison) |
120 |
|
121 |
@NOTE |
122 |
This function should be surrounded by Asc_SignalHandlerPush/Pop both |
123 |
with arguments (SIGFPE,SIG_IGN). If it is being called in a loop, |
124 |
the push/pop should be _outside_ the loop. |
125 |
*/ |
126 |
|
127 |
ASC_DLLSPEC int32 relman_obj_direction(struct rel_relation *rel); |
128 |
/**< |
129 |
* Returns: |
130 |
* - direction = -1 if objective is minimization |
131 |
* - direction = 1 if objective is maximization |
132 |
* - direction = 0 otherwise. (ie. if not an objective) |
133 |
*/ |
134 |
|
135 |
ASC_DLLSPEC real64 relman_scale(struct rel_relation *rel); |
136 |
/**< |
137 |
* Calculates relation nominal scaling factor for |
138 |
* current values stored in the relations variables. |
139 |
* Fills the relations nominal field and also returns |
140 |
* the relations nominal. |
141 |
*/ |
142 |
|
143 |
#define relman_diff(a,b,c,d) (abort(),1) |
144 |
/**< |
145 |
Calculates the derivative of the relation residual with respect to |
146 |
the specified variable and stuffs it in pd. if problem with |
147 |
calculation, returns 1, else 0. |
148 |
If the value of safe is nonzero, "safe" functions will be used to |
149 |
calculate the residual. |
150 |
|
151 |
@TODO relman_diff() needs to be reimplemented - needs compiler-side work. |
152 |
*/ |
153 |
|
154 |
|
155 |
ASC_DLLSPEC int relman_diff2(struct rel_relation *rel, |
156 |
const var_filter_t *filter, |
157 |
real64 *derivatives, |
158 |
int32 *variables, |
159 |
int32 *count, |
160 |
int32 safe); |
161 |
/**< |
162 |
Calculates the row of the jacobian matrix (the transpose gradient of |
163 |
the relation residual, \f$ \grad^{T}(f) \f$) corresponding to the relation |
164 |
rel. The filter determines which variables actually contribute to the |
165 |
jacobian. |
166 |
|
167 |
derivatives[i] will contain the derivative of the relation with |
168 |
respect to the variable whose solver index is stored in |
169 |
variables[i]. |
170 |
|
171 |
@param rel Relation being differentiated |
172 |
@param filter Filter for variables for which derivs are desired |
173 |
@param safe If nonzero, "safe" functions are used to for the calculations |
174 |
@param derivatives output vector (allocated by the calling function) |
175 |
@param variables output vector (allocated by the calling function) |
176 |
@param count output value, will be set to the number of elements assigned upon exit. |
177 |
|
178 |
@return 0 on success, non-zero if an error is encountered in the calculation |
179 |
*/ |
180 |
|
181 |
|
182 |
/* return 0 on success (derivatives, variables and count are output vars too) */ |
183 |
ASC_DLLSPEC int relman_diff2_rev(struct rel_relation *rel, |
184 |
const var_filter_t *filter, |
185 |
real64 *derivatives, |
186 |
int32 *variables, |
187 |
int32 *count, int32 safe); |
188 |
|
189 |
/**< |
190 |
similar to relman_diff2, but uses revers Automatic differentiation to obtain derivatives |
191 |
*/ |
192 |
|
193 |
ASC_DLLSPEC int relman_hess(struct rel_relation *rel, |
194 |
const var_filter_t *filter, |
195 |
hessian_mtx *hess_matrix, |
196 |
int32 *count, |
197 |
unsigned long max_dimension, |
198 |
int32 safe); |
199 |
/**< |
200 |
Hessian Matrix Evaluation, |
201 |
@param rel is the relation whose Hessian Matrix is desired |
202 |
@param filter is the variable filter |
203 |
@param hess_matrix is the Lower Triangular Matrix into which values are filled |
204 |
@param count is the count of elements filled |
205 |
@param safe is the boolean value indicating whether evaluation is safe or non-safe |
206 |
|
207 |
@return 0 on success, non-zero if an error is encountered in the calculation |
208 |
*/ |
209 |
|
210 |
ASC_DLLSPEC int relman_diff3(struct rel_relation *rel, |
211 |
const var_filter_t *filter, |
212 |
real64 *derivatives, |
213 |
struct var_variable **variables, |
214 |
int32 *count, |
215 |
int32 safe); |
216 |
/**< as relman_diff2 but fills a var_variable* array intest of an index array. */ |
217 |
|
218 |
ASC_DLLSPEC int relman_diff_grad(struct rel_relation *rel, |
219 |
const var_filter_t *filter, |
220 |
real64 *derivatives, |
221 |
int32 *variables_master, |
222 |
int32 *variables_solver, |
223 |
int32 *count, |
224 |
real64 *resid, |
225 |
int32 safe); |
226 |
/**< |
227 |
* Calculates the row of the jacobian matrix (the transpose gradient of |
228 |
* the relation residual grad^T(f) ) corresponding to the relation |
229 |
* rel. The filter determines which variables actually contribute to the |
230 |
* jacobian. The residual of the relation is also computed and returned. |
231 |
* If an error is encountered in the calculation, the status returned is |
232 |
* 1. Status = 0 is OK. |
233 |
* If the value of safe is nonzero, "safe" functions are used to for |
234 |
* the calculations.<br><br> |
235 |
* The calling function should allocate the output vectors 'derivatives', |
236 |
* 'variables_master' and 'variables_solver'. 'count' will be set to |
237 |
* the number of elements assigned upon exit. |
238 |
* derivative(i) will contain the derivative of the relation with |
239 |
* respect to the variable whose master index is stored in |
240 |
* variables_master(i). The solver index of each variable is stored in |
241 |
* variables_solver(i). |
242 |
* |
243 |
* There are two differences wrt to relman_diff2: |
244 |
* - the master index (solver independent) is obtained |
245 |
* - the residual is evaluated |
246 |
*/ |
247 |
|
248 |
ASC_DLLSPEC int relman_diffs(struct rel_relation *rel, |
249 |
const var_filter_t *filter, mtx_matrix_t mtx, |
250 |
real64 *resid, int safe); |
251 |
/**< |
252 |
Calculates the row of the jacobian matrix (the transpose gradient of |
253 |
the relation residual grad^T(f) ) corresponding to the relation |
254 |
rel. The filter determines which variables actually contribute to the |
255 |
jacobian. The residual of the relation is also computed and returned. |
256 |
If an error is encountered in the calculation, the status returned is |
257 |
1 and the residual is set to some number we managed to calculate, |
258 |
while the gradient is discarded. status = 0 is OK. |
259 |
|
260 |
@param rel relation for which jacobian entries are required |
261 |
@param filter filter for which variables should actually contribute to the jacobian |
262 |
@param mtx matrix into which the row (corresponding to rel) is written |
263 |
@param safe if non-zero, "safe" functions are used to for the calucaltions. |
264 |
|
265 |
It doesn't matter how you have permuted the columns and rows: |
266 |
for the vars which pass the filter you send we |
267 |
fill the org row determined by rel_sindex and the org cols |
268 |
determined by var_sindex. |
269 |
|
270 |
@return 0 on success, 1 on calculation error (residual will be returned, grad discarded) |
271 |
|
272 |
@NOTE The row of the mtx corresponding to rel should be cleared |
273 |
before calling this function, since this FILLS with the gradient.<br><br> |
274 |
|
275 |
@NOTE *changed* -- This operator used to just ADD on top of any incidence |
276 |
already in the row. This is not TRUE now. |
277 |
|
278 |
@TODO This operator really needs to be redesigned so it can deal with |
279 |
harwellian matrices, glassbox rels and blackbox. |
280 |
*/ |
281 |
|
282 |
extern int32 relman_diff_harwell(struct rel_relation **rlist, |
283 |
var_filter_t *vfilter, rel_filter_t *rfilter, |
284 |
int32 rlen, int32 bias, int32 mors, |
285 |
real64 *avec, int32 *ivec, int32 *jvec); |
286 |
/**< |
287 |
* This fills an "a-i-j" sparse matrix in the avec/ivec/jvec given. |
288 |
* @param rlist struct rel_relation **, list of relations rlen long. |
289 |
* @param vfilter var_filter_t *, stuffs gradient for matching variables only. |
290 |
* @param rlen int32, length of list of relations. |
291 |
* @param bias int32, 0 = row grouped together, 1 = column grouped together. |
292 |
* There is a substantial penalty for bias = 1. we MODEL by row. |
293 |
* @param mors int32, 0 = master var index of columns, master rel index of rows |
294 |
* 1 = solver var index of columns, master rel index of rows |
295 |
* 2 = master var index of columns, solver rel index of rows |
296 |
* 3 = solver var index of columns, solver rel index of rows |
297 |
* Size of avec,ivec,jvec given is assumed big enough. |
298 |
* big_enough = relman_jacobian_count(rlist,rlen,vfilter,rfilter,&dummy); |
299 |
* If ivec or jvec given is NULL, then neither is stuffed, though avec is. |
300 |
@return 0 on success, <0 on floating point errors, 1 on unrecoverable error. |
301 |
|
302 |
err = 1 --> unrecoverable error/bad input. caller should probably punt. |
303 |
err < 0 --> -(number of floating point errors in evaluation). |
304 |
The matrix will contain an approximation only. |
305 |
|
306 |
@todo relman_diff_harwell() bias == 1 is not yet implemented. |
307 |
*/ |
308 |
|
309 |
ASC_DLLSPEC int32 relman_jacobian_count(struct rel_relation **rlist, |
310 |
int32 rlen, |
311 |
var_filter_t *vfilter, |
312 |
rel_filter_t *rfilter, |
313 |
int32 *rhomax); |
314 |
/**< |
315 |
* Return the number of nonzero gradient entries in the equations |
316 |
* given. Only equations passing rfilter and entries passing vfilter |
317 |
* are counted. rlen is the length of the relation list. |
318 |
* *rhomax is the largest row count on return. |
319 |
*/ |
320 |
|
321 |
ASC_DLLSPEC int32 relman_hessian_count( |
322 |
struct rel_relation **rlist, int32 rlen |
323 |
, var_filter_t *vfilter, rel_filter_t *rfilter |
324 |
, int32 *rhomax |
325 |
); |
326 |
/**< |
327 |
* Return the number of nonzero gradient entries in the equations |
328 |
* given. Only equations passing rfilter and entries passing vfilter |
329 |
* are counted. rlen is the length of the relation list. |
330 |
* *rhomax is the largest row count on return. |
331 |
*/ |
332 |
|
333 |
ASC_DLLSPEC boolean relman_calc_satisfied_scaled(struct rel_relation *rel, |
334 |
real64 tolerance); |
335 |
/**< |
336 |
* This definition of satisfaction includes the notion |
337 |
* of scaling by the relation nominal before comparison. |
338 |
* @see relman_calc_satisfied. |
339 |
*/ |
340 |
ASC_DLLSPEC boolean relman_calc_satisfied(struct rel_relation *rel, |
341 |
real64 tolerance); |
342 |
/**< |
343 |
* Returns TRUE or FALSE depending on whether the relation whose residual |
344 |
* has been previously calculated is satisfied based on the value stored |
345 |
* in the residual field. The satisfied field of the relation is also |
346 |
* updated. A tolerance specification allows equalities to be declared |
347 |
* satisfied as long as their residuals are close to zero. |
348 |
* @see relman_calc_satisfied_scaled. |
349 |
*/ |
350 |
|
351 |
#define relman_directly_solve(r,s,a,n) \ |
352 |
relman_directly_solve_new(r,s,a,n,1.0e-8) |
353 |
/**< @see relman_directly_solve_new(). */ |
354 |
extern real64 *relman_directly_solve_new(struct rel_relation *rel, |
355 |
struct var_variable *solvefor, |
356 |
int *able, |
357 |
int *nsolns, |
358 |
real64 tol); |
359 |
/**< |
360 |
* Attempts to solve the given equation for the given variable. If this |
361 |
* function is able to determine the solution set, then *able is set to |
362 |
* 1 and a newly allocated solution list is returned: *nsolns will be |
363 |
* set to the length of this array. Otherwise *able is 0 and NULL |
364 |
* is returned. NULL *may* also be returned if the solution set is empty. |
365 |
* A return of able == 1, solution_list != NULL, and nsolns == 0 is |
366 |
* possible for certain classes of floating point exceptions. |
367 |
* It is assumed that the relation is a condition of equality.<br><br> |
368 |
* |
369 |
* relman_directly_solve_new() handles passing in a tolerance for glassbox |
370 |
* relations so a rootfinder can do the work rather than leaving it to |
371 |
* someone else. The rootfinder is based on Brent's algorithm. Old clients of |
372 |
* relman_directly solve are grandfathered at a default tolerance of 1e-8. |
373 |
* Once all these clients are gone, go back to the old name space for |
374 |
* the new function.<br><br> |
375 |
* |
376 |
* Do NOT free or keep a persistent pointer to the solution_list this |
377 |
* function returns. |
378 |
*/ |
379 |
|
380 |
#define relman_make_string_infix(sys,rel) \ |
381 |
relman_make_vstring_infix((sys),(rel),TRUE) |
382 |
/**< @see relman_make_xstring_infix() */ |
383 |
#define relman_make_string_postfix(sys,rel) \ |
384 |
relman_make_vstring_postfix((sys),(rel),TRUE) |
385 |
/**< @see relman_make_xstring_infix() */ |
386 |
#define relman_make_xstring_infix(sys,rel) \ |
387 |
relman_make_vstring_infix((sys),(rel),FALSE) |
388 |
/**< |
389 |
@return string |
390 |
@param sys |
391 |
@param rel struct rel_relation *rel |
392 |
|
393 |
Creates a sufficiently large string (you must free it when you're |
394 |
done with it) into which it converts a relation. The string will be |
395 |
terminated with a '\0' character. |
396 |
|
397 |
The xstring versions of this call make strings where all the variables |
398 |
are written as x<varindex> (e.g. x23) rather than as object names. |
399 |
The MASTER index (var_mindex) is used, not the solver's sindex. |
400 |
Currently the compiler does not support xstring postfix format, |
401 |
but could easily do so if needed. |
402 |
|
403 |
The name of a var is context dependent, so you have to provide the |
404 |
slv_system_t from which you got the relation. |
405 |
|
406 |
@see relman_make_string_postfix |
407 |
@see relman_make_string_infix |
408 |
*/ |
409 |
|
410 |
#if 0 /* needs compiler-side work */ |
411 |
# define relman_make_xstring_postfix(sys,rel) \ |
412 |
relman_make_vstring_postfix((sys),(rel),FALSE) |
413 |
#else |
414 |
# define relman_make_xstring_postfix(sys,rel) \ |
415 |
dummy_rel_string((sys),(rel),0) |
416 |
#endif |
417 |
/**< |
418 |
* Not suppported. |
419 |
* @TODO Consider adding support for xstring postfix format. |
420 |
*/ |
421 |
|
422 |
ASC_DLLSPEC char *relman_make_vstring_infix(slv_system_t sys, |
423 |
struct rel_relation *rel, |
424 |
int style); |
425 |
/**< |
426 |
* Implementation function for relman_make_string_infix() and |
427 |
* relman_make_xstring_infix(). Do not call this function |
428 |
* directly - use one of the macros instead. |
429 |
*/ |
430 |
extern char *relman_make_vstring_postfix(slv_system_t sys, |
431 |
struct rel_relation *rel, |
432 |
int style); |
433 |
/**< |
434 |
* Implementation function for relman_make_string_postfix(). and |
435 |
* Do not call this function directly - use the macro instead. |
436 |
*/ |
437 |
|
438 |
extern char *dummyrelstring(slv_system_t sys, |
439 |
struct rel_relation *rel, |
440 |
int style); |
441 |
/**< Temporary no-op function to placehold unimplemented io functions. */ |
442 |
|
443 |
extern void relman_free_reused_mem(void); |
444 |
/**< Call when desired to free memory cached internally. */ |
445 |
|
446 |
/* @} */ |
447 |
|
448 |
#endif /* ASC_RELMAN_H */ |
449 |
|