X-Git-Url: https://scm.cri.mines-paristech.fr/git/linpy.git/blobdiff_plain/dbe638f61f1927ee6f3dffaaf2dc34418725f50a..98edd00eb4b05e85f7cb1b85cff2f4d733909c57:/doc/tutorial.rst diff --git a/doc/tutorial.rst b/doc/tutorial.rst new file mode 100644 index 0000000..8598cbd --- /dev/null +++ b/doc/tutorial.rst @@ -0,0 +1,116 @@ + +.. _tutorial: + +Tutorial +======== + +Polyhedra +--------- + +The following example shows how we can manipulate polyhedra using LinPy. +Let us define two square polyhedra, corresponding to the sets ``square1 = {(x, y) | 0 <= x <= 2, 0 <= y <= 2}`` and ``square2 = {(x, y) | 2 <= x <= 4, 2 <= y <= 4}``. +First, we need define the symbols used, for instance with the :func:`symbols` function. + +>>> from linpy import * +>>> x, y = symbols('x y') + +Then, we can build the :class:`Polyhedron` object ``square1`` from its constraints: + +>>> square1 = Le(0, x, 2) & Le(0, y, 2) +>>> square1 +And(Ge(x, 0), Ge(-x + 2, 0), Ge(y, 0), Ge(-y + 2, 0)) + +LinPy provides comparison functions :func:`Lt`, :func:`Le`, :func:`Eq`, :func:`Ne`, :func:`Ge` and :func:`Gt` to build constraints, and logical operators :func:`And`, :func:`Or`, :func:`Not` to combine them. +Alternatively, a polyhedron can be built from a string: + +>>> square2 = Polyhedron('1 <= x <= 3, 1 <= y <= 3') +>>> square2 +And(Ge(x - 1, 0), Ge(-x + 3, 0), Ge(y - 1, 0), Ge(-y + 3, 0)) + +The usual polyhedral operations are available, including intersection: + +>>> inter = square1.intersection(square2) +>>> inter +And(Ge(x - 1, 0), Ge(-x + 2, 0), Ge(y - 1, 0), Ge(-y + 2, 0)) + +convex union: + +>>> hull = square1.convex_union(square2) +>>> hull +And(Ge(x, 0), Ge(y, 0), Ge(-x + y + 2, 0), Ge(x - y + 2, 0), Ge(-x + 3, 0), Ge(-y + 3, 0)) + +and projection: + +>>> square1.project([y]) +And(Ge(x, 0), Ge(-x + 2, 0)) + +Equality and inclusion tests are also provided. +Special values :data:`Empty` and :data:`Universe` represent the empty and universe polyhedra. + +>>> inter <= square1 +True +>>> inter == Empty +False + + +Domains +------- + +LinPy is also able to manipulate polyhedral *domains*, that is, unions of polyhedra. +An example of domain is the set union (as opposed to convex union) of polyhedra ``square1`` and ``square2``. +The result is a :class:`Domain` object. + +>>> union = square1 | square2 +>>> union +Or(And(Ge(-x + 2, 0), Ge(x, 0), Ge(-y + 2, 0), Ge(y, 0)), And(Ge(-x + 3, 0), Ge(x - 1, 0), Ge(-y + 3, 0), Ge(y - 1, 0))) +>>> union <= hull +True + +Unlike polyhedra, domains allow exact computation of union, subtraction and complementary operations. + +>>> diff = square1 - square2 +>>> diff +Or(And(Eq(x, 0), Ge(y, 0), Ge(-y + 2, 0)), And(Eq(y, 0), Ge(x - 1, 0), Ge(-x + 2, 0))) +>>> ~square1 +Or(Ge(-x - 1, 0), Ge(x - 3, 0), And(Ge(x, 0), Ge(-x + 2, 0), Ge(-y - 1, 0)), And(Ge(x, 0), Ge(-x + 2, 0), Ge(y - 3, 0))) + + +Plotting +-------- + +LinPy can use the :mod:`matplotlib` plotting library, if available, to plot bounded polyhedra and domains. + +>>> import matplotlib.pyplot as plt +>>> from matplotlib import pylab +>>> fig = plt.figure() +>>> plot = fig.add_subplot(1, 1, 1, aspect='equal') +>>> square1.plot(plot, facecolor='red', alpha=0.3) +>>> square2.plot(plot, facecolor='blue', alpha=0.3) +>>> hull.plot(plot, facecolor='blue', alpha=0.3) +>>> pylab.show() + +Note that you can pass a plot object to the :meth:`Domain.plot` method, which provides great flexibility. +Also, keyword arguments can be passed such as color and the degree of transparency of a polygon. + +.. figure:: images/union.jpg + :align: center + +3D plots are also supported. + +>>> import matplotlib.pyplot as plt +>>> from matplotlib import pylab +>>> from mpl_toolkits.mplot3d import Axes3D +>>> from linpy import * +>>> x, y, z = symbols('x y z') +>>> fig = plt.figure() +>>> plot = fig.add_subplot(1, 1, 1, projection='3d', aspect='equal') +>>> plot.set_title('Chamfered cube') +>>> poly = Le(0, x, 3) & Le(0, y, 3) & Le(0, z, 3) & \ + Le(z - 2, x) & Le(x, z + 2) & Le(1 - z, x) & Le(x, 5 - z) & \ + Le(z - 2, y) & Le(y, z + 2) & Le(1 - z, y) & Le(y, 5 - z) & \ + Le(y - 2, x) & Le(x, y + 2) & Le(1 - y, x) & Le(x, 5 - y) +>>> poly.plot(plot, facecolor='red', alpha=0.75) +>>> pylab.show() + +.. figure:: images/cham_cube.jpg + :align: center