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

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