+ return Polyhedron(inequalities=[(self - other)._toint() - 1])
+
+ @classmethod
+ def fromsympy(cls, expr):
+ import sympy
+ coefficients = {}
+ constant = 0
+ for symbol, coefficient in expr.as_coefficients_dict().items():
+ coefficient = Fraction(coefficient.p, coefficient.q)
+ if symbol == sympy.S.One:
+ constant = coefficient
+ elif isinstance(symbol, sympy.Symbol):
+ symbol = symbol.name
+ coefficients[symbol] = coefficient
+ else:
+ raise ValueError('non-linear expression: {!r}'.format(expr))
+ return cls(coefficients, constant)
+
+ def tosympy(self):
+ import sympy
+ expr = 0
+ for symbol, coefficient in self.coefficients():
+ term = coefficient * sympy.Symbol(symbol)
+ expr += term
+ expr += self.constant
+ return expr
+
+
+class Constant(Expression):
+
+ def __new__(cls, numerator=0, denominator=None):
+ self = object().__new__(cls)
+ if denominator is None:
+ if isinstance(numerator, numbers.Rational):
+ self._constant = numerator
+ elif isinstance(numerator, Constant):
+ self._constant = numerator.constant
+ else:
+ raise TypeError('constant must be a rational number or a Constant instance')
+ else:
+ self._constant = Fraction(numerator, denominator)
+ self._coefficients = {}
+ self._symbols = ()
+ self._dimension = 0
+ return self
+
+ def isconstant(self):
+ return True
+
+ def __bool__(self):
+ return bool(self.constant)
+
+ def __repr__(self):
+ if self.constant.denominator == 1:
+ return '{}({!r})'.format(self.__class__.__name__, self.constant)
+ else:
+ return '{}({!r}, {!r})'.format(self.__class__.__name__,
+ self.constant.numerator, self.constant.denominator)
+
+ @classmethod
+ def fromsympy(cls, expr):
+ import sympy
+ if isinstance(expr, sympy.Rational):
+ return cls(expr.p, expr.q)
+ elif isinstance(expr, numbers.Rational):
+ return cls(expr)
+ else:
+ raise TypeError('expr must be a sympy.Rational instance')
+
+
+class Symbol(Expression):
+
+ __slots__ = Expression.__slots__ + (
+ '_name',
+ )
+
+ def __new__(cls, name):
+ if isinstance(name, Symbol):
+ name = name.name
+ elif not isinstance(name, str):
+ raise TypeError('name must be a string or a Symbol instance')
+ self = object().__new__(cls)
+ self._coefficients = {name: 1}
+ self._constant = 0
+ self._symbols = tuple(name)
+ self._name = name
+ self._dimension = 1
+ return self
+
+ @property
+ def name(self):
+ return self._name