13 *Symbols* are the basic components to build expressions and constraints.
14 They correspond to mathematical variables.
16 .. class:: Symbol(name)
18 Return a symbol with the name string given in argument.
19 Alternatively, the function :func:`symbols` allows to create several symbols at once.
20 Symbols are instances of class :class:`LinExpr` and inherit its functionalities.
26 Two instances of :class:`Symbol` are equal if they have the same name.
30 The name of the symbol.
34 Return a new :class:`Dummy` symbol instance with the same name.
38 Return a sorting key for the symbol.
39 It is useful to sort a list of symbols in a consistent order, as comparison functions are overridden (see the documentation of class :class:`LinExpr`).
41 >>> sort(symbols, key=Symbol.sortkey)
44 .. function:: symbols(names)
46 This function returns a tuple of symbols whose names are taken from a comma or whitespace delimited string, or a sequence of strings.
47 It is useful to define several symbols at once.
49 >>> x, y = symbols('x y')
50 >>> x, y = symbols('x, y')
51 >>> x, y = symbols(['x', 'y'])
54 Sometimes you need to have a unique symbol. For example, you might need a temporary one in some calculation, which is going to be substituted for something else at the end anyway.
55 This is achieved using ``Dummy('x')``.
57 .. class:: Dummy(name=None)
59 A variation of :class:`Symbol` in which all symbols are unique and identified by an internal count index.
60 If a name is not supplied then a string value of the count index will be used.
61 This is useful when a unique, temporary variable is needed and the name of the variable used in the expression is not important.
63 Unlike :class:`Symbol`, :class:`Dummy` instances with the same name are not equal:
66 >>> x1, x2 = Dummy('x'), Dummy('x')
75 .. _reference_linexprs:
80 A *linear expression* consists of a list of coefficient-variable pairs that capture the linear terms, plus a constant term.
81 Linear expressions are used to build constraints. They are temporary objects that typically have short lifespans.
83 Linear expressions are generally built using overloaded operators.
84 For example, if ``x`` is a :class:`Symbol`, then ``x + 1`` is an instance of :class:`LinExpr`.
86 .. class:: LinExpr(coefficients=None, constant=0)
89 Return a linear expression from a dictionary or a sequence, that maps symbols to their coefficients, and a constant term.
90 The coefficients and the constant term must be rational numbers.
92 For example, the linear expression ``x + 2*y + 1`` can be constructed using one of the following instructions:
94 >>> x, y = symbols('x y')
95 >>> LinExpr({x: 1, y: 2}, 1)
96 >>> LinExpr([(x, 1), (y, 2)], 1)
98 However, it may be easier to use overloaded operators:
100 >>> x, y = symbols('x y')
103 Alternatively, linear expressions can be constructed from a string:
105 >>> LinExpr('x + 2y + 1')
107 :class:`LinExpr` instances are hashable, and should be treated as immutable.
109 A linear expression with a single symbol of coefficient 1 and no constant term is automatically subclassed as a :class:`Symbol` instance.
110 A linear expression with no symbol, only a constant term, is automatically subclassed as a :class:`Rational` instance.
112 .. method:: coefficient(symbol)
115 Return the coefficient value of the given symbol, or ``0`` if the symbol does not appear in the expression.
117 .. method:: coefficients()
119 Iterate over the pairs ``(symbol, value)`` of linear terms in the expression.
120 The constant term is ignored.
122 .. attribute:: constant
124 The constant term of the expression.
126 .. attribute:: symbols
128 The tuple of symbols present in the expression, sorted according to :meth:`Symbol.sortkey`.
130 .. attribute:: dimension
132 The dimension of the expression, i.e. the number of symbols present in it.
134 .. method:: isconstant()
136 Return ``True`` if the expression only consists of a constant term.
137 In this case, it is a :class:`Rational` instance.
139 .. method:: issymbol()
141 Return ``True`` if an expression only consists of a symbol with coefficient ``1``.
142 In this case, it is a :class:`Symbol` instance.
146 Iterate over the coefficient values in the expression, and the constant term.
148 .. method:: __add__(expr)
150 Return the sum of two linear expressions.
152 .. method:: __sub__(expr)
154 Return the difference between two linear expressions.
156 .. method:: __mul__(value)
158 Return the product of the linear expression by a rational.
160 .. method:: __truediv__(value)
162 Return the quotient of the linear expression by a rational.
164 .. method:: __eq__(expr)
166 Test whether two linear expressions are equal.
167 Unlike methods :meth:`LinExpr.__lt__`, :meth:`LinExpr.__le__`, :meth:`LinExpr.__ge__`, :meth:`LinExpr.__gt__`, the result is a boolean value, not a polyhedron.
168 To express that two linear expressions are equal or not equal, use functions :func:`Eq` and :func:`Ne` instead.
170 As explained below, it is possible to create polyhedra from linear expressions using comparison methods.
172 .. method:: __lt__(expr)
177 Create a new :class:`Polyhedron` instance whose unique constraint is the comparison between two linear expressions.
178 As an alternative, functions :func:`Lt`, :func:`Le`, :func:`Ge` and :func:`Gt` can be used.
180 >>> x, y = symbols('x y')
184 .. method:: scaleint()
186 Return the expression multiplied by its lowest common denominator to make all values integer.
188 .. method:: subs(symbol, expression)
191 Substitute the given symbol by an expression and return the resulting expression.
192 Raise :exc:`TypeError` if the resulting expression is not linear.
194 >>> x, y = symbols('x y')
199 To perform multiple substitutions at once, pass a sequence or a dictionary of ``(old, new)`` pairs to ``subs``.
201 >>> e.subs({x: y, y: x})
204 .. classmethod:: fromstring(string)
206 Create an expression from a string.
207 Raise :exc:`SyntaxError` if the string is not properly formatted.
209 There are also methods to convert linear expressions to and from `SymPy <http://sympy.org>`_ expressions:
211 .. classmethod:: fromsympy(expr)
213 Create a linear expression from a :mod:`sympy` expression.
214 Raise :exc:`TypeError` is the :mod:`sympy` expression is not linear.
216 .. method:: tosympy()
218 Convert the linear expression to a sympy expression.
221 Apart from :mod:`Symbol`, a particular case of linear expressions are rational values, i.e. linear expressions consisting only of a constant term, with no symbol.
222 They are implemented by the :class:`Rational` class, that inherits from both :class:`LinExpr` and :class:`fractions.Fraction` classes.
224 .. class:: Rational(numerator, denominator=1)
227 The first version requires that the *numerator* and *denominator* are instances of :class:`numbers.Rational` and returns a new :class:`Rational` instance with the value ``numerator/denominator``.
228 If the denominator is ``0``, it raises a :exc:`ZeroDivisionError`.
229 The other version of the constructor expects a string.
230 The usual form for this instance is::
232 [sign] numerator ['/' denominator]
234 where the optional ``sign`` may be either '+' or '-' and the ``numerator`` and ``denominator`` (if present) are strings of decimal digits.
236 See the documentation of :class:`fractions.Fraction` for more information and examples.
239 .. _reference_polyhedra:
244 A *convex polyhedron* (or simply "polyhedron") is the space defined by a system of linear equalities and inequalities.
245 This space can be unbounded.
247 .. class:: Polyhedron(equalities, inequalities)
249 Polyhedron(geometric object)
251 Return a polyhedron from two sequences of linear expressions: *equalities* is a list of expressions equal to ``0``, and *inequalities* is a list of expressions greater or equal to ``0``.
252 For example, the polyhedron ``0 <= x <= 2, 0 <= y <= 2`` can be constructed with:
254 >>> x, y = symbols('x y')
255 >>> square1 = Polyhedron([], [x, 2 - x, y, 2 - y])
257 And(0 <= x, x <= 2, 0 <= y, y <= 2)
259 It may be easier to use comparison operators :meth:`LinExpr.__lt__`, :meth:`LinExpr.__le__`, :meth:`LinExpr.__ge__`, :meth:`LinExpr.__gt__`, or functions :func:`Lt`, :func:`Le`, :func:`Eq`, :func:`Ge` and :func:`Gt`, using one of the following instructions:
261 >>> x, y = symbols('x y')
262 >>> square1 = (0 <= x) & (x <= 2) & (0 <= y) & (y <= 2)
263 >>> square1 = Le(0, x, 2) & Le(0, y, 2)
265 It is also possible to build a polyhedron from a string.
267 >>> square1 = Polyhedron('0 <= x <= 2, 0 <= y <= 2')
269 Finally, a polyhedron can be constructed from a :class:`GeometricObject` instance, calling the :meth:`GeometricObject.aspolyedron` method.
270 This way, it is possible to compute the polyhedral hull of a :class:`Domain` instance, i.e., the convex hull of two polyhedra:
272 >>> square1 = Polyhedron('0 <= x <= 2, 0 <= y <= 2')
273 >>> square2 = Polyhedron('1 <= x <= 3, 1 <= y <= 3')
274 >>> Polyhedron(square1 | square2)
275 And(0 <= x, 0 <= y, x <= y + 2, y <= x + 2, x <= 3, y <= 3)
277 A polyhedron is a :class:`Domain` instance, and, therefore, inherits the functionalities of this class.
278 It is also a :class:`GeometricObject` instance.
280 .. attribute:: equalities
282 The tuple of equalities.
283 This is a list of :class:`LinExpr` instances that are equal to ``0`` in the polyhedron.
285 .. attribute:: inequalities
287 The tuple of inequalities.
288 This is a list of :class:`LinExpr` instances that are greater or equal to ``0`` in the polyhedron.
290 .. attribute:: constraints
292 The tuple of constraints, i.e., equalities and inequalities.
293 This is semantically equivalent to: ``equalities + inequalities``.
295 .. method:: convex_union(polyhedron[, ...])
297 Return the convex union of two or more polyhedra.
299 .. method:: asinequalities()
301 Express the polyhedron using inequalities, given as a list of expressions greater or equal to 0.
303 .. method:: widen(polyhedron)
305 Compute the *standard widening* of two polyhedra, à la Halbwachs.
307 In its current implementation, this method is slow and should not be used on large polyhedra.
312 The empty polyhedron, whose set of constraints is not satisfiable.
316 The universe polyhedron, whose set of constraints is always satisfiable, i.e. is empty.
319 .. _reference_domains:
324 A *domain* is a union of polyhedra.
325 Unlike polyhedra, domains allow exact computation of union, subtraction and complementary operations.
327 .. class:: Domain(*polyhedra)
329 Domain(geometric object)
331 Return a domain from a sequence of polyhedra.
333 >>> square1 = Polyhedron('0 <= x <= 2, 0 <= y <= 2')
334 >>> square2 = Polyhedron('1 <= x <= 3, 1 <= y <= 3')
335 >>> dom = Domain(square1, square2)
337 Or(And(x <= 2, 0 <= x, y <= 2, 0 <= y), And(x <= 3, 1 <= x, y <= 3, 1 <= y))
339 It is also possible to build domains from polyhedra using arithmetic operators :meth:`Domain.__or__`, :meth:`Domain.__invert__` or functions :func:`Or` and :func:`Not`, using one of the following instructions:
341 >>> dom = square1 | square2
342 >>> dom = Or(square1, square2)
344 Alternatively, a domain can be built from a string:
346 >>> dom = Domain('0 <= x <= 2, 0 <= y <= 2; 1 <= x <= 3, 1 <= y <= 3')
348 Finally, a domain can be built from a :class:`GeometricObject` instance, calling the :meth:`GeometricObject.asdomain` method.
350 A domain is also a :class:`GeometricObject` instance.
351 A domain with a unique polyhedron is automatically subclassed as a :class:`Polyhedron` instance.
353 .. attribute:: polyhedra
355 The tuple of polyhedra present in the domain.
357 .. attribute:: symbols
359 The tuple of symbols present in the domain equations, sorted according to :meth:`Symbol.sortkey`.
361 .. attribute:: dimension
363 The dimension of the domain, i.e. the number of symbols present in it.
365 .. method:: isempty()
367 Return ``True`` if the domain is empty, that is, equal to :data:`Empty`.
369 .. method:: __bool__()
371 Return ``True`` if the domain is non-empty.
373 .. method:: isuniverse()
375 Return ``True`` if the domain is universal, that is, equal to :data:`Universe`.
377 .. method:: isbounded()
379 Return ``True`` is the domain is bounded.
381 .. method:: __eq__(domain)
383 Return ``True`` if two domains are equal.
385 .. method:: isdisjoint(domain)
387 Return ``True`` if two domains have a null intersection.
389 .. method:: issubset(domain)
392 Report whether another domain contains the domain.
394 .. method:: __lt__(domain)
396 Report whether another domain is contained within the domain.
398 .. method:: complement()
401 Return the complementary domain of the domain.
403 .. method:: make_disjoint()
405 Return an equivalent domain, whose polyhedra are disjoint.
407 .. method:: coalesce()
409 Simplify the representation of the domain by trying to combine pairs of polyhedra into a single polyhedron, and return the resulting domain.
411 .. method:: detect_equalities()
413 Simplify the representation of the domain by detecting implicit equalities, and return the resulting domain.
415 .. method:: remove_redundancies()
417 Remove redundant constraints in the domain, and return the resulting domain.
419 .. method:: project(symbols)
421 Project out the sequence of symbols given in arguments, and return the resulting domain.
425 Return a sample of the domain, as an integer instance of :class:`Point`.
426 If the domain is empty, a :exc:`ValueError` exception is raised.
428 .. method:: intersection(domain[, ...])
431 Return the intersection of two or more domains as a new domain.
432 As an alternative, function :func:`And` can be used.
434 .. method:: union(domain[, ...])
438 Return the union of two or more domains as a new domain.
439 As an alternative, function :func:`Or` can be used.
441 .. method:: difference(domain)
444 Return the difference between two domains as a new domain.
448 Return the lexicographic minimum of the elements in the domain.
452 Return the lexicographic maximum of the elements in the domain.
454 .. method:: vertices()
456 Return the vertices of the domain, as a list of rational instances of :class:`Point`.
460 Return the integer points of a bounded domain, as a list of integer instances of :class:`Point`.
461 If the domain is not bounded, a :exc:`ValueError` exception is raised.
463 .. method:: __contains__(point)
465 Return ``True`` if the point is contained within the domain.
469 Return the list of faces of a bounded domain.
470 Each face is represented by a list of vertices, in the form of rational instances of :class:`Point`.
471 If the domain is not bounded, a :exc:`ValueError` exception is raised.
473 .. method:: plot(plot=None, **options)
475 Plot a 2D or 3D domain using `matplotlib <http://matplotlib.org/>`_.
476 Draw it to the current *plot* object if present, otherwise create a new one.
477 *options* are keyword arguments passed to the matplotlib drawing functions, they can be used to set the drawing color for example.
478 Raise :exc:`ValueError` is the domain is not 2D or 3D.
480 .. method:: subs(symbol, expression)
483 Substitute the given symbol by an expression in the domain constraints.
484 To perform multiple substitutions at once, pass a sequence or a dictionary of ``(old, new)`` pairs to ``subs``.
485 The syntax of this function is similar to :func:`LinExpr.subs`.
487 .. classmethod:: fromstring(string)
489 Create a domain from a string.
490 Raise :exc:`SyntaxError` if the string is not properly formatted.
492 There are also methods to convert a domain to and from `SymPy <http://sympy.org>`_ expressions:
494 .. classmethod:: fromsympy(expr)
496 Create a domain from a sympy expression.
498 .. method:: tosympy()
500 Convert the domain to a sympy expression.
503 .. _reference_operators:
505 Comparison and Logic Operators
506 ------------------------------
508 The following functions create :class:`Polyhedron` or :class:`Domain` instances using the comparisons of two or more :class:`LinExpr` instances:
510 .. function:: Lt(expr1, expr2[, expr3, ...])
512 Create the polyhedron with constraints ``expr1 < expr2 < expr3 ...``.
514 .. function:: Le(expr1, expr2[, expr3, ...])
516 Create the polyhedron with constraints ``expr1 <= expr2 <= expr3 ...``.
518 .. function:: Eq(expr1, expr2[, expr3, ...])
520 Create the polyhedron with constraints ``expr1 == expr2 == expr3 ...``.
522 .. function:: Ne(expr1, expr2[, expr3, ...])
524 Create the domain such that ``expr1 != expr2 != expr3 ...``.
525 The result is a :class:`Domain` object, not a :class:`Polyhedron`.
527 .. function:: Ge(expr1, expr2[, expr3, ...])
529 Create the polyhedron with constraints ``expr1 >= expr2 >= expr3 ...``.
531 .. function:: Gt(expr1, expr2[, expr3, ...])
533 Create the polyhedron with constraints ``expr1 > expr2 > expr3 ...``.
535 The following functions combine :class:`Polyhedron` or :class:`Domain` instances using logic operators:
537 .. function:: And(domain1, domain2[, ...])
539 Create the intersection domain of the domains given in arguments.
541 .. function:: Or(domain1, domain2[, ...])
543 Create the union domain of the domains given in arguments.
545 .. function:: Not(domain)
547 Create the complementary domain of the domain given in argument.
550 .. _reference_geometry:
555 .. class:: GeometricObject
557 :class:`GeometricObject` is an abstract class to represent objects with a geometric representation in space.
558 Subclasses of :class:`GeometricObject` are :class:`Polyhedron`, :class:`Domain` and :class:`Point`.
559 The following elements must be provided:
561 .. attribute:: symbols
563 The tuple of symbols present in the object expression, sorted according to :class:`Symbol.sortkey()`.
565 .. attribute:: dimension
567 The dimension of the object, i.e. the number of symbols present in it.
569 .. method:: aspolyedron()
571 Return a :class:`Polyhedron` object that approximates the geometric object.
573 .. method:: asdomain()
575 Return a :class:`Domain` object that approximates the geometric object.
577 .. class:: Point(coordinates)
579 Create a point from a dictionary or a sequence that maps the symbols to their coordinates.
580 Coordinates must be rational numbers.
582 For example, the point ``(x: 1, y: 2)`` can be constructed using one of the following instructions:
584 >>> x, y = symbols('x y')
585 >>> p = Point({x: 1, y: 2})
586 >>> p = Point([(x, 1), (y, 2)])
588 :class:`Point` instances are hashable and should be treated as immutable.
590 A point is a :class:`GeometricObject` instance.
592 .. attribute:: symbols
594 The tuple of symbols present in the point, sorted according to :class:`Symbol.sortkey()`.
596 .. attribute:: dimension
598 The dimension of the point, i.e. the number of symbols present in it.
600 .. method:: coordinate(symbol)
603 Return the coordinate value of the given symbol.
604 Raise :exc:`KeyError` if the symbol is not involved in the point.
606 .. method:: coordinates()
608 Iterate over the pairs ``(symbol, value)`` of coordinates in the point.
612 Iterate over the coordinate values in the point.
614 .. method:: isorigin()
616 Return ``True`` if all coordinates are ``0``.
618 .. method:: __bool__()
620 Return ``True`` if not all coordinates are ``0``.
622 .. method:: __add__(vector)
624 Translate the point by a :class:`Vector` object and return the resulting point.
626 .. method:: __sub__(point)
629 The first version substracts a point from another and returns the resulting vector.
630 The second version translates the point by the opposite vector of *vector* and returns the resulting point.
632 .. method:: __eq__(point)
634 Test whether two points are equal.
637 .. class:: Vector(coordinates)
638 Vector(point1, point2)
640 The first version creates a vector from a dictionary or a sequence that maps the symbols to their coordinates, similarly to :meth:`Point`.
641 The second version creates a vector between two points.
643 :class:`Vector` instances are hashable and should be treated as immutable.
645 .. attribute:: symbols
647 The tuple of symbols present in the point, sorted according to :class:`Symbol.sortkey()`.
649 .. attribute:: dimension
651 The dimension of the point, i.e. the number of symbols present in it.
653 .. method:: coordinate(symbol)
656 Return the coordinate value of the given symbol.
657 Raise :exc:`KeyError` if the symbol is not involved in the point.
659 .. method:: coordinates()
661 Iterate over the pairs ``(symbol, value)`` of coordinates in the point.
665 Iterate over the coordinate values in the point.
669 Return ``True`` if all coordinates are ``0``.
671 .. method:: __bool__()
673 Return ``True`` if not all coordinates are ``0``.
675 .. method:: __add__(point)
678 The first version translates the point *point* to the vector and returns the resulting point.
679 The second version adds vector *vector* to the vector and returns the resulting vector.
681 .. method:: __sub__(point)
684 The first version substracts a point from a vector and returns the resulting point.
685 The second version returns the difference vector between two vectors.
687 .. method:: __neg__()
689 Return the opposite vector.
691 .. method:: __mul__(value)
693 Multiply the vector by a scalar value and return the resulting vector.
695 .. method:: __truediv__(value)
697 Divide the vector by a scalar value and return the resulting vector.
699 .. method:: __eq__(vector)
701 Test whether two vectors are equal.
703 .. method:: angle(vector)
705 Retrieve the angle required to rotate the vector into the vector passed in argument.
706 The result is an angle in radians, ranging between ``-pi`` and ``pi``.
708 .. method:: cross(vector)
710 Compute the cross product of two 3D vectors.
711 If either one of the vectors is not three-dimensional, a :exc:`ValueError` exception is raised.
713 .. method:: dot(vector)
715 Compute the dot product of two vectors.
719 Return the norm of the vector.
723 Return the squared norm of the vector.
727 Return the normalized vector, i.e. the vector of same direction but with norm 1.