/[ascend]/trunk/base/generic/compiler/relation_util.h
ViewVC logotype

Contents of /trunk/base/generic/compiler/relation_util.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 522 - (show annotations) (download) (as text)
Fri Apr 21 07:22:20 2006 UTC (13 years, 6 months ago) by johnpye
File MIME type: text/x-chdr
File size: 23262 byte(s)
Fixed all the missing symbols so that ASCEND Tcl/Tk interface builds with separate 'ascendtcl.dll'.
Split Driver.c across Driver.c and new main.c, which has no Tcl/Tk references.

1 /* ASCEND modelling environment
2 Copyright (C) 1990 Karl Michael Westerberg, Thomas Guthrie Weidner Epperly
3 Copyright (C) 1993 Joseph James Zaher
4 Copyright (C) 1993, 1994 Benjamin Andrew Allan, Joseph James Zaher
5 Copyright (C) 1996 Benjamin Andrew Allan, Kenneth Tyner
6 Copyright (C) 2006 Carnegie Mellon University
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
22 *//**
23 @file
24 Relation utility functions for Ascend.
25 This module defines the dimensionality checking and some other
26 auxillaries for Ascend.
27
28 Requires:
29 #include "utilities/ascConfig.h"
30 #include "compiler/fractions.h"
31 #include "compiler/compiler.h"
32 #include "compiler/functype.h"
33 #include "compiler/safe.h"
34 #include "compiler/dimen.h"
35 #include "compiler/types.h"
36 #include "compiler/relation_type.h"
37 #include "compiler/relation_util.h"
38 *//*
39 Version: $Revision: 1.27 $
40 Version control file: $RCSfile: relation_util.h,v $
41 Date last modified: $Date: 1998/02/05 16:37:48 $
42 Last modified by: $Author: ballan $
43 */
44
45 #ifndef ASC_RELATION_UTIL_H
46 #define ASC_RELATION_UTIL_H
47
48 #include <utilities/ascConfig.h>
49
50 ASC_DLLSPEC(int ) g_check_dimensions_noisy;
51 /**<
52 * If 0, warnings are suppressed. If 1, warnings are given
53 * from RelationCheckDimensions();
54 */
55
56 extern int RelationCheckDimensions(struct relation *rel, dim_type *dimens);
57 /**<
58 * Scans a relation in postfix and collects all dimensional
59 * information by applying each token. It returns a value of TRUE
60 * only if no real instances or real atom instances with wild
61 * dimensionality and no dimensional inconsistencies were encountered.
62 * If the return value is 2 rather than 1, then the dimensionality
63 * has been determined before.
64 * The address of an allocated dimension type is passed in so that
65 * the dimensions of the relation (or at least what the function
66 * thinks the dimensions ought to be) can be also obtained.
67 *
68 * THIS ONLY WORKS ON e_token relations and maybe in future e_opcode
69 * relations. rel is assumed to be valid when called. !!!
70 *
71 * This brings in the asc_check_dimensions function from ascend_utils.
72 * 3/96 Ben Allan
73 */
74
75 ASC_DLLSPEC(enum Expr_enum ) RelationRelop(CONST struct relation *rel);
76 /**<
77 * Return the type of the relation operator of the relation.
78 * Returns one of the following:
79 * <pre>
80 * e_equal equality constraint
81 * e_notequal non-equality contraint
82 * e_less less than contraint
83 * e_greater greater than contraint
84 * e_lesseq less than or equal contraint
85 * e_greatereq greater than or equal contraint
86 * e_maximize objective function to be maximized (rhs is empty)
87 * e_minimize objective function to be minimized (rhs is empty)
88 * </pre>
89 */
90
91 extern unsigned long NumberVariables(CONST struct relation *rel);
92 /**<
93 * This will indicate the number of distinct real atoms to which this relation
94 * points. This number contains both fixed and non-fixed atoms.
95 * This routine is smart enough to deal with all the different relation types.
96 */
97
98 ASC_DLLSPEC(struct Instance *) RelationVariable(CONST struct relation *rel,
99 unsigned long varnum);
100 /**<
101 * This will return the varnum'th variable.
102 * This routine is smart enough to deal with all the different relation
103 * types.
104 */
105
106 /*----------------------------------------------------------------------------
107 * TokenRelation and OpCodeRelation specific code.
108 *
109 * It is the responsibility of the user of these routines to be aware
110 * of the type of relation being used. Very little sanity checking is
111 * done.
112 *----------------------------------------------------------------------------
113 */
114
115 ASC_DLLSPEC(unsigned long ) RelationLength(CONST struct relation *rel, int lhs);
116 /**<
117 * If lhs is true, return the number of terms on the left hand side of the
118 * relation. Otherwise, return the number of terms on the right hand side
119 * of the relation.
120 */
121
122 ASC_DLLSPEC(CONST struct relation_term *) RelationTerm(CONST struct relation *rel,
123 unsigned long pos,
124 int lhs);
125 /**<
126 * If lhs is true, return the term in position pos of the left hand side.
127 * Otherwise, return the term in position pos of the right hand side.
128 * A bizarre thing about this operator: 1 <= pos <= RelationLength(rel,lhs).
129 * This is a holdover from gl_list days.
130 */
131
132 #ifdef NDEBUG
133 #define NewRelationTerm(r,p,l) \
134 A_TERM( (l)!=0 ? (&(RTOKEN(r).lhs[(p)])) : (&(RTOKEN(r).rhs[(p)])) )
135 #else
136 #define NewRelationTerm(r,p,l) NewRelationTermF((r),(p),(l))
137 #endif
138 /**<
139 * If l is true, return the term in position p of the left hand side.
140 * Otherwise, return the term in position p of the right hand side.
141 * For this operator: 0 <= p < RelationLength(rel,lhs) as a C array.
142 * Once Everybody gets their damn hands off RelationTerm, switch its
143 * semantics and eliminate one of this pair.
144 * @param r CONST struct relation*, the relation to query.
145 * @param p unsigned long, the position to retrieve.
146 * @param l int, flag for whether to return from the lhs or rhs.
147 * @return The specified term as a CONST struct relation_term*.
148 * @see NewRelationTermF()
149 */
150 extern CONST struct relation_term
151 *NewRelationTermF(CONST struct relation *rel, unsigned long apos, int lhs);
152 /**<
153 * Implementation function for NewRelationTerm(). Do not call this
154 * function directly - use NewRelationTerm() instead.
155 */
156
157 #ifdef NDEBUG
158 #define RelationSideTerm(rs,p) A_TERM(&((rs)[(p)]))
159 #else
160 #define RelationSideTerm(rs,p) RelationSideTermF((rs),(p))
161 #endif
162 /**<
163 * Return the term in position p of the side.
164 * For this operator: 0 <= p < length of the side.
165 * @param rs CONST union RelationTermUnion*, the relation to query.
166 * @param p unsigned long, the position to retrieve.
167 * @return The specified term as a CONST struct relation_term*.
168 * @see RelationSideTermF()
169 */
170 extern CONST struct relation_term
171 *RelationSideTermF(CONST union RelationTermUnion *relside, unsigned long apos);
172 /**<
173 * Implementation function for RelationSideTerm(). Do not call this
174 * function directly - use RelationSideTerm() instead.
175 */
176
177 #ifdef NDEBUG
178 #define RelationTermType(rtp) ((rtp)->t)
179 #else
180 #define RelationTermType(rtp) RelationTermTypeF(rtp)
181 #endif
182 /**<
183 * Return the type of the relation term.
184 * WARNING: if ALLOCATED_TESTS is active, term must be an allocated term;
185 * automatic variables will cause an assert() to fail.
186 * @param rtp CONST struct relation_term*, the term to query.
187 * @return The type as an enum Expr_enum.
188 * @see RelationTermTypeF()
189 */
190 ASC_DLLSPEC(enum Expr_enum ) RelationTermTypeF(CONST struct relation_term *term);
191 /**<
192 * Implementation function for RelationTermType(). Do not call this
193 * function directly - use RelationTermType() instead.
194 */
195
196 ASC_DLLSPEC(unsigned long ) TermVarNumber(CONST struct relation_term *term);
197 /**<
198 * Return the index into the relations variable list.
199 */
200
201 ASC_DLLSPEC(long ) TermInteger(CONST struct relation_term *term);
202 /**<
203 * Return the integer value from a e_int type relation term.
204 */
205
206 ASC_DLLSPEC(double ) TermReal(CONST struct relation_term *term);
207 /**<
208 * Return the double value from a e_real type relation term.
209 */
210
211 extern double TermVariable(CONST struct relation *rel,
212 CONST struct relation_term *term);
213 /**<
214 * Return the double value from a e_var type relation term.
215 */
216
217 ASC_DLLSPEC(CONST dim_type *) TermDimensions(CONST struct relation_term *term);
218 /**<
219 * Return the dimensions of a e_real, e_int, or e_zero relation term type.
220 * (e_int is always Dimensionless(); e_zero is always WildDimension().)
221 */
222
223 ASC_DLLSPEC(CONST struct Func *) TermFunc(CONST struct relation_term *term);
224 /**<
225 * Return the function pointer of a function operator.
226 */
227
228 ASC_DLLSPEC(unsigned long ) RelationDepth(CONST struct relation *rel);
229 /**<
230 * Return the depth of stack required to evaluate this relation.
231 */
232
233 /*------------------------------------------------------------------------
234 * TokenRelation Infix operations.
235 *------------------------------------------------------------------------
236 */
237
238 /*------------------------------------------------------------------------
239 * The four defines following return term pointers.
240 * struct relation_term *r, *t;
241 * r = TermUniLeft(t); for example.
242 * These should be implemented as functions which assert type
243 * and revert to macros with NDEBUG.
244 *------------------------------------------------------------------------
245 */
246 #define TermUniLeft(t) ( ((struct RelationUnary *)t) -> left)
247 #define TermFuncLeft(t) ( ((struct RelationFunc *)t) -> left)
248 #define TermBinLeft(t) ( ((struct RelationBinary *)t) -> left)
249 #define TermBinRight(t) ( ((struct RelationBinary *)t) -> right)
250
251 extern struct relation_term *RelationINF_Lhs(CONST struct relation *rel);
252 /**<
253 * Returns the lhs of an infix relation. This may be NULL,
254 * if the relation has not been set for infix scanning.
255 */
256
257 extern struct relation_term *RelationINF_Rhs(CONST struct relation *rel);
258 /**<
259 * Return the rhs of an infix relation. This may be NULL
260 * if the relation has not been set up for infix scanning, or if
261 * the relation is an objective relation.
262 */
263
264 extern int ArgsForRealToken(enum Expr_enum ex);
265 /**<
266 * Return the number of args required for a token from a real equation.
267 */
268
269 /*------------------------------------------------------------------------
270 * Opcode Relation processing.
271 * This stuff is NOT complete.
272 *------------------------------------------------------------------------
273 */
274 #define OpCode_Lhs(r) ((int *)(ROPCODE(r).lhs))
275 #define OpCode_Rhs(r) ((int *)(ROPCODE(r).rhs))
276 #define OpCodeNumberArgs(r) (ROPCODE(r).nargs)
277 #define OpCodeConstants(r) ((double *)(ROPCODE(r).constants))
278
279 /*------------------------------------------------------------------------
280 * BlackBox Relation processing.
281 *------------------------------------------------------------------------
282 */
283 extern struct ExtCallNode *BlackBoxExtCall(CONST struct relation *rel);
284 extern int *BlackBoxArgs(CONST struct relation *rel);
285
286 #define BlackBoxNumberArgs(r) (RBBOX(r).nargs)
287
288 /*------------------------------------------------------------------------
289 * GlassBoxRelation queries.
290 * These will be called a lot so that they will all be made
291 * macros. Double check that the same is true for the
292 * ExternalFunc routines.
293 *------------------------------------------------------------------------
294 */
295 extern struct ExternalFunc *GlassBoxExtFunc(CONST struct relation *rel);
296 extern int GlassBoxRelIndex(CONST struct relation *rel);
297 extern int *GlassBoxArgs(CONST struct relation *rel);
298
299 #define GlassBoxNumberArgs(r) (RGBOX(r).nargs)
300
301 extern CONST struct gl_list_t *RelationVarList(CONST struct relation *r);
302 /**<
303 * Returns the unique incident variable list which is owned by the
304 * relation. *DO NOT MODIFY*. It is for the convenience of those
305 * desirous of a READ_ONLY look. It is a list of instance pointers, which may
306 * be NULL.
307 * All relation types will properly respond to this qurey.
308 */
309
310 ASC_DLLSPEC(dim_type *) RelationDim(CONST struct relation *rel);
311 /**<
312 * Return the derived dimensionality of the relation.
313 * Defaults to Wild.
314 */
315
316 ASC_DLLSPEC(int ) SetRelationDim(struct relation *rel, dim_type *d);
317 /**<
318 * Set the dimensionality of the relation. return 0 unless there is a
319 * problem (rel was null, for instance.)
320 */
321
322 ASC_DLLSPEC(double) RelationResidual(CONST struct relation *rel);
323 /**<
324 * Return the residual of the relation.
325 */
326
327 extern void SetRelationResidual(struct relation *rel, double value);
328 /**<
329 * Set the value of the relation residual.
330 */
331
332 extern double RelationMultiplier(CONST struct relation *rel);
333 /**<
334 * Return the langrage multiplier of the relation. This will have some
335 * hybrid dimensions that still needs to be decided, as it is a function
336 * of the objective function(s).
337 */
338
339 extern void SetRelationMultiplier(struct relation *rel, double value);
340 /**<
341 * Set the value of the relation langrage multiplier. This will have some
342 * hybrid dimensions that still needs to be decided.
343 */
344
345 ASC_DLLSPEC(int ) RelationIsCond(CONST struct relation *rel);
346 /**<
347 * Return the value of the iscond flag of the relation.
348 * If relation is NULL, returns 0.
349 */
350
351 extern void SetRelationIsCond(struct relation *rel);
352 /**<
353 * Sets the value of the iscond field of the relation to 1
354 * If relation is NULL, writes error message.
355 */
356
357 extern double RelationNominal(CONST struct relation *rel);
358 /**<
359 * Return the nominal of the relation.
360 */
361
362 ASC_DLLSPEC(void ) SetRelationNominal(struct relation *rel, double d);
363 /**<
364 * Sets the value of the nominal field of the relation to the absolute
365 * value of d, unless d is 0.0.
366 */
367
368 ASC_DLLSPEC(double ) CalcRelationNominal(struct Instance *i);
369 /**<
370 * Calculate the nominal of a relation.
371 * Returns 0.0 if something went detectably wrong in the calculation,
372 * otherwise calculates the absolute value of the maximum affine term
373 * and returns it, given an instance which is a token relation. Other
374 * relation types return the value 1.0.
375 * Does not set the constant stored with the relation.<br><br>
376 *
377 * When opcode relations are fully supported,
378 * this function should be made to work for them, too.<br><br>
379 *
380 * Art contends that the proper nominal for blackbox
381 * relations is the nominal of the output variable, though this is
382 * not implemented at present.<br><br>
383 *
384 * Art further contends that the proper nominal for glassbox relations
385 * is the 2 norm of its gradient vector after fixed variables are
386 * removed and free elements have been scaled by the variable nominals.
387 * It should be noted that the glassbox scaling proposed by this method
388 * is precisely what the Slv solvers used up to August 1995.
389 * IMHO (baa) the glassbox generated should include code which knows
390 * how to calculate relation nominals.
391 */
392
393 extern void PrintRelationNominals(struct Instance *i);
394 /**<
395 * Perform a visit instance tree starting at i and calc/print consts.
396 * This function doesn't belong here.
397 */
398
399 extern char *tmpalloc(int nbytes);
400 /**<
401 * Temporarily allocates a given number of bytes. The memory need
402 * not be freed, but the next call to this function will reuse the
403 * previous allocation. Memory returned will NOT be zeroed.
404 * Calling with nbytes==0 will free any memory allocated.
405 */
406
407 #define tmpalloc_array(nelts,type) ((type *)tmpalloc((nelts)*sizeof(type)))
408 /**<
409 * Creates an array of "nelts" objects, each with type "type".
410 */
411
412 /*
413 * The following mess of functions
414 * migrated out of the solver directory into this file. Who
415 * ever heard of a math modeling language that doesn't supply
416 * evaluation functions for its equations?
417 * These are for Token equations, though if they can be done
418 * for all equation types that's a plus.
419 * Supercedes the bleeding mess in calc.c, rel.c, relman.c which was
420 * very ugly.
421 * BAA 5/96
422 *
423 */
424
425 extern int RelationCalcResidualBinary(CONST struct relation *rel, double *res);
426 /**<
427 * Returns 0 if it calculates a valid residual, 1 if
428 * for any reason it cannot. Reasons include:
429 * - relation not token relation.
430 * - token relation not compiled to binary.
431 * - NaN/infinity result.
432 * - out of memory.
433 * If return is 1, then res will not have been changed.
434 * This function may raise SIGFPE it calls external code.
435 */
436
437 extern enum safe_err
438 RelationCalcResidualPostfixSafe(struct Instance *i, double *res);
439 /**<
440 * Sets *res to the value (leftside - rightside) of the relation.
441 * status != 0 (safe_ok = 0) implies a problem.
442 * This function is slower than RelationCalcResidual() because it does
443 * a lot of range checking AND a floating point trap.
444 */
445
446 extern int RelationCalcResidualPostfix(struct Instance *i, double *res);
447 /**<
448 * Sets *res to the value (leftside - rightside) of the relation.
449 * Uses postfix evaluation.
450 * status != 0 implies a problem.
451 * Notes: This function is a possible source of floating point
452 * exceptions and should not be used during compilation.
453 */
454
455 /*
456 * The following bit flags are used to build up the return
457 * status from RelationCalcExceptionsInfix.
458 * No provision is made for checking gradient elements --
459 * gradients are in principle an all or nothing affair.
460 */
461 #define RCE_BADINPUT -1 /**< called with non-token relation */
462 #define RCE_OK 0 /**< no error */
463 #define RCE_ERR_LHS 0x1 /**< left side evaluation error */
464 #define RCE_ERR_RHS 0x2 /**< right side evaluation error */
465 #define RCE_ERR_LHSGRAD 0x4 /**< left side gradient error */
466 #define RCE_ERR_RHSGRAD 0x8 /**< right side gradient error */
467 #define RCE_ERR_LHSINF 0x10 /**< left side returns Infinity */
468 #define RCE_ERR_RHSINF 0x20 /**< right side returns Infinity */
469 #define RCE_ERR_LHSNAN 0x40 /**< left side returns NaN */
470 #define RCE_ERR_RHSNAN 0x80 /**< right side returns NaN */
471
472 ASC_DLLSPEC(int ) RelationCalcExceptionsInfix(struct Instance *i);
473 /**<
474 * Uses infix evaluation to check gradient and residual
475 * floating point exceptions.
476 * status != 0 implies a problem.
477 * Notes: This function is a possible source of floating point
478 * exceptions and should not be used during compilation.
479 * This function should not be called except inside the scope of a
480 * Asc_SignalHandlerPush(SIGFPE,SIG_IGN);
481 * Asc_SignalHandlerPop(SIGFPE,SIG_IGN);
482 * pair.
483 * Functions that report exceptions here may still be evaluated
484 * With the Safe relation evaluation routines in all but the most
485 * bizarre circumstances. The Safe results are necessarily approximate.
486 *
487 * @bug At present, gradient checks are not implemented as the code
488 * required is messy. We need to rearrange CalcResidGrad().
489 */
490
491 extern int RelationCalcResidualInfix(struct Instance *i, double *res);
492 /**<
493 * Sets *res to the value (leftside - rightside) of the relation.
494 * Uses infix evaluation.
495 * Non-zero return value implies a problem.
496 * Notes: This function is a possible source of floating point
497 * exceptions and should not be used during compilation.
498 */
499
500 #define RelationCalcResidual(i,r) RelationCalcResidualPostfix(i,r)
501 #define RelationCalcResidualSafe(i,r) RelationCalcResidualPostfixSafe(i,r)
502
503 extern int RelationCalcGradient(struct Instance *i, double *grad);
504 /**<
505 * This calculates the gradient of the relation df/dx (f = lhs-rhs)
506 * where x is ALL entries in the relation's var list.
507 * The var list is a gl_list_t indexed from 1 to length.
508 * You must provide grad, the space to put the gradient, an array of
509 * double of length matching the gl_list_t.
510 * We will stuff df/dx[i] into grad[i-1], where i is the list position
511 * in the relation's var list.<br><br>
512 *
513 * Non-zero return value implies a problem.<br><br>
514 *
515 * Notes: This function is a possible source of floating point
516 * exceptions and should not be used during compilation.
517 */
518
519 extern enum safe_err RelationCalcGradientSafe(struct Instance *i, double *grad);
520 /**<
521 * This calculates the gradient of the relation df/dx (f = lhs-rhs)
522 * where x is ALL entries in the relation's var list.
523 * This function is to RelationCalcGradient as
524 * RelationCalcResidualSafe is to RelationCalcResidual.
525 * Non-zero return value implies a problem.
526 */
527
528 extern int RelationCalcResidGrad(struct Instance *i, double *res, double *grad);
529 /**<
530 * This function combines the Residual and Gradient calls, since these
531 * may be done together at basically the cost of just one.
532 * Non-zero return value implies a problem.<br><br>
533 * Notes: This function is a possible source of floating point
534 * exceptions and should not be used during compilation.
535 */
536
537 extern enum safe_err
538 RelationCalcResidGradSafe(struct Instance *i, double *res, double *grad);
539 /**<
540 * This is the combined Safe version.
541 * Non-zero return value implies a problem.
542 */
543
544 extern double *RelationFindRoots(struct Instance *i,
545 double lower_bound,
546 double upper_bound,
547 double nominal,
548 double tolerance,
549 unsigned long *varnum,
550 int *able,
551 int *nsolns);
552 /**<
553 * RelationFindRoot WILL find a root if there is one. It is in charge of
554 * trying every trick in the book. The user must pass in a pointer to a
555 * struct relation. We require that the relation be of the type e_token with
556 * relation->relop = e_equals and we will whine if it is not. The calling
557 * function should check able and/or nsolns before accessing the information
558 * in the soln_list.
559 * - nsolns < 0 : severe problems, soln_list will be NULL
560 * - nsolns = 0 : No solution found
561 * - nsolns > 0 : The soln_status equals the number of roots found
562 *
563 * The calling function should NOT free the soln_list.<br><br>
564 *
565 * This function is NOT thread safe because it uses an internal memory
566 * recycle.
567 * Before shutting down the system, or as desired, call this as:
568 * (void) RelationFindRoots(NULL,0,0,0,0,NULL,NULL,NULL);
569 * in order to free this memory.
570 */
571
572 extern int RelationCalcDerivative(struct Instance *i, unsigned long index, double *grad);
573 /**<
574 * This calculates the derivative of the relation df/dx (f = lhs-rhs)
575 * where x is the INDEX-th entry in the relation's var list.
576 * The var list is a gl_list_t indexed from 1 to length.
577 * Non-zero return value implies a problem.<br><br>
578 *
579 * Notes: This function is a possible source of floating point
580 * exceptions and should not be used during compilation.
581 */
582
583 extern enum safe_err
584 RelationCalcDerivativeSafe(struct Instance *i, unsigned long index, double *grad);
585 /**<
586 * Calculates the derivative safely.
587 * Non-zero return value implies a problem.
588 */
589
590
591 extern struct gl_list_t
592 *CollectTokenRelationsWithUniqueBINlessShares(struct Instance *i, unsigned long maxlen);
593 /**<
594 * Collect the token relation 'shares' in i which have not been compiled
595 * (or at least attempted so) to binary form yet.
596 * If more than maxlen are found, returns NULL instead. Presumably there
597 * is some upper limit beyond which you don't want to know the answer to
598 * this question. If none are found, returns a 0 length list.
599 * Actually, it is not a share that is collected, but instead any
600 * one of the relation instances which use the share is collected.
601 * The list returned should be destroyed by the user (not its content,though).
602 */
603
604 #endif /* ASC_RELATION_UTIL_H */

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22