#
source:
coopr.pyomo/trunk/coopr/pyomo/base/intrinsic_functions.py
@
3714

Revision 3714, 5.5 KB checked in by jdsiiro, 5 years ago (diff) |
---|

Line | |
---|---|

1 | # _________________________________________________________________________ |

2 | # |

3 | # Coopr: A COmmon Optimization Python Repository |

4 | # Copyright (c) 2008 Sandia Corporation. |

5 | # This software is distributed under the BSD License. |

6 | # Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, |

7 | # the U.S. Government retains certain rights in this software. |

8 | # For more information, see the Coopr README.txt file. |

9 | # _________________________________________________________________________ |

10 | |

11 | # |

12 | # TODO: Do we need to have different Expression objects for different |

13 | # intrinsic expressions? |

14 | # TODO: If an expression has a fixed value, should we simply call the |

15 | # intrinsic function with the value of that expression? |

16 | # TODO: Do we need to register these expression objects? |

17 | # |

18 | |

19 | __all__ = ['log', 'log10', 'sin', 'cos', 'tan', 'cosh', 'sinh', 'tanh', |

20 | 'asin', 'acos', 'atan', 'exp', 'sqrt', 'asinh', 'acosh', 'atanh'] |

21 | |

22 | import math |

23 | |

24 | from component import Component |

25 | from expr import _IntrinsicFunctionExpression |

26 | from numvalue import NumericValue, as_numeric |

27 | |

28 | |

29 | def generate_intrinsic_function_expression(args, nargs, name, fcn): |

30 | def _clone_if_needed(obj): |

31 | count = sys.getrefcount(obj) - generate_intrinsic_function_expression.UNREFERENCED_EXPR_COUNT |

32 | if generate_intrinsic_function_expression.clone_if_needed_callback: |

33 | generate_intrinsic_function_expression.clone_if_needed_callback(count) |

34 | if count == 0: |

35 | return obj |

36 | elif count > 0: |

37 | generate_intrinsic_function_expression.clone_counter += 1 |

38 | return obj.clone() |

39 | else: |

40 | raise RuntimeError, "Expression entered generate_expression() " \ |

41 | "with too few references (%s<0); this is indicative of a " \ |

42 | "SERIOUS ERROR in the expression reuse detection scheme." \ |

43 | % ( count, ) |

44 | |

45 | # Special handling: if there are no Pyomo Modeling Objects in the |

46 | # argument list, then evaluate the expression and return the result. |

47 | pyomo_expression = False |

48 | for arg in args: |

49 | # FIXME: does anyone know why we also test for 'Component' here? [JDS] |

50 | if isinstance(arg, NumericValue) or isinstance(arg, Component): |

51 | # TODO: efficiency: we already know this is a NumericValue - |

52 | # so we should be able to avoid the call to as_numeric() |

53 | # below (expecially since most intrinsic functions are unary |

54 | # operators. |

55 | pyomo_expression = True |

56 | break |

57 | if not pyomo_expression: |

58 | return fcn(*args) |

59 | |

60 | new_args = [] |

61 | for arg in args: |

62 | new_arg = as_numeric(arg) |

63 | if new_arg.is_expression(): |

64 | new_arg = _clone_if_needed(new_arg) |

65 | elif new_arg.is_indexed(): |

66 | raise ValueError, "Argument for intrinsic function '%s' is an "\ |

67 | "n-ary numeric value: %s\n Have you given variable or "\ |

68 | "parameter '%s' an index?" % (name, new_arg.name, new_arg.name) |

69 | new_args.append(arg) |

70 | return _IntrinsicFunctionExpression(name, nargs, tuple(new_args), fcn) |

71 | |

72 | # [testing] clone_check_callback allows test functions to intercept the |

73 | # call to _clone_if_needed and see the returned value from |

74 | # sys.getrefcount. |

75 | generate_intrinsic_function_expression.clone_if_needed_callback = None |

76 | |

77 | # [debugging] clone_counter is a count of the number of calls to |

78 | # expr.clone() made during expression generation. |

79 | generate_intrinsic_function_expression.clone_counter = 0 |

80 | |

81 | # [configuration] UNREFERENCED_EXPR_COUNT is a "magic number" that |

82 | # indicates the stack depth between "normal" modeling and |

83 | # _clone_if_needed(). If an expression enters _clone_if_needed() with |

84 | # UNREFERENCED_EXPR_COUNT references, then there are no other variables |

85 | # that hold a reference to the expression and cloning is not necessary. |

86 | # If there are more references than UNREFERENCED_EXPR_COUNT, then we |

87 | # must clone the expression before operating on it. It should be an |

88 | # error to hit _clone_if_needed() with fewer than |

89 | # UNREFERENCED_EXPR_COUNT references. |

90 | generate_intrinsic_function_expression.UNREFERENCED_EXPR_COUNT = 7 |

91 | |

92 | |

93 | def log(*args): |

94 | return generate_intrinsic_function_expression(args, 1, 'log', math.log) |

95 | |

96 | def log10(*args): |

97 | return generate_intrinsic_function_expression(args, 1, 'log10', math.log10) |

98 | |

99 | def sin(*args): |

100 | return generate_intrinsic_function_expression(args, 1, 'sin', math.sin) |

101 | |

102 | def cos(*args): |

103 | return generate_intrinsic_function_expression(args, 1, 'cos', math.cos) |

104 | |

105 | def tan(*args): |

106 | return generate_intrinsic_function_expression(args, 1, 'tan', math.tan) |

107 | |

108 | def sinh(*args): |

109 | return generate_intrinsic_function_expression(args, 1, 'sinh', math.sinh) |

110 | |

111 | def cosh(*args): |

112 | return generate_intrinsic_function_expression(args, 1, 'cosh', math.cosh) |

113 | |

114 | def tanh(*args): |

115 | return generate_intrinsic_function_expression(args, 1, 'tanh', math.tanh) |

116 | |

117 | def asin(*args): |

118 | return generate_intrinsic_function_expression(args, 1, 'asin', math.asin) |

119 | |

120 | def acos(*args): |

121 | return generate_intrinsic_function_expression(args, 1, 'acos', math.acos) |

122 | |

123 | def atan(*args): |

124 | return generate_intrinsic_function_expression(args, 1, 'atan', math.atan) |

125 | |

126 | def exp(*args): |

127 | return generate_intrinsic_function_expression(args, 1, 'exp', math.exp) |

128 | |

129 | def sqrt(*args): |

130 | return generate_intrinsic_function_expression(args, 1, 'sqrt', math.sqrt) |

131 | |

132 | def asinh(*args): |

133 | return generate_intrinsic_function_expression(args, 1, 'asinh', math.asinh) |

134 | |

135 | def acosh(*args): |

136 | return generate_intrinsic_function_expression(args, 1, 'acosh', math.acosh) |

137 | |

138 | def atanh(*args): |

139 | return generate_intrinsic_function_expression(args, 1, 'atanh', math.atanh) |

**Note:**See TracBrowser for help on using the repository browser.