Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased
### Added
- Added possibility of having variables in exponent.
- Added basic type stubs to help with IDE autocompletion and type checking.
### Fixed
- Implemented all binary operations between MatrixExpr and GenExpr
Expand Down
26 changes: 26 additions & 0 deletions src/pyscipopt/expr.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,19 @@ cdef class Expr:
res *= self
return res

def __rpow__(self, other):
"""
Implements base**x as scip.exp(x * scip.log(base)).
Note: base must be positive.
"""
if _is_number(other):
base = float(other)
if base <= 0.0:
raise ValueError("Base of a**x must be positive, as expression is reformulated to scip.exp(x * scip.log(a)); got %g" % base)
return exp(self * log(base))
else:
raise TypeError(f"Unsupported base type {type(other)} for exponentiation.")

def __neg__(self):
return Expr({v:-c for v,c in self.terms.items()})

Expand Down Expand Up @@ -544,6 +557,19 @@ cdef class GenExpr:

return ans

def __rpow__(self, other):
"""
Implements base**x as scip.exp(x * scip.log(base)).
Note: base must be positive.
"""
if _is_number(other):
base = float(other)
if base <= 0.0:
raise ValueError("Base of a**x must be positive, as expression is reformulated to scip.exp(x * scip.log(a)); got %g" % base)
return exp(self * log(base))
else:
raise TypeError(f"Unsupported base type {type(other)} for exponentiation.")

#TODO: ipow, idiv, etc
def __truediv__(self,other):
divisor = buildGenExprObj(other)
Expand Down
11 changes: 11 additions & 0 deletions tests/test_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,14 @@ def test_equation(model):
assert isinstance(equat.expr, GenExpr)
assert equat._lhs == equat._rhs
assert equat._lhs == 0.0

def test_rpow_constant_base(model):
m, x, y, z = model
a = 2**x
b = exp(x * log(2.0))
assert isinstance(a, GenExpr)
assert repr(a) == repr(b) # Structural equality is not implemented; compare strings
m.addCons(2**x <= 1)

with pytest.raises(ValueError):
c = (-2)**x
Loading