forked from Pyomo/pyomo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunc_designer.py
207 lines (172 loc) · 6.7 KB
/
func_designer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# ___________________________________________________________________________
#
# Pyomo: Python Optimization Modeling Objects
# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and
# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
__all__ = ['Pyomo2FuncDesigner']
import logging
import six
try:
import FuncDesigner
FD_available=True
except ImportError:
FD_available=False
from pyomo.core.base import SymbolMap, NumericLabeler
from pyomo.core.base import Constraint, Objective, Var
from pyomo.core.base import expr, var
from pyomo.core.base import param
from pyomo.core.base import numvalue
from pyomo.core.base import _ExpressionData
try:
long
intlist = [int, float, long]
except:
intlist = [int, float]
logger = logging.getLogger('pyomo.core')
labeler = NumericLabeler("x")
if FD_available:
try:
tanh = FuncDesigner.tanh
arcsinh = FuncDesigner.arcsinh
arccosh = FuncDesigner.arccosh
arctanh = FuncDesigner.arctanh
except:
import FuncDesignerExt
tanh = FuncDesignerExt.tanh
arcsinh = FuncDesignerExt.arcsinh
arccosh = FuncDesignerExt.arccosh
arctanh = FuncDesignerExt.arctanh
def fd_pow(x,y):
return x**y
intrinsic_function_expressions = {
'log':FuncDesigner.log,
'log10':FuncDesigner.log10,
'sin':FuncDesigner.sin,
'cos':FuncDesigner.cos,
'tan':FuncDesigner.tan,
'sinh':FuncDesigner.sinh,
'cosh':FuncDesigner.cosh,
'tanh':FuncDesigner.tanh,
'asin':FuncDesigner.arcsin,
'acos':FuncDesigner.arccos,
'atan':FuncDesigner.arctan,
'exp':FuncDesigner.exp,
'sqrt':FuncDesigner.sqrt,
'asinh':FuncDesigner.arcsinh,
'acosh':arccosh,
'atanh':arctanh,
'pow':fd_pow,
'abs':FuncDesigner.abs,
'ceil':FuncDesigner.ceil,
'floor':FuncDesigner.floor
}
id_counter=0
def Pyomo2FD_expression(exp, ipoint, vars, symbol_map):
if isinstance(exp, expr._IntrinsicFunctionExpression):
if not exp.name in intrinsic_function_expressions:
logger.error("Unsupported intrinsic function (%s)", exp.name)
raise TypeError("FuncDesigner does not support '{0}' expressions".format(exp.name))
args = []
for child_exp in exp._args:
args.append( Pyomo2FD_expression(child_exp, ipoint, vars, symbol_map))
fn = intrinsic_function_expressions[exp.name]
return fn(*tuple(args))
elif isinstance(exp, expr._SumExpression):
args = []
for child_exp in exp._args:
args.append( Pyomo2FD_expression(child_exp, ipoint, vars, symbol_map) )
iargs = args.__iter__()
#
# NOTE: this call to FuncDesigner.sum() _must_ be passed a list. If a
# generator is passed to this function, then an unbalanced expression tree will
# be generated that is not well-suited for large models!
#
if six.PY2:
return FuncDesigner.sum([c*iargs.next() for c in exp._coef]) + exp._const
else:
return FuncDesigner.sum([c*next(iargs) for c in exp._coef]) + exp._const
elif isinstance(exp, expr._ProductExpression):
ans = exp._coef
for n in exp._numerator:
ans *= Pyomo2FD_expression(n, ipoint, vars, symbol_map)
for n in exp._denominator:
ans /= Pyomo2FD_expression(n, ipoint, vars, symbol_map)
return ans
#elif isinstance(exp, expr._InequalityExpression):
#args = []
#for child_exp in exp._args:
#args.append( Pyomo2FD_expression(child_exp, ipoint, vars, symbol_map) )
#
#ans = args[0]
#for i in xrange(len(args)-1):
## FD doesn't care whether the inequality is strict
#ans = ans < args[i+1]
#return ans
#elif isinstance(exp, expr._InequalityExpression):
#return Pyomo2FD_expression(exp._args[0], ipoint, vars) == Pyomo2FD_expression(exp._args[1], ipoint, vars, symbol_map)
elif isinstance(exp, _ExpressionData):
return Pyomo2FD_expression(exp._args[0], ipoint, vars, symbol_map)
elif (isinstance(exp,var._VarData) or isinstance(exp,var.Var)) and not exp.is_fixed():
vname = symbol_map.getSymbol(exp, labeler)
if not vname in vars:
vars[vname] = FuncDesigner.oovar(vname)
ipoint[vars[vname]] = 0.0 if exp.value is None else exp.value
#symbol_map.getSymbol(exp, lambda obj,x: x, vname)
return vars[vname]
elif isinstance(exp,param._ParamData):
return exp.value
elif type(exp) in intlist:
return exp
elif isinstance(exp,numvalue.NumericConstant) or exp.is_fixed():
return exp.value
else:
raise ValueError("Unsupported expression type in Pyomo2FD_expression: "+str(type(exp)))
def Pyomo2FuncDesigner(instance):
if not FD_available:
return None
ipoint = {}
vars = {}
sense = None
nobj = 0
smap = SymbolMap()
_f_name = []
_f = []
_c = []
for con in instance.component_data_objects(Constraint, active=True):
body = Pyomo2FD_expression(con.body, ipoint, vars, smap)
if not con.lower is None:
lower = Pyomo2FD_expression(con.lower, ipoint, vars, smap)
_c.append( body > lower )
if not con.upper is None:
upper = Pyomo2FD_expression(con.upper, ipoint, vars, smap)
_c.append( body < upper )
for var in instance.component_data_objects(Var, active=True):
body = Pyomo2FD_expression(var, ipoint, vars, smap)
if not var.lb is None:
lower = Pyomo2FD_expression(var.lb, ipoint, vars, smap)
_c.append( body > lower )
if not var.ub is None:
upper = Pyomo2FD_expression(var.ub, ipoint, vars, smap)
_c.append( body < upper )
for obj in instance.component_data_objects(Objective, active=True):
nobj += 1
if obj.is_minimizing():
_f.append( Pyomo2FD_expression(obj.expr, ipoint, vars, smap) )
else:
_f.append( - Pyomo2FD_expression(obj.expr, ipoint, vars, smap) )
_f_name.append(obj.name)
smap.getSymbol(obj, lambda objective: objective.name)
# TODO - use 0.0 for default values???
# TODO - create results map
S = FuncDesigner.oosystem()
S._symbol_map = smap
S.f = _f[0]
S._f_name = _f_name
S.constraints.update(_c)
S.initial_point = ipoint
S.sense = sense
return S