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

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