_expr_richcmp(self, other, op):
59 ifisinstance(other, Expr)
orisinstance(other, GenExpr):
60 return(self - other) <= 0.0
61 elif_is_number(other):
62 return ExprCons(self, rhs=float(other))
64 raiseNotImplementedError
66 ifisinstance(other, Expr)
orisinstance(other, GenExpr):
67 return(self - other) >= 0.0
68 elif_is_number(other):
69 return ExprCons(self, lhs=float(other))
71 raiseNotImplementedError
73 ifisinstance(other, Expr)
orisinstance(other, GenExpr):
74 return(self - other) == 0.0
75 elif_is_number(other):
76 return ExprCons(self, lhs=float(other), rhs=float(other))
78 raiseNotImplementedError
80 raiseNotImplementedError(
"Can only support constraints with '<=', '>=', or '=='.")
84 '''This is a monomial term''' 86__slots__ = (
'vartuple',
'ptrtuple',
'hashval')
89self.
vartuple= tuple(sorted(vartuple, key=
lambdav: v.ptr()))
100 returnself.
ptrtuple== other.ptrtuple
106both = self.
vartuple+ other.vartuple
110 return 'Term(%s)'%
', '.join([str(v)
forv
inself.
vartuple])
117 """helper function to generate an object of type GenExpr""" 120 elifisinstance(expr, Expr):
125 forvars, coef
inexpr.terms.items():
130sumexpr += coef * varexpr
136sumexpr += coef * prodexpr
139 assertisinstance(expr, GenExpr)
147 '''terms is a dict of variables to coefficients. 149 CONST is used as key for the constant term.''' 150self.
terms= {}
ifterms
is None elseterms
152 iflen(self.
terms) == 0:
153self.
terms[CONST] = 0.0
156 if notisinstance(key, Term):
158 returnself.
terms.get(key, 0.0)
161 returniter(self.
terms)
164 try:
returnnext(self.
terms)
165 except:
raiseStopIteration
175 assertisinstance(other, Expr)
176left,right = right,left
177terms = left.terms.copy()
179 ifisinstance(right, Expr):
181 forv,c
inright.terms.items():
182terms[v] = terms.get(v, 0.0) + c
183 elif_is_number(right):
185terms[CONST] = terms.get(CONST, 0.0) + c
186 elifisinstance(right, GenExpr):
189 raiseNotImplementedError
193 ifisinstance(other, Expr):
194 forv,c
inother.terms.items():
195self.
terms[v] = self.
terms.get(v, 0.0) + c
196 elif_is_number(other):
198self.
terms[CONST] = self.
terms.get(CONST, 0.0) + c
199 elifisinstance(other, GenExpr):
205 raiseNotImplementedError
209 if_is_number(other):
211 return Expr({v:f*c
forv,c
inself.
terms.items()})
212 elif_is_number(self):
214 return Expr({v:f*c
forv,c
inother.terms.items()})
215 elifisinstance(other, Expr):
217 forv1, c1
inself.
terms.items():
218 forv2, c2
inother.terms.items():
220terms[v] = terms.get(v, 0.0) + c1 * c2
222 elifisinstance(other, GenExpr):
225 raiseNotImplementedError
228 if_is_number(other):
232 returnselfexpr.__truediv__(other)
240 returnotherexpr.__truediv__(self)
243 iffloat(other).is_integer()
andother >= 0:
254 return Expr({v:-c
forv,c
inself.
terms.items()})
257 returnself + (-other)
266 return-1.0 * self + other
269 '''turn it into a constraint''' 270 return_expr_richcmp(self, other, op)
273 '''remove terms with coefficient of 0''' 274self.
terms= {t:c
for(t,c)
inself.
terms.items()
ifc != 0.0}
277 return 'Expr(%s)'% repr(self.
terms)
280 '''computes highest degree of terms''' 281 iflen(self.
terms) == 0:
284 returnmax(len(v)
forv
inself.
terms)
288 '''Constraints with a polynomial expressions and lower/upper bounds.''' 297 assert not(lhs
is None andrhs
is None)
301 '''move constant terms in expression to bounds''' 302 ifisinstance(self.
expr, Expr):
303c = self.
expr[CONST]
305 assertself.
expr[CONST] == 0.0
308 assertisinstance(self.
expr, GenExpr)
311 if notself.
_lhs is None:
313 if notself.
_rhs is None:
318 '''turn it into a constraint''' 320 if notself.
_rhs is None:
321 raiseTypeError(
'ExprCons already has upper bound')
322 assertself.
_rhs is None 323 assert notself.
_lhs is None 325 if not_is_number(other):
326 raiseTypeError(
'Ranged ExprCons is not well defined!')
330 if notself.
_lhs is None:
331 raiseTypeError(
'ExprCons already has lower bound')
332 assertself.
_lhs is None 333 assert notself.
_rhs is None 335 if not_is_number(other):
336 raiseTypeError(
'Ranged ExprCons is not well defined!')
343 return 'ExprCons(%s, %s, %s)'% (self.
expr, self.
_lhs, self.
_rhs)
346 '''Make sure that equality of expressions is not asserted with ==''' 348msg =
"""Can't evaluate constraints as booleans. 350 If you want to add a ranged constraint of the form 351 lhs <= expression <= rhs 352 you have to use parenthesis to break the Python syntax for chained comparisons: 353 lhs <= (expression <= rhs) 358 '''add linear expressions and constants much faster than Python's sum 359 by avoiding intermediate data structures and adding terms inplace 362 forterm
intermlist:
367 '''multiply linear expressions and constants by avoiding intermediate 368 data structures and multiplying terms inplace 371 forterm
intermlist:
379exp, log, sqrt, sin, cos =
'exp',
'log',
'sqrt',
'sin',
'cos' 380plus, minus, mul, div, power =
'+',
'-',
'*',
'/',
'**' 412 ifleft.getOp() == Operator.add:
413ans.coefs.extend(left.coefs)
414ans.children.extend(left.children)
415ans.constant += left.constant
416 elifleft.getOp() == Operator.const:
417ans.constant += left.number
419ans.coefs.append(1.0)
420ans.children.append(left)
423 ifright.getOp() == Operator.add:
424ans.coefs.extend(right.coefs)
425ans.children.extend(right.children)
426ans.constant += right.constant
427 elifright.getOp() == Operator.const:
428ans.constant += right.number
430ans.coefs.append(1.0)
431ans.children.append(right)
467 ifleft.getOp() == Operator.prod:
468ans.children.extend(left.children)
469ans.constant *= left.constant
470 elifleft.getOp() == Operator.const:
471ans.constant *= left.number
473ans.children.append(left)
476 ifright.getOp() == Operator.prod:
477ans.children.extend(right.children)
478ans.constant *= right.constant
479 elifright.getOp() == Operator.const:
480ans.constant *= right.number
482ans.children.append(right)
510 ifexpo.getOp() != Operator.const:
511 raiseNotImplementedError(
"exponents must be numbers")
512 ifself.
getOp() == Operator.const:
513 return Constant(self.number**expo.number)
515ans.children.append(self)
516ans.expo = expo.number
524 ifdivisor.getOp() == Operator.const
anddivisor.number == 0.0:
525 raiseZeroDivisionError(
"cannot divide by 0")
526 returnself * divisor**(-1)
531 returnotherexpr.__truediv__(self)
537 returnself + (-other)
546 return-1.0 * self + other
549 '''turn it into a constraint''' 550 return_expr_richcmp(self, other, op)
553 '''Note: none of these expressions should be polynomial''' 554 returnfloat(
'inf')
557 '''returns operator of GenExpr''' 571self.
_op= Operator.add
573 returnself.
_op+
"("+ str(self.
constant) +
","+
",".join(map(
lambdachild : child.__repr__(), self.
children)) +
")" 581self.
_op= Operator.prod
583 returnself.
_op+
"("+ str(self.
constant) +
","+
",".join(map(
lambdachild : child.__repr__(), self.
children)) +
")" 590self.
_op= Operator.varidx
600self.
_op= Operator.power
618self.
_op= Operator.const
624 """returns expression with exp-function""" 627 """returns expression with log-function""" 630 """returns expression with sqrt-function""" 633 """returns expression with sin-function""" 636 """returns expression with cos-function""" 640 '''transforms tree to an array of nodes. each node is an operator and the position of the 641 children of that operator (i.e. the other nodes) in the array''' 642 assertisinstance(expr, GenExpr)
648 """adds a given value to an array""" 649nodes.append(tuple([
'const', [val]]))
650 returnlen(nodes) - 1
658 """adds expression to array""" 660 ifop == Operator.const:
661nodes.append(tuple([op, [expr.number]]))
662 elifop != Operator.varidx:
664nchildren = len(expr.children)
665 forchild
inexpr.children:
668 ifop == Operator.power:
671 elif(op == Operator.add
andexpr.constant != 0.0)
or(op == Operator.prod
andexpr.constant != 1.0):
674nodes.append( tuple( [op, indices] ) )
676nodes.append( tuple( [op, expr.children] ) )
677 returnlen(nodes) - 1
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4