Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
### Changed
- Speed up `constant * Expr` via C-level API
- Speed up `Term.__eq__` via the C-level API
- Move magic methods (`__radd__`, `__sub__`, `__rsub__`, `__rmul__`, `__richcmp__`, `__neg__`, and `__rtruediv__`) to `ExprLike` base class
### Removed
- Removed outdated warning about Make build system incompatibility
- Removed `Term.ptrtuple` to optimize `Term` memory usage
Expand Down
69 changes: 21 additions & 48 deletions src/pyscipopt/expr.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,27 @@ cdef class ExprLike:

return NotImplemented

def __radd__(self, other, /):
return self + other

def __sub__(self, other, /):
return self + (-other)

def __rsub__(self, other, /):
return (-self) + other

def __rmul__(self, other, /):
return self * other

def __rtruediv__(self, other, /):
return buildGenExprObj(other) / self

def __richcmp__(self, other, int op):
return _expr_richcmp(self, other, op)

def __neg__(self):
return self * -1.0

def __abs__(self) -> GenExpr:
return UnaryExpr(Operator.fabs, buildGenExprObj(self))

Expand Down Expand Up @@ -383,10 +404,6 @@ cdef class Expr(ExprLike):
selfexpr = buildGenExprObj(self)
return selfexpr.__truediv__(other)

def __rtruediv__(self, other):
''' other / self '''
return buildGenExprObj(other) / self

def __pow__(self, other, modulo):
if float(other).is_integer() and other >= 0:
exp = int(other)
Expand All @@ -411,25 +428,6 @@ cdef class Expr(ExprLike):
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()})

def __sub__(self, other):
return self + (-other)

def __radd__(self, other):
return self.__add__(other)

def __rmul__(self, other):
return self.__mul__(other)

def __rsub__(self, other):
return -1.0 * self + other

def __richcmp__(self, other, op):
'''turn it into a constraint'''
return _expr_richcmp(self, other, op)

def normalize(self):
'''remove terms with coefficient of 0'''
self.terms = {t:c for (t,c) in self.terms.items() if c != 0.0}
Expand Down Expand Up @@ -488,7 +486,6 @@ cdef class ExprCons:
if not self._rhs is None:
self._rhs -= c


def __richcmp__(self, other, op):
'''turn it into a constraint'''
if op == 1: # <=
Expand Down Expand Up @@ -715,30 +712,6 @@ cdef class GenExpr(ExprLike):
raise ZeroDivisionError("cannot divide by 0")
return self * divisor**(-1)

def __rtruediv__(self, other):
''' other / self '''
otherexpr = buildGenExprObj(other)
return otherexpr.__truediv__(self)

def __neg__(self):
return -1.0 * self

def __sub__(self, other):
return self + (-other)

def __radd__(self, other):
return self.__add__(other)

def __rmul__(self, other):
return self.__mul__(other)

def __rsub__(self, other):
return -1.0 * self + other

def __richcmp__(self, other, op):
'''turn it into a constraint'''
return _expr_richcmp(self, other, op)

def degree(self):
'''Note: none of these expressions should be polynomial'''
return float('inf')
Expand Down
20 changes: 6 additions & 14 deletions src/pyscipopt/scip.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,12 @@ class ExprLike:
*args: Incomplete,
**kwargs: Incomplete,
) -> Incomplete: ...
def __radd__(self, other: Incomplete, /) -> Incomplete: ...
def __sub__(self, other: Incomplete, /) -> Incomplete: ...
def __rsub__(self, other: Incomplete, /) -> Incomplete: ...
def __rmul__(self, other: Incomplete, /) -> Incomplete: ...
def __rtruediv__(self, other: Incomplete, /) -> Incomplete: ...
def __neg__(self) -> Incomplete: ...
def __abs__(self) -> GenExpr: ...
def exp(self) -> GenExpr: ...
def log(self) -> GenExpr: ...
Expand All @@ -346,7 +352,6 @@ class Expr(ExprLike):
def __init__(self, terms: Incomplete = ...) -> None: ...
def degree(self) -> Incomplete: ...
def normalize(self) -> Incomplete: ...
def __abs__(self) -> GenExpr: ...
def __add__(self, other: Incomplete, /) -> Incomplete: ...
def __eq__(self, other: object, /) -> bool: ...
def __ge__(self, other: object, /) -> bool: ...
Expand All @@ -358,14 +363,8 @@ class Expr(ExprLike):
def __lt__(self, other: object, /) -> bool: ...
def __mul__(self, other: Incomplete, /) -> Incomplete: ...
def __ne__(self, other: object, /) -> bool: ...
def __neg__(self) -> Incomplete: ...
def __pow__(self, other: Incomplete, modulo: Incomplete = ..., /) -> Incomplete: ...
def __radd__(self, other: Incomplete, /) -> Incomplete: ...
def __rmul__(self, other: Incomplete, /) -> Incomplete: ...
def __rpow__(self, other: Incomplete, /) -> Incomplete: ...
def __rsub__(self, other: Incomplete, /) -> Incomplete: ...
def __rtruediv__(self, other: Incomplete, /) -> Incomplete: ...
def __sub__(self, other: Incomplete, /) -> Incomplete: ...
def __truediv__(self, other: Incomplete, /) -> Incomplete: ...

@disjoint_base
Expand All @@ -392,7 +391,6 @@ class GenExpr(ExprLike):
def __init__(self) -> None: ...
def degree(self) -> Incomplete: ...
def getOp(self) -> Incomplete: ...
def __abs__(self) -> GenExpr: ...
def __add__(self, other: Incomplete, /) -> Incomplete: ...
def __eq__(self, other: object, /) -> bool: ...
def __ge__(self, other: object, /) -> bool: ...
Expand All @@ -401,14 +399,8 @@ class GenExpr(ExprLike):
def __lt__(self, other: object, /) -> bool: ...
def __mul__(self, other: Incomplete, /) -> Incomplete: ...
def __ne__(self, other: object, /) -> bool: ...
def __neg__(self) -> Incomplete: ...
def __pow__(self, other: Incomplete, modulo: Incomplete = ..., /) -> Incomplete: ...
def __radd__(self, other: Incomplete, /) -> Incomplete: ...
def __rmul__(self, other: Incomplete, /) -> Incomplete: ...
def __rpow__(self, other: Incomplete, /) -> Incomplete: ...
def __rsub__(self, other: Incomplete, /) -> Incomplete: ...
def __rtruediv__(self, other: Incomplete, /) -> Incomplete: ...
def __sub__(self, other: Incomplete, /) -> Incomplete: ...
def __truediv__(self, other: Incomplete, /) -> Incomplete: ...

@disjoint_base
Expand Down
Loading