Welcome to pplpy’s documentation!¶
Installation¶
pplpy is available from the Python Package Index. You can hence install it with:
$ pip install pplpy
The code source can be obtained from github:
$ git clone https://github.com/videlec/pplpy.git
Module documentation¶
Cython wrapper for the Parma Polyhedra Library (PPL)
The Parma Polyhedra Library (PPL) is a library for polyhedral computations over ,:math:mathbb{Q}. This interface tries to reproduce the C++ API as faithfully as possible in Python. For example, the following C++ excerpt:
Variable x(0);
Variable y(1);
Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x <= 3);
cs.insert(y >= 0);
cs.insert(y <= 3);
C_Polyhedron poly_from_constraints(cs);
translates into:
>>> from ppl import Variable, Constraint_System, C_Polyhedron
>>> x = Variable(0)
>>> y = Variable(1)
>>> cs = Constraint_System()
>>> cs.insert(x >= 0)
>>> cs.insert(x <= 3)
>>> cs.insert(y >= 0)
>>> cs.insert(y <= 3)
>>> poly_from_constraints = C_Polyhedron(cs)
The same polyhedron constructed from generators:
>>> from ppl import Variable, Generator_System, C_Polyhedron, point
>>> gs = Generator_System()
>>> gs.insert(point(0*x + 0*y))
>>> gs.insert(point(0*x + 3*y))
>>> gs.insert(point(3*x + 0*y))
>>> gs.insert(point(3*x + 3*y))
>>> poly_from_generators = C_Polyhedron(gs)
Rich comparisons test equality/inequality and strict/non-strict containment:
>>> poly_from_generators == poly_from_constraints
True
>>> poly_from_generators >= poly_from_constraints
True
>>> poly_from_generators < poly_from_constraints
False
>>> poly_from_constraints.minimized_generators()
Generator_System {point(0/1, 0/1), point(0/1, 3/1), point(3/1, 0/1), point(3/1, 3/1)}
>>> poly_from_constraints.minimized_constraints()
Constraint_System {-x0+3>=0, -x1+3>=0, x0>=0, x1>=0}
As we see above, the library is generally easy to use. There are a few pitfalls that are not entirely obvious without consulting the documentation, in particular:
There are no vectors used to describe
Generator(points, closure points, rays, lines) orConstraint(strict inequalities, non-strict inequalities, or equations). Coordinates are always specified via linear polynomials inVariableAll coordinates of rays and lines as well as all coefficients of constraint relations are (arbitrary precision) integers. Only the generators
point()andclosure_point()allow one to specify an overall divisor of the otherwise integral coordinates. For example:>>> from ppl import Variable, point >>> x = Variable(0); y = Variable(1) >>> p = point( 2*x+3*y, 5 ); p point(2/5, 3/5) >>> p.coefficient(x) 2 >>> p.coefficient(y) 3 >>> p.divisor() 5
PPL supports (topologically) closed polyhedra (
C_Polyhedron) as well as not neccesarily closed polyhedra (NNC_Polyhedron). Only the latter allows closure points (=points of the closure but not of the actual polyhedron) and strict inequalities (>and<)
The naming convention for the C++ classes is that they start with
PPL_, for example, the original Linear_Expression becomes
PPL_Linear_Expression. The Python wrapper has the same name as the
original library class, that is, just Linear_Expression. In short:
- If you are using the Python wrapper (if in doubt: thats you), then you use the same names as the PPL C++ class library.
- If you are writing your own Cython code, you can access the
underlying C++ classes by adding the prefix
PPL_.
Finally, PPL is fast. For example, here is the permutahedron of 5 basis vectors:
>>> from ppl import Variable, Generator_System, point, C_Polyhedron
>>> basis = range(0,5)
>>> x = [ Variable(i) for i in basis ]
>>> gs = Generator_System();
>>> from itertools import permutations
>>> for coeff in permutations(basis):
... gs.insert(point( sum( (coeff[i]+1)*x[i] for i in basis ) ))
>>> C_Polyhedron(gs)
A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 120 points
DIFFERENCES VS. C++
Since Python and C++ syntax are not always compatible, there are necessarily some differences. The main ones are:
- The
Linear_Expressionalso accepts an iterable as input for the homogeneous cooefficients. Polyhedronand its subclasses as well asGenerator_SystemandConstraint_Systemcan be set immutable via aset_immutable()method. This is the analog of declaring a C++ instanceconst. All other classes are immutable by themselves.
AUTHORS:
- Volker Braun (2010-10-08): initial version (within Sage).
- Risan (2012-02-19): extension for MIP_Problem class (within Sage)
- Vincent Delecroix (2016): convert Sage files into a standalone Python package
- Vincent Klein (2017): improve doctest support and Python 3 compatibility
-
ppl.closure_point()¶ Construct a closure point.
A closure point is a point of the topological closure of a polyhedron that is not a point of the polyhedron itself.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).divisor– an integer.
OUTPUT:
A new
Generatorrepresenting the point.Raises a
ValueError` if ``divisor==0.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.closure_point(2*y+7, 3) closure_point(0/3, 2/3) >>> Generator.closure_point(y+7, 3) closure_point(0/3, 1/3) >>> Generator.closure_point(7, 3) closure_point() >>> Generator.closure_point(0, 0) Traceback (most recent call last): ... ValueError: PPL::closure_point(e, d): d == 0.
-
ppl.line()¶ Construct a line.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).
OUTPUT:
A new
Generatorrepresenting the line.Raises a
ValueError` if the homogeneous part of ``expressionrepresents the origin of the vector space.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.line(2*y) line(0, 1) >>> Generator.line(y) line(0, 1) >>> Generator.line(1) Traceback (most recent call last): ... ValueError: PPL::line(e): e == 0, but the origin cannot be a line.
-
ppl.point()¶ Construct a point.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).divisor– an integer.
OUTPUT:
A new
Generatorrepresenting the point.Raises a
ValueError` if ``divisor==0.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.point(2*y+7, 3) point(0/3, 2/3) >>> Generator.point(y+7, 3) point(0/3, 1/3) >>> Generator.point(7, 3) point() >>> Generator.point(0, 0) Traceback (most recent call last): ... ValueError: PPL::point(e, d): d == 0.
-
ppl.ray()¶ Construct a ray.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).
OUTPUT:
A new
Generatorrepresenting the ray.Raises a
ValueError` if the homogeneous part of ``expressionrepresents the origin of the vector space.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.ray(2*y) ray(0, 1) >>> Generator.ray(y) ray(0, 1) >>> Generator.ray(1) Traceback (most recent call last): ... ValueError: PPL::ray(e): e == 0, but the origin cannot be a ray.
-
class
ppl.wrappers.C_Polyhedron¶ Bases:
ppl.wrappers.PolyhedronWrapper for PPL’s
C_Polyhedronclass.An object of the class
C_Polyhedronrepresents a topologically closed convex polyhedron in the vector space. SeeNNC_Polyhedronfor more general (not necessarily closed) polyhedra.When building a closed polyhedron starting from a system of constraints, an exception is thrown if the system contains a strict inequality constraint. Similarly, an exception is thrown when building a closed polyhedron starting from a system of generators containing a closure point.
INPUT:
arg– the defining data of the polyhedron. Any one of the following is accepted:- A non-negative integer. Depending on
degenerate_element, either the space-filling or the empty polytope in the given dimensionargis constructed. - A
Constraint_System. - A
Generator_System. - A single
Constraint. - A single
Generator. - A
C_Polyhedron.
- A non-negative integer. Depending on
degenerate_element– string, either'universe'or'empty'. Only used ifargis an integer.
OUTPUT:
A
C_Polyhedron.Examples:
>>> from ppl import Constraint, Constraint_System, Generator, Generator_System, Variable, C_Polyhedron, point, ray >>> x = Variable(0) >>> y = Variable(1) >>> C_Polyhedron( 5*x-2*y >= x+y-1 ) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 1 ray, 1 line >>> cs = Constraint_System() >>> cs.insert( x >= 0 ) >>> cs.insert( y >= 0 ) >>> C_Polyhedron(cs) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 2 rays >>> C_Polyhedron( point(x+y) ) A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point >>> gs = Generator_System() >>> gs.insert( point(-x-y) ) >>> gs.insert( ray(x) ) >>> C_Polyhedron(gs) A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 1 ray
The empty and universe polyhedra are constructed like this:
>>> C_Polyhedron(3, 'empty') The empty polyhedron in QQ^3 >>> C_Polyhedron(3, 'empty').constraints() Constraint_System {-1==0} >>> C_Polyhedron(3, 'universe') The space-filling polyhedron in QQ^3 >>> C_Polyhedron(3, 'universe').constraints() Constraint_System {}
Note that, by convention, the generator system of a polyhedron is either empty or contains at least one point. In particular, if you define a polyhedron via a non-empty
Generator_Systemit must contain a point (at any position). If you start with a single generator, this generator must be a point:>>> C_Polyhedron( ray(x) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::C_Polyhedron(gs): *this is an empty polyhedron and the non-empty generator system gs contains no points.
-
class
ppl.wrappers.Constraint¶ Bases:
objectWrapper for PPL’s
Constraintclass.An object of the class
Constraintis either:- an equality \(\sum_{i=0}^{n-1} a_i x_i + b = 0\)
- a non-strict inequality \(\sum_{i=0}^{n-1} a_i x_i + b \geq 0\)
- a strict inequality \(\sum_{i=0}^{n-1} a_i x_i + b > 0\)
where \(n\) is the dimension of the space, \(a_i\) is the integer coefficient of variable \(x_i\), and \(b_i\) is the integer inhomogeneous term.
INPUT/OUTPUT:
You construct constraints by writing inequalities in
Linear_Expression. Do not attempt to manually construct constraints.Examples:
>>> from ppl import Constraint, Variable, Linear_Expression >>> x = Variable(0) >>> y = Variable(1) >>> 5*x-2*y > x+y-1 4*x0-3*x1+1>0 >>> 5*x-2*y >= x+y-1 4*x0-3*x1+1>=0 >>> 5*x-2*y == x+y-1 4*x0-3*x1+1==0 >>> 5*x-2*y <= x+y-1 -4*x0+3*x1-1>=0 >>> 5*x-2*y < x+y-1 -4*x0+3*x1-1>0 >>> x > 0 x0>0
Special care is needed if the left hand side is a constant:
>>> 0 == 1 # watch out! False >>> Linear_Expression(0) == 1 -1==0
-
OK()¶ Check if all the invariants are satisfied.
Examples:
>>> from ppl import Linear_Expression, Variable >>> x = Variable(0) >>> y = Variable(1) >>> ineq = (3*x+2*y+1>=0) >>> ineq.OK() True
-
ascii_dump()¶ Write an ASCII dump to stderr.
Examples:
>>> cmd = 'from ppl import Linear_Expression, Variable\n' >>> cmd += 'x = Variable(0)\n' >>> cmd += 'y = Variable(1)\n' >>> cmd += 'e = (3*x+2*y+1 > 0)\n' >>> cmd += 'e.ascii_dump()\n' >>> import subprocess, sys >>> proc = subprocess.Popen([sys.executable, '-c', cmd], stderr=subprocess.PIPE) >>> out, err = proc.communicate() >>> print(str(err.decode('ascii'))) size 4 1 3 2 -1 ...
-
coefficient()¶ Return the coefficient of the variable
v.INPUT:
v– aVariable.
OUTPUT:
An integer.
Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> ineq = 3*x+1 > 0 >>> ineq.coefficient(x) 3 >>> y = Variable(1) >>> ineq = 3**50 * y + 2 > 1 >>> str(ineq.coefficient(y)) '717897987691852588770249' >>> ineq.coefficient(x) 0
-
coefficients()¶ Return the coefficients of the constraint.
See also
coefficient().OUTPUT:
A tuple of integers of length
space_dimension().Examples:
>>> from ppl import Variable >>> x = Variable(0); y = Variable(1) >>> ineq = ( 3*x+5*y+1 == 2); ineq 3*x0+5*x1-1==0 >>> ineq.coefficients() (3, 5)
-
inhomogeneous_term()¶ Return the inhomogeneous term of the constraint.
OUTPUT:
Integer.
Examples:
>>> from ppl import Variable >>> y = Variable(1) >>> ineq = 10+y > 9 >>> ineq x1+1>0 >>> ineq.inhomogeneous_term() 1 >>> ineq = 2**66 + y > 0 >>> str(ineq.inhomogeneous_term()) '73786976294838206464'
-
is_equality()¶ Test whether
selfis an equality.OUTPUT:
Boolean. Returns
Trueif and only ifselfis an equality constraint.Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> (x==0).is_equality() True >>> (x>=0).is_equality() False >>> (x>0).is_equality() False
-
is_equivalent_to()¶ Test whether
selfandcare equivalent.INPUT:
c– aConstraint.
OUTPUT:
Boolean. Returns
Trueif and only ifselfandcare equivalent constraints.Note that constraints having different space dimensions are not equivalent. However, constraints having different types may nonetheless be equivalent, if they both are tautologies or inconsistent.
Examples:
>>> from ppl import Variable, Linear_Expression >>> x = Variable(0) >>> y = Variable(1) >>> (x > 0).is_equivalent_to(Linear_Expression(0) < x) True >>> (x > 0).is_equivalent_to(0*y < x) False >>> (0*x > 1).is_equivalent_to(0*x == -2) True
-
is_inconsistent()¶ Test whether
selfis an inconsistent constraint, that is, always false.An inconsistent constraint can have either one of the following forms:
- an equality: \(\sum 0 x_i + b = 0\) with bnot=0,
- a non-strict inequality: \(\sum 0 x_i + b \geq 0\) with b< 0, or
- a strict inequality: \(\sum 0 x_i + b > 0\) with bleq 0.
OUTPUT:
Boolean. Returns
Trueif and only ifselfis an inconsistent constraint.Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> (x==1).is_inconsistent() False >>> (0*x>=1).is_inconsistent() True
-
is_inequality()¶ Test whether
selfis an inequality.OUTPUT:
Boolean. Returns
Trueif and only ifselfis an inequality constraint, either strict or non-strict.Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> (x==0).is_inequality() False >>> (x>=0).is_inequality() True >>> (x>0).is_inequality() True
-
is_nonstrict_inequality()¶ Test whether
selfis a non-strict inequality.OUTPUT:
Boolean. Returns
Trueif and only ifselfis an non-strict inequality constraint.Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> (x==0).is_nonstrict_inequality() False >>> (x>=0).is_nonstrict_inequality() True >>> (x>0).is_nonstrict_inequality() False
-
is_strict_inequality()¶ Test whether
selfis a strict inequality.OUTPUT:
Boolean. Returns
Trueif and only ifselfis an strict inequality constraint.Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> (x==0).is_strict_inequality() False >>> (x>=0).is_strict_inequality() False >>> (x>0).is_strict_inequality() True
-
is_tautological()¶ Test whether
selfis a tautological constraint.A tautology can have either one of the following forms:
- an equality: \(\sum 0 x_i + 0 = 0\),
- a non-strict inequality: \(\sum 0 x_i + b \geq 0\) with bgeq 0, or
- a strict inequality: \(\sum 0 x_i + b > 0\) with b> 0.
OUTPUT:
Boolean. Returns
Trueif and only ifselfis a tautological constraint.Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> (x==0).is_tautological() False >>> (0*x>=0).is_tautological() True
-
space_dimension()¶ Return the dimension of the vector space enclosing
self.OUTPUT:
Integer.
Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> y = Variable(1) >>> (x>=0).space_dimension() 1 >>> (y==1).space_dimension() 2
-
type()¶ Return the constraint type of
self.OUTPUT:
String. One of
'equality','nonstrict_inequality', or'strict_inequality'.Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> (x==0).type() 'equality' >>> (x>=0).type() 'nonstrict_inequality' >>> (x>0).type() 'strict_inequality'
-
class
ppl.wrappers.Constraint_System¶ Bases:
ppl.wrappers._mutable_or_immutableWrapper for PPL’s
Constraint_Systemclass.An object of the class Constraint_System is a system of constraints, i.e., a multiset of objects of the class Constraint. When inserting constraints in a system, space dimensions are automatically adjusted so that all the constraints in the system are defined on the same vector space.
Examples:
>>> from ppl import Constraint_System, Variable >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System( 5*x-2*y > 0 ) >>> cs.insert( 6*x < 3*y ) >>> cs.insert( x >= 2*x-7*y ) >>> cs Constraint_System {5*x0-2*x1>0, ...} >>> cs[0] 5*x0-2*x1>0
-
OK()¶ Check if all the invariants are satisfied.
Examples:
>>> from ppl import Variable, Constraint_System >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System( 3*x+2*y+1 <= 10 ) >>> cs.OK() True
-
ascii_dump()¶ Write an ASCII dump to stderr.
Examples:
>>> cmd = 'from ppl import Constraint_System, Variable\n' >>> cmd += 'x = Variable(0)\n' >>> cmd += 'y = Variable(1)\n' >>> cmd += 'cs = Constraint_System( 3*x > 2*y+1 )\n' >>> cmd += 'cs.ascii_dump()\n' >>> import subprocess, sys >>> proc = subprocess.Popen([sys.executable, '-c', cmd], stderr=subprocess.PIPE) >>> out, err = proc.communicate() >>> print(str(err.decode('ascii'))) topology NOT_NECESSARILY_CLOSED ...
-
clear()¶ Removes all constraints from the constraint system and sets its space dimension to 0.
Examples:
>>> from ppl import Variable, Constraint_System >>> x = Variable(0) >>> cs = Constraint_System(x>0) >>> cs Constraint_System {x0>0} >>> cs.clear() >>> cs Constraint_System {}
-
empty()¶ Return
Trueif and only ifselfhas no constraints.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, Constraint_System, point >>> x = Variable(0) >>> cs = Constraint_System() >>> cs.empty() True >>> cs.insert( x>0 ) >>> cs.empty() False
-
has_equalities()¶ Tests whether
selfcontains one or more equality constraints.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, Constraint_System >>> x = Variable(0) >>> cs = Constraint_System() >>> cs.insert( x>0 ) >>> cs.insert( x<0 ) >>> cs.has_equalities() False >>> cs.insert( x==0 ) >>> cs.has_equalities() True
-
has_strict_inequalities()¶ Tests whether
selfcontains one or more strict inequality constraints.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, Constraint_System >>> x = Variable(0) >>> cs = Constraint_System() >>> cs.insert( x>=0 ) >>> cs.insert( x==-1 ) >>> cs.has_strict_inequalities() False >>> cs.insert( x>0 ) >>> cs.has_strict_inequalities() True
-
insert()¶ Insert
cinto the constraint system.INPUT:
c– aConstraint.
Examples:
>>> from ppl import Variable, Constraint_System >>> x = Variable(0) >>> cs = Constraint_System() >>> cs.insert( x>0 ) >>> cs Constraint_System {x0>0}
-
space_dimension()¶ Return the dimension of the vector space enclosing
self.OUTPUT:
Integer.
Examples:
>>> from ppl import Variable, Constraint_System >>> x = Variable(0) >>> cs = Constraint_System( x>0 ) >>> cs.space_dimension() 1
-
-
class
ppl.wrappers.Constraint_System_iterator¶ Bases:
objectWrapper for PPL’s
Constraint_System::const_iteratorclass.Examples:
>>> from ppl import Constraint_System, Variable >>> from ppl.wrappers import Constraint_System_iterator >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System( 5*x < 2*y ) >>> cs.insert( 6*x-y == 0 ) >>> cs.insert( x >= 2*x-7*y ) >>> next(Constraint_System_iterator(cs)) -5*x0+2*x1>0 >>> list(cs) [-5*x0+2*x1>0, 6*x0-x1==0, -x0+7*x1>=0]
-
class
ppl.wrappers.Generator¶ Bases:
objectWrapper for PPL’s
Generatorclass.An object of the class Generator is one of the following:
- a line \(\ell = (a_0, \dots, a_{n-1})^T\)
- a ray \(r = (a_0, \dots, a_{n-1})^T\)
- a point \(p = (\tfrac{a_0}{d}, \dots, \tfrac{a_{n-1}}{d})^T\)
- a closure point \(c = (\tfrac{a_0}{d}, \dots, \tfrac{a_{n-1}}{d})^T\)
where \(n\) is the dimension of the space and, for points and closure points, \(d\) is the divisor.
INPUT/OUTPUT:
Use the helper functions
line(),ray(),point(), andclosure_point()to construct generators. Analogous class methods are also available, seeGenerator.line(),Generator.ray(),Generator.point(),Generator.closure_point(). Do not attempt to construct generators manually.Note
The generators are constructed from linear expressions. The inhomogeneous term is always silently discarded.
Examples:
>>> from ppl import Generator, Variable >>> x = Variable(0) >>> y = Variable(1) >>> Generator.line(5*x-2*y) line(5, -2) >>> Generator.ray(5*x-2*y) ray(5, -2) >>> Generator.point(5*x-2*y, 7) point(5/7, -2/7) >>> Generator.closure_point(5*x-2*y, 7) closure_point(5/7, -2/7)
-
OK()¶ Check if all the invariants are satisfied.
Examples:
>>> from ppl import Linear_Expression, Variable >>> x = Variable(0) >>> y = Variable(1) >>> e = 3*x+2*y+1 >>> e.OK() True
-
ascii_dump()¶ Write an ASCII dump to stderr.
Examples:
>>> cmd = 'from ppl import Linear_Expression, Variable, point\n' >>> cmd += 'x = Variable(0)\n' >>> cmd += 'y = Variable(1)\n' >>> cmd += 'p = point(3*x+2*y)\n' >>> cmd += 'p.ascii_dump()\n' >>> import subprocess >>> import sys >>> proc = subprocess.Popen([sys.executable, '-c', cmd], stderr=subprocess.PIPE) >>> out, err = proc.communicate() >>> print(str(err.decode('ascii'))) size 3 1 3 2 ...
-
closure_point()¶ Construct a closure point.
A closure point is a point of the topological closure of a polyhedron that is not a point of the polyhedron itself.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).divisor– an integer.
OUTPUT:
A new
Generatorrepresenting the point.Raises a
ValueError` if ``divisor==0.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.closure_point(2*y+7, 3) closure_point(0/3, 2/3) >>> Generator.closure_point(y+7, 3) closure_point(0/3, 1/3) >>> Generator.closure_point(7, 3) closure_point() >>> Generator.closure_point(0, 0) Traceback (most recent call last): ... ValueError: PPL::closure_point(e, d): d == 0.
-
coefficient()¶ Return the coefficient of the variable
v.INPUT:
v– aVariable.
OUTPUT:
An integer.
Examples:
>>> from ppl import Variable, line >>> x = Variable(0) >>> line = line(3*x+1) >>> line line(1) >>> line.coefficient(x) 1
-
coefficients()¶ Return the coefficients of the generator.
See also
coefficient().OUTPUT:
A tuple of integers of length
space_dimension().Examples:
>>> from ppl import Variable, point >>> x = Variable(0); y = Variable(1) >>> p = point(3*x+5*y+1, 2); p point(3/2, 5/2) >>> p.coefficients() (3, 5)
-
divisor()¶ If
selfis either a point or a closure point, return its divisor.OUTPUT:
An integer. If
selfis a ray or a line, raisesValueError.Examples:
>>> from ppl import Generator, Variable >>> x = Variable(0) >>> y = Variable(1) >>> point = Generator.point(2*x-y+5) >>> point.divisor() 1 >>> line = Generator.line(2*x-y+5) >>> line.divisor() Traceback (most recent call last): ... ValueError: PPL::Generator::divisor(): *this is neither a point nor a closure point.
-
is_closure_point()¶ Test whether
selfis a closure point.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, point, closure_point, ray, line >>> x = Variable(0) >>> line(x).is_closure_point() False >>> ray(x).is_closure_point() False >>> point(x,2).is_closure_point() False >>> closure_point(x,2).is_closure_point() True
-
is_equivalent_to()¶ Test whether
selfandgare equivalent.INPUT:
g– aGenerator.
OUTPUT:
Boolean. Returns
Trueif and only ifselfandgare equivalent generators.Note that generators having different space dimensions are not equivalent.
Examples:
>>> from ppl import Generator, Variable, point, line >>> x = Variable(0) >>> y = Variable(1) >>> point(2*x , 2).is_equivalent_to( point(x) ) True >>> point(2*x+0*y, 2).is_equivalent_to( point(x) ) False >>> line(4*x).is_equivalent_to(line(x)) True
-
is_line()¶ Test whether
selfis a line.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, point, closure_point, ray, line >>> x = Variable(0) >>> line(x).is_line() True >>> ray(x).is_line() False >>> point(x,2).is_line() False >>> closure_point(x,2).is_line() False
-
is_line_or_ray()¶ Test whether
selfis a line or a ray.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, point, closure_point, ray, line >>> x = Variable(0) >>> line(x).is_line_or_ray() True >>> ray(x).is_line_or_ray() True >>> point(x,2).is_line_or_ray() False >>> closure_point(x,2).is_line_or_ray() False
-
is_point()¶ Test whether
selfis a point.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, point, closure_point, ray, line >>> x = Variable(0) >>> line(x).is_point() False >>> ray(x).is_point() False >>> point(x,2).is_point() True >>> closure_point(x,2).is_point() False
-
is_ray()¶ Test whether
selfis a ray.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, point, closure_point, ray, line >>> x = Variable(0) >>> line(x).is_ray() False >>> ray(x).is_ray() True >>> point(x,2).is_ray() False >>> closure_point(x,2).is_ray() False
-
line()¶ Construct a line.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).
OUTPUT:
A new
Generatorrepresenting the line.Raises a
ValueError` if the homogeneous part of ``expressionrepresents the origin of the vector space.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.line(2*y) line(0, 1) >>> Generator.line(y) line(0, 1) >>> Generator.line(1) Traceback (most recent call last): ... ValueError: PPL::line(e): e == 0, but the origin cannot be a line.
-
point()¶ Construct a point.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).divisor– an integer.
OUTPUT:
A new
Generatorrepresenting the point.Raises a
ValueError` if ``divisor==0.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.point(2*y+7, 3) point(0/3, 2/3) >>> Generator.point(y+7, 3) point(0/3, 1/3) >>> Generator.point(7, 3) point() >>> Generator.point(0, 0) Traceback (most recent call last): ... ValueError: PPL::point(e, d): d == 0.
-
ray()¶ Construct a ray.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).
OUTPUT:
A new
Generatorrepresenting the ray.Raises a
ValueError` if the homogeneous part of ``expressionrepresents the origin of the vector space.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.ray(2*y) ray(0, 1) >>> Generator.ray(y) ray(0, 1) >>> Generator.ray(1) Traceback (most recent call last): ... ValueError: PPL::ray(e): e == 0, but the origin cannot be a ray.
-
space_dimension()¶ Return the dimension of the vector space enclosing
self.OUTPUT:
Integer.
Examples:
>>> from ppl import Variable, point >>> x = Variable(0) >>> y = Variable(1) >>> point(x).space_dimension() 1 >>> point(y).space_dimension() 2
-
type()¶ Return the generator type of
self.OUTPUT:
String. One of
'line','ray','point', or'closure_point'.Examples:
>>> from ppl import Variable, point, closure_point, ray, line >>> x = Variable(0) >>> line(x).type() 'line' >>> ray(x).type() 'ray' >>> point(x,2).type() 'point' >>> closure_point(x,2).type() 'closure_point'
-
class
ppl.wrappers.Generator_System¶ Bases:
ppl.wrappers._mutable_or_immutableWrapper for PPL’s
Generator_Systemclass.An object of the class Generator_System is a system of generators, i.e., a multiset of objects of the class Generator (lines, rays, points and closure points). When inserting generators in a system, space dimensions are automatically adjusted so that all the generators in the system are defined on the same vector space. A system of generators which is meant to define a non-empty polyhedron must include at least one point: the reason is that lines, rays and closure points need a supporting point (lines and rays only specify directions while closure points only specify points in the topological closure of the NNC polyhedron).
Examples:
>>> from ppl import Generator_System, Variable, line, ray, point, closure_point >>> x = Variable(0) >>> y = Variable(1) >>> gs = Generator_System(line(5*x-2*y)) >>> gs.insert(ray(6*x-3*y)) >>> gs.insert(point(2*x-7*y, 5)) >>> gs.insert(closure_point(9*x-1*y, 2)) >>> gs Generator_System {line(5, -2), ray(2, -1), point(2/5, -7/5), closure_point(9/2, -1/2)}
-
OK()¶ Check if all the invariants are satisfied.
Examples:
>>> from ppl import Variable, Generator_System, point >>> x = Variable(0) >>> y = Variable(1) >>> gs = Generator_System( point(3*x+2*y+1) ) >>> gs.OK() True
-
ascii_dump()¶ Write an ASCII dump to stderr.
Examples:
>>> cmd = 'from ppl import Generator_System, point, Variable\n' >>> cmd += 'x = Variable(0)\n' >>> cmd += 'y = Variable(1)\n' >>> cmd += 'gs = Generator_System( point(3*x+2*y+1) )\n' >>> cmd += 'gs.ascii_dump()\n' >>> import subprocess, sys >>> proc = subprocess.Popen([sys.executable, '-c', cmd], stderr=subprocess.PIPE) >>> out, err = proc.communicate() >>> print(str(err.decode('ascii'))) topology NECESSARILY_CLOSED ...
-
clear()¶ Removes all generators from the generator system and sets its space dimension to 0.
Examples:
>>> from ppl import Variable, Generator_System, point >>> x = Variable(0) >>> gs = Generator_System( point(3*x) ); gs Generator_System {point(3/1)} >>> gs.clear() >>> gs Generator_System {}
-
empty()¶ Return
Trueif and only ifselfhas no generators.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, Generator_System, point >>> x = Variable(0) >>> gs = Generator_System() >>> gs.empty() True >>> gs.insert( point(-3*x) ) >>> gs.empty() False
-
insert()¶ Insert
ginto the generator system.The number of space dimensions of
selfis increased, if needed.INPUT:
g– aGenerator.
Examples:
>>> from ppl import Variable, Generator_System, point >>> x = Variable(0) >>> gs = Generator_System( point(3*x) ) >>> gs.insert( point(-3*x) ) >>> gs Generator_System {point(3/1), point(-3/1)}
-
space_dimension()¶ Return the dimension of the vector space enclosing
self.OUTPUT:
Integer.
Examples:
>>> from ppl import Variable, Generator_System, point >>> x = Variable(0) >>> gs = Generator_System( point(3*x) ) >>> gs.space_dimension() 1
-
-
class
ppl.wrappers.Generator_System_iterator¶ Bases:
objectWrapper for PPL’s
Generator_System::const_iteratorclass.Examples:
>>> from ppl import Generator_System, Variable, line, ray, point, closure_point >>> from ppl.wrappers import Generator_System_iterator >>> x = Variable(0) >>> y = Variable(1) >>> gs = Generator_System( line(5*x-2*y) ) >>> gs.insert( ray(6*x-3*y) ) >>> gs.insert( point(2*x-7*y, 5) ) >>> gs.insert( closure_point(9*x-1*y, 2) ) >>> next(Generator_System_iterator(gs)) line(5, -2) >>> list(gs) [line(5, -2), ray(2, -1), point(2/5, -7/5), closure_point(9/2, -1/2)]
-
class
ppl.wrappers.Linear_Expression¶ Bases:
objectWrapper for PPL’s
PPL_Linear_Expressionclass.INPUT:
The constructor accepts zero, one, or two arguments.
If there are two arguments
Linear_Expression(a,b), they are interpreted asa– an iterable of integer coefficients, for example a list.b– an integer. The inhomogeneous term.
A single argument
Linear_Expression(arg)is interpreted asarg– something that determines a linear expression. Possibilities are:- a
Variable: The linear expression given by that variable. - a
Linear_Expression: The copy constructor. - an integer: Constructs the constant linear expression.
- a
No argument is the default constructor and returns the zero linear expression.
OUTPUT:
Examples:
>>> from ppl import Variable, Linear_Expression >>> Linear_Expression([1,2,3,4],5) x0+2*x1+3*x2+4*x3+5 >>> Linear_Expression(10) 10 >>> Linear_Expression() 0 >>> Linear_Expression(10).inhomogeneous_term() 10 >>> x = Variable(123) >>> expr = x+1; expr x123+1 >>> expr.OK() True >>> expr.coefficient(x) 1 >>> expr.coefficient( Variable(124) ) 0
-
OK()¶ Check if all the invariants are satisfied.
Examples:
>>> from ppl import Linear_Expression, Variable >>> x = Variable(0) >>> y = Variable(1) >>> e = 3*x+2*y+1 >>> e.OK() True
-
all_homogeneous_terms_are_zero()¶ Test if
selfis a constant linear expression.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, Linear_Expression >>> Linear_Expression(10).all_homogeneous_terms_are_zero() True
-
ascii_dump()¶ Write an ASCII dump to stderr.
Examples:
>>> cmd = 'from ppl import Linear_Expression, Variable\n' >>> cmd += 'x = Variable(0)\n' >>> cmd += 'y = Variable(1)\n' >>> cmd += 'e = 3*x+2*y+1\n' >>> cmd += 'e.ascii_dump()\n' >>> from subprocess import Popen, PIPE >>> import sys >>> proc = Popen([sys.executable, '-c', cmd], stdout=PIPE, stderr=PIPE) >>> out, err = proc.communicate() >>> len(out) == 0 True >>> len(err) > 0 True
-
coefficient()¶ Return the coefficient of the variable
v.INPUT:
v– aVariable.
OUTPUT:
An integer.
Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> e = 3*x+1 >>> e.coefficient(x) 3
-
coefficients()¶ Return the coefficients of the linear expression.
OUTPUT:
A tuple of integers of length
space_dimension().Examples:
>>> from ppl import Variable >>> x = Variable(0); y = Variable(1) >>> e = 3*x+5*y+1 >>> e.coefficients() (3, 5)
-
inhomogeneous_term()¶ Return the inhomogeneous term of the linear expression.
OUTPUT:
Integer.
Examples:
>>> from ppl import Variable, Linear_Expression >>> Linear_Expression(10).inhomogeneous_term() 10
-
is_zero()¶ Test if
selfis the zero linear expression.OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable, Linear_Expression >>> Linear_Expression(0).is_zero() True >>> Linear_Expression(10).is_zero() False
-
space_dimension()¶ Return the dimension of the vector space necessary for the linear expression.
OUTPUT:
Integer.
Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> y = Variable(1) >>> (x+y+1).space_dimension() 2 >>> (x+y).space_dimension() 2 >>> (y+1).space_dimension() 2 >>> (x+1).space_dimension() 1 >>> (y+1-y).space_dimension() 2
-
class
ppl.wrappers.MIP_Problem¶ Bases:
ppl.wrappers._mutable_or_immutablewrapper for PPL’s MIP_Problem class
An object of the class MIP_Problem represents a Mixed Integer (Linear) Program problem.
INPUT:
dim– integerargs– an array of the defining data of the MIP_Problem. For each element, any one of the following is accepted:
OUTPUT:
A
MIP_Problem.Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert(x >= 0) >>> cs.insert(y >= 0) >>> cs.insert(3 * x + 5 * y <= 10) >>> m = MIP_Problem(2, cs, x + y) >>> m MIP Problem (maximization, 2 variables, 3 constraints) >>> m.optimal_value() Fraction(10, 3) >>> float(_) 3.3333333333333335 >>> m.optimizing_point() point(10/3, 0/3)
-
OK()¶ Check if all the invariants are satisfied.
OUTPUT:
Trueif and only ifselfsatisfies all the invariants.Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> m = MIP_Problem() >>> m.add_space_dimensions_and_embed(2) >>> m.add_constraint(x >= 0) >>> m.OK() True
-
add_constraint()¶ Adds a copy of constraint c to the MIP problem.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> m = MIP_Problem() >>> m.add_space_dimensions_and_embed(2) >>> m.add_constraint(x >= 0) >>> m.add_constraint(y >= 0) >>> m.add_constraint(3 * x + 5 * y <= 10) >>> m.set_objective_function(x + y) >>> m.optimal_value() Fraction(10, 3)
Tests:
>>> z = Variable(2) >>> m.add_constraint(z >= -3) Traceback (most recent call last): ... ValueError: PPL::MIP_Problem::add_constraint(c): c.space_dimension() == 3 exceeds this->space_dimension == 2.
-
add_constraints()¶ Adds a copy of the constraints in cs to the MIP problem.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert(x >= 0) >>> cs.insert(y >= 0) >>> cs.insert(3 * x + 5 * y <= 10) >>> m = MIP_Problem(2) >>> m.set_objective_function(x + y) >>> m.add_constraints(cs) >>> m.optimal_value() Fraction(10, 3)
Tests:
>>> p = Variable(9) >>> cs.insert(p >= -3) >>> m.add_constraints(cs) Traceback (most recent call last): ... ValueError: PPL::MIP_Problem::add_constraints(cs): cs.space_dimension() == 10 exceeds this->space_dimension() == 2.
-
add_space_dimensions_and_embed()¶ Adds m new space dimensions and embeds the old MIP problem in the new vector space.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert( x >= 0) >>> cs.insert( y >= 0 ) >>> cs.insert( 3 * x + 5 * y <= 10 ) >>> m = MIP_Problem(2, cs, x + y) >>> m.add_space_dimensions_and_embed(5) >>> m.space_dimension() 7
-
clear()¶ Reset the MIP_Problem to be equal to the trivial MIP_Problem.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert( x >= 0) >>> cs.insert( y >= 0 ) >>> cs.insert( 3 * x + 5 * y <= 10 ) >>> m = MIP_Problem(2, cs, x + y) >>> m.objective_function() x0+x1 >>> m.clear() >>> m.objective_function() 0
-
constraints()¶ Return the constraints of this MIP
The output is an instance of
Constraint_System.Examples:
>>> from ppl import Variable, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> M = MIP_Problem(2) >>> M.add_constraint(x + y <= 5) >>> M.add_constraint(3*x - 18*y >= -2) >>> M.constraints() Constraint_System {-x0-x1+5>=0, 3*x0-18*x1+2>=0}
Note that modifying the output of this method will not modify the underlying MIP problem object:
>>> cs = M.constraints() >>> cs.insert(x <= 3) >>> cs Constraint_System {-x0-x1+5>=0, 3*x0-18*x1+2>=0, -x0+3>=0} >>> M.constraints() Constraint_System {-x0-x1+5>=0, 3*x0-18*x1+2>=0}
-
evaluate_objective_function()¶ Return the result of evaluating the objective function on evaluating_point. ValueError thrown if self and evaluating_point are dimension-incompatible or if the generator evaluating_point is not a point.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem, Generator >>> x = Variable(0) >>> y = Variable(1) >>> m = MIP_Problem() >>> m.add_space_dimensions_and_embed(2) >>> m.add_constraint(x >= 0) >>> m.add_constraint(y >= 0) >>> m.add_constraint(3 * x + 5 * y <= 10) >>> m.set_objective_function(x + y) >>> g = Generator.point(5 * x - 2 * y, 7) >>> m.evaluate_objective_function(g) Fraction(3, 7) >>> z = Variable(2) >>> g = Generator.point(5 * x - 2 * z, 7) >>> m.evaluate_objective_function(g) Traceback (most recent call last): ... ValueError: PPL::MIP_Problem::evaluate_objective_function(p, n, d): *this and p are dimension incompatible.
-
is_satisfiable()¶ Check if the MIP_Problem is satisfiable
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> m = MIP_Problem() >>> m.add_space_dimensions_and_embed(2) >>> m.add_constraint(x >= 0) >>> m.add_constraint(y >= 0) >>> m.add_constraint(3 * x + 5 * y <= 10) >>> m.is_satisfiable() True
-
objective_function()¶ Return the optimal value of the MIP_Problem.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert( x >= 0) >>> cs.insert( y >= 0 ) >>> cs.insert( 3 * x + 5 * y <= 10 ) >>> m = MIP_Problem(2, cs, x + y) >>> m.objective_function() x0+x1
-
optimal_value()¶ Return the optimal value of the MIP_Problem. ValueError thrown if self does not have an optimizing point, i.e., if the MIP problem is unbounded or not satisfiable.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert( x >= 0 ) >>> cs.insert( y >= 0 ) >>> cs.insert( 3 * x + 5 * y <= 10 ) >>> m = MIP_Problem(2, cs, x + y) >>> m.optimal_value() Fraction(10, 3) >>> cs = Constraint_System() >>> cs.insert( x >= 0 ) >>> m = MIP_Problem(1, cs, x + x ) >>> m.optimal_value() Traceback (most recent call last): ... ValueError: PPL::MIP_Problem::optimizing_point(): *this ... have an optimizing point.
-
optimization_mode()¶ Return the optimization mode used in the MIP_Problem.
It will return “maximization” if the MIP_Problem was set to MAXIMIZATION mode, and “minimization” otherwise.
Examples:
>>> from ppl import MIP_Problem >>> m = MIP_Problem() >>> m.optimization_mode() 'maximization'
-
optimizing_point()¶ Returns an optimal point for the MIP_Problem, if it exists.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> m = MIP_Problem() >>> m.add_space_dimensions_and_embed(2) >>> m.add_constraint(x >= 0) >>> m.add_constraint(y >= 0) >>> m.add_constraint(3 * x + 5 * y <= 10) >>> m.set_objective_function(x + y) >>> m.optimizing_point() point(10/3, 0/3)
-
set_objective_function()¶ Sets the objective function to obj.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> m = MIP_Problem() >>> m.add_space_dimensions_and_embed(2) >>> m.add_constraint(x >= 0) >>> m.add_constraint(y >= 0) >>> m.add_constraint(3 * x + 5 * y <= 10) >>> m.set_objective_function(x + y) >>> m.optimal_value() Fraction(10, 3)
Tests:
>>> z = Variable(2) >>> m.set_objective_function(x + y + z) Traceback (most recent call last): ... ValueError: PPL::MIP_Problem::set_objective_function(obj): obj.space_dimension() == 3 exceeds this->space_dimension == 2.
-
set_optimization_mode()¶ Sets the optimization mode to mode.
Examples:
>>> from ppl import MIP_Problem >>> m = MIP_Problem() >>> m.optimization_mode() 'maximization' >>> m.set_optimization_mode('minimization') >>> m.optimization_mode() 'minimization'
Tests:
>>> m.set_optimization_mode('max') Traceback (most recent call last): ... ValueError: Unknown value: mode=max.
-
solve()¶ Optimizes the MIP_Problem
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> m = MIP_Problem() >>> m.add_space_dimensions_and_embed(2) >>> m.add_constraint(x >= 0) >>> m.add_constraint(y >= 0) >>> m.add_constraint(3 * x + 5 * y <= 10) >>> m.set_objective_function(x + y) >>> m.solve() {'status': 'optimized'}
-
space_dimension()¶ Return the space dimension of the MIP_Problem.
Examples:
>>> from ppl import Variable, Constraint_System, MIP_Problem >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert( x >= 0) >>> cs.insert( y >= 0 ) >>> cs.insert( 3 * x + 5 * y <= 10 ) >>> m = MIP_Problem(2, cs, x + y) >>> m.space_dimension() 2
-
class
ppl.wrappers.MIP_Problem_constraints_iterator¶ Bases:
objectWrapper for PPL’s
Constraint_System::const_iteratorclass.
-
class
ppl.wrappers.NNC_Polyhedron¶ Bases:
ppl.wrappers.PolyhedronWrapper for PPL’s
NNC_Polyhedronclass.An object of the class
NNC_Polyhedronrepresents a not necessarily closed (NNC) convex polyhedron in the vector space.Note: Since NNC polyhedra are a generalization of closed polyhedra, any object of the class
C_Polyhedroncan be (explicitly) converted into an object of the classNNC_Polyhedron. The reason for defining two different classes is that objects of the classC_Polyhedronare characterized by a more efficient implementation, requiring less time and memory resources.INPUT:
arg– the defining data of the polyhedron. Any one of the following is accepted:- An non-negative integer. Depending on
degenerate_element, either the space-filling or the empty polytope in the given dimensionargis constructed. - A
Constraint_System. - A
Generator_System. - A single
Constraint. - A single
Generator. - A
NNC_Polyhedron. - A
C_Polyhedron.
- An non-negative integer. Depending on
degenerate_element– string, either'universe'or'empty'. Only used ifargis an integer.
OUTPUT:
A
C_Polyhedron.Examples:
>>> from ppl import Constraint, Constraint_System, Generator, Generator_System, Variable, NNC_Polyhedron, point, ray, closure_point >>> x = Variable(0) >>> y = Variable(1) >>> NNC_Polyhedron( 5*x-2*y > x+y-1 ) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 1 closure_point, 1 ray, 1 line >>> cs = Constraint_System() >>> cs.insert( x > 0 ) >>> cs.insert( y > 0 ) >>> NNC_Polyhedron(cs) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 1 closure_point, 2 rays >>> NNC_Polyhedron( point(x+y) ) A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point >>> gs = Generator_System() >>> gs.insert( point(-y) ) >>> gs.insert( closure_point(-x-y) ) >>> gs.insert( ray(x) ) >>> p = NNC_Polyhedron(gs); p A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 1 closure_point, 1 ray >>> p.minimized_constraints() Constraint_System {x1+1==0, x0+1>0}
Note that, by convention, every polyhedron must contain a point:
>>> NNC_Polyhedron( closure_point(x+y) ) Traceback (most recent call last): ... ValueError: PPL::NNC_Polyhedron::NNC_Polyhedron(gs): *this is an empty polyhedron and the non-empty generator system gs contains no points.
-
class
ppl.wrappers.Poly_Con_Relation¶ Bases:
objectWrapper for PPL’s
Poly_Con_Relationclass.INPUT/OUTPUT:
You must not construct
Poly_Con_Relationobjects manually. You will usually get them fromrelation_with(). You can also get pre-defined relations from the class methodsnothing(),is_disjoint(),strictly_intersects(),is_included(), andsaturates().Examples:
>>> from ppl import Poly_Con_Relation >>> saturates = Poly_Con_Relation.saturates(); saturates saturates >>> is_included = Poly_Con_Relation.is_included(); is_included is_included >>> is_included.implies(saturates) False >>> saturates.implies(is_included) False >>> rels = [] >>> rels.append(Poly_Con_Relation.nothing()) >>> rels.append(Poly_Con_Relation.is_disjoint()) >>> rels.append(Poly_Con_Relation.strictly_intersects()) >>> rels.append(Poly_Con_Relation.is_included()) >>> rels.append(Poly_Con_Relation.saturates()) >>> rels [nothing, is_disjoint, strictly_intersects, is_included, saturates] >>> for i, rel_i in enumerate(rels): ... s = "" ... for j, rel_j in enumerate(rels): ... s=s+str(int(rel_i.implies(rel_j))) + ' ' ... print(" ".join(str(int(rel_i.implies(rel_j))) for j, rel_j in enumerate(rels))) 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 0 1
-
OK()¶ Check if all the invariants are satisfied.
Examples:
>>> from ppl import Poly_Con_Relation >>> Poly_Con_Relation.nothing().OK() True
-
ascii_dump()¶ Write an ASCII dump to stderr.
Examples:
>>> cmd = 'from ppl import Poly_Con_Relation\n' >>> cmd += 'Poly_Con_Relation.nothing().ascii_dump()\n' >>> import subprocess, sys >>> proc = subprocess.Popen([sys.executable, '-c', cmd], stderr=subprocess.PIPE) >>> out, err = proc.communicate() >>> print(str(err.decode('ascii'))) NOTHING
-
implies()¶ Test whether
selfimpliesy.INPUT:
y– aPoly_Con_Relation.
OUTPUT:
Boolean.
Trueif and only ifselfimpliesy.Examples:
>>> from ppl import Poly_Con_Relation >>> nothing = Poly_Con_Relation.nothing() >>> nothing.implies( nothing ) True
-
is_disjoint()¶ Return the assertion “The polyhedron and the set of points satisfying the constraint are disjoint”.
OUTPUT:
Examples:
>>> from ppl import Poly_Con_Relation >>> Poly_Con_Relation.is_disjoint() is_disjoint
-
is_included()¶ Return the assertion “The polyhedron is included in the set of points satisfying the constraint”.
OUTPUT:
Examples:
>>> from ppl import Poly_Con_Relation >>> Poly_Con_Relation.is_included() is_included
-
nothing()¶ Return the assertion that says nothing.
OUTPUT:
Examples:
>>> from ppl import Poly_Con_Relation >>> Poly_Con_Relation.nothing() nothing
-
saturates()¶ Return the assertion “”.
OUTPUT:
Examples:
>>> from ppl import Poly_Con_Relation >>> Poly_Con_Relation.saturates() saturates
-
strictly_intersects()¶ Return the assertion “The polyhedron intersects the set of points satisfying the constraint, but it is not included in it”.
Returns: a Poly_Con_Relation.Examples:
>>> from ppl import Poly_Con_Relation >>> Poly_Con_Relation.strictly_intersects() strictly_intersects
-
-
class
ppl.wrappers.Poly_Gen_Relation¶ Bases:
objectWrapper for PPL’s
Poly_Con_Relationclass.INPUT/OUTPUT:
You must not construct
Poly_Gen_Relationobjects manually. You will usually get them fromrelation_with(). You can also get pre-defined relations from the class methodsnothing()andsubsumes().Examples:
>>> from ppl import Poly_Gen_Relation >>> nothing = Poly_Gen_Relation.nothing(); nothing nothing >>> subsumes = Poly_Gen_Relation.subsumes(); subsumes subsumes >>> nothing.implies( subsumes ) False >>> subsumes.implies( nothing ) True
-
OK()¶ Check if all the invariants are satisfied.
Examples:
>>> from ppl import Poly_Gen_Relation >>> Poly_Gen_Relation.nothing().OK() True
-
ascii_dump()¶ Write an ASCII dump to stderr.
Examples:
>>> cmd = 'from ppl import Poly_Gen_Relation\n' >>> cmd += 'Poly_Gen_Relation.nothing().ascii_dump()\n' >>> from subprocess import Popen, PIPE >>> import sys >>> proc = Popen([sys.executable, '-c', cmd], stderr=PIPE) >>> out, err = proc.communicate() >>> print(str(err.decode('ascii'))) NOTHING >>> proc.returncode 0
-
implies()¶ Test whether
selfimpliesy.INPUT:
y– aPoly_Gen_Relation.
OUTPUT:
Boolean.
Trueif and only ifselfimpliesy.Examples:
>>> from ppl import Poly_Gen_Relation >>> nothing = Poly_Gen_Relation.nothing() >>> nothing.implies( nothing ) True
-
nothing()¶ Return the assertion that says nothing.
OUTPUT:
Examples:
>>> from ppl import Poly_Gen_Relation >>> Poly_Gen_Relation.nothing() nothing
-
subsumes()¶ Return the assertion “Adding the generator would not change the polyhedron”.
OUTPUT:
Examples:
>>> from ppl import Poly_Gen_Relation >>> Poly_Gen_Relation.subsumes() subsumes
-
-
class
ppl.wrappers.Polyhedron¶ Bases:
ppl.wrappers._mutable_or_immutableWrapper for PPL’s
Polyhedronclass.An object of the class Polyhedron represents a convex polyhedron in the vector space.
A polyhedron can be specified as either a finite system of constraints or a finite system of generators (see Section Representations of Convex Polyhedra) and it is always possible to obtain either representation. That is, if we know the system of constraints, we can obtain from this the system of generators that define the same polyhedron and vice versa. These systems can contain redundant members: in this case we say that they are not in the minimal form.
INPUT/OUTPUT:
This is an abstract base for
C_PolyhedronandNNC_Polyhedron. You cannot instantiate this class.-
OK()¶ Check if all the invariants are satisfied.
The check is performed so as to intrude as little as possible. If the library has been compiled with run-time assertions enabled, error messages are written on std::cerr in case invariants are violated. This is useful for the purpose of debugging the library.
INPUT:
check_not_empty– boolean.Trueif and only if, in addition to checking the invariants,selfmust be checked to be not empty.
OUTPUT:
Trueif and only ifselfsatisfies all the invariants and eithercheck_not_emptyisFalseorselfis not empty.Examples:
>>> from ppl import Linear_Expression, Variable >>> x = Variable(0) >>> y = Variable(1) >>> e = 3*x+2*y+1 >>> e.OK() True
-
add_constraint()¶ Add a constraint to the polyhedron.
Adds a copy of constraint
cto the system of constraints ofself, without minimizing the result.See alse
add_constraints().INPUT:
c– theConstraintthat will be added to the system of constraints ofself.
OUTPUT:
This method modifies the polyhedron
selfand does not return anything.Raises a
ValueErrorifselfand the constraintcare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron( y>=0 ) >>> p.add_constraint( x>=0 )
We just added a 1-d constraint to a 2-d polyhedron, this is fine. The other way is not:>>> p = C_Polyhedron( x>=0 ) >>> p.add_constraint( y>=0 ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_constraint(c): this->space_dimension() == 1, c.space_dimension() == 2.
The constraint must also be topology-compatible, that is,C_Polyhedrononly allows non-strict inequalities:>>> p = C_Polyhedron( x>=0 ) >>> p.add_constraint( x< 1 ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_constraint(c): c is a strict inequality.
-
add_constraints()¶ Add constraints to the polyhedron.
Adds a copy of constraints in
csto the system of constraints ofself, without minimizing the result.See alse
add_constraint().INPUT:
cs– theConstraint_Systemthat will be added to the system of constraints ofself.
OUTPUT:
This method modifies the polyhedron
selfand does not return anything.Raises a
ValueErrorifselfand the constraints incsare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, Constraint_System >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert(x>=0) >>> cs.insert(y>=0) >>> p = C_Polyhedron( y<=1 ) >>> p.add_constraints(cs)
We just added a 1-d constraint to a 2-d polyhedron, this is fine. The other way is not:
>>> p = C_Polyhedron( x<=1 ) >>> p.add_constraints(cs) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_recycled_constraints(cs): this->space_dimension() == 1, cs.space_dimension() == 2.
The constraints must also be topology-compatible, that is,
C_Polyhedrononly allows non-strict inequalities:>>> p = C_Polyhedron( x>=0 ) >>> p.add_constraints( Constraint_System(x<0) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_recycled_constraints(cs): cs contains strict inequalities.
-
add_generator()¶ Add a generator to the polyhedron.
Adds a copy of constraint
cto the system of generators ofself, without minimizing the result.INPUT:
g– theGeneratorthat will be added to the system of Generators ofself.
OUTPUT:
This method modifies the polyhedron
selfand does not return anything.Raises a
ValueErrorifselfand the generatorgare topology-incompatible or dimension-incompatible, or ifselfis an empty polyhedron andgis not a point.Examples:
>>> from ppl import Variable, C_Polyhedron, point, closure_point, ray >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron(1, 'empty') >>> p.add_generator( point(0*x) )
We just added a 1-d generator to a 2-d polyhedron, this is fine. The other way is not:>>> p = C_Polyhedron(1, 'empty') >>> p.add_generator( point(0*y) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_generator(g): this->space_dimension() == 1, g.space_dimension() == 2.
The constraint must also be topology-compatible, that is,C_Polyhedrondoes not allowclosure_point()generators:>>> p = C_Polyhedron( point(0*x+0*y) ) >>> p.add_generator( closure_point(0*x) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_generator(g): g is a closure point.
Finally, ever non-empty polyhedron must have at least one point generator:
>>> p = C_Polyhedron(3, 'empty') >>> p.add_generator( ray(x) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_generator(g): *this is an empty polyhedron and g is not a point.
-
add_generators()¶ Add generators to the polyhedron.
Adds a copy of the generators in
gsto the system of generators ofself, without minimizing the result.See alse
add_generator().INPUT:
gs– theGenerator_Systemthat will be added to the system of constraints ofself.
OUTPUT:
This method modifies the polyhedron
selfand does not return anything.Raises a
ValueErrorifselfand one of the generators ingsare topology-incompatible or dimension-incompatible, or ifselfis an empty polyhedron andgsdoes not contain a point.Examples:
>>> from ppl import Variable, C_Polyhedron, Generator_System, point, ray, closure_point >>> x = Variable(0) >>> y = Variable(1) >>> gs = Generator_System() >>> gs.insert(point(0*x+0*y)) >>> gs.insert(point(1*x+1*y)) >>> p = C_Polyhedron(2, 'empty') >>> p.add_generators(gs)
We just added a 1-d constraint to a 2-d polyhedron, this is fine. The other way is not:
>>> p = C_Polyhedron(1, 'empty') >>> p.add_generators(gs) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_recycled_generators(gs): this->space_dimension() == 1, gs.space_dimension() == 2.
The constraints must also be topology-compatible, that is,
C_Polyhedrondoes not allowclosure_point()generators:>>> p = C_Polyhedron( point(0*x+0*y) ) >>> p.add_generators( Generator_System(closure_point(x) )) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_recycled_generators(gs): gs contains closure points.
-
add_space_dimensions_and_embed()¶ Add
mnew space dimensions and embedselfin the new vector space.The new space dimensions will be those having the highest indexes in the new polyhedron, which is characterized by a system of constraints in which the variables running through the new dimensions are not constrained. For instance, when starting from the polyhedron P and adding a third space dimension, the result will be the polyhedron
\[\Big\{ (x,y,z)^T \in \mathbb{R}^3 \Big| (x,y)^T \in P \Big\}\]INPUT:
m– integer.
OUTPUT:
This method assigns the embedded polyhedron to
selfand does not return anything.Raises a
ValueErrorif addingmnew space dimensions would cause the vector space to exceed dimensionself.max_space_dimension().Examples:
>>> from ppl import Variable, C_Polyhedron, point >>> x = Variable(0) >>> p = C_Polyhedron( point(3*x) ) >>> p.add_space_dimensions_and_embed(1) >>> p.minimized_generators() Generator_System {line(0, 1), point(3/1, 0/1)} >>> p.add_space_dimensions_and_embed( p.max_space_dimension() ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_space_dimensions_and_embed(m): adding m new space dimensions exceeds the maximum allowed space dimension.
-
add_space_dimensions_and_project()¶ Add
mnew space dimensions and embedselfin the new vector space.The new space dimensions will be those having the highest indexes in the new polyhedron, which is characterized by a system of constraints in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the polyhedron P and adding a third space dimension, the result will be the polyhedron
\[\Big\{ (x,y,0)^T \in \mathbb{R}^3 \Big| (x,y)^T \in P \Big\}\]INPUT:
m– integer.
OUTPUT:
This method assigns the projected polyhedron to
selfand does not return anything.Raises a
ValueErrorif addingmnew space dimensions would cause the vector space to exceed dimensionself.max_space_dimension().Examples:
>>> from ppl import Variable, C_Polyhedron, point >>> x = Variable(0) >>> p = C_Polyhedron( point(3*x) ) >>> p.add_space_dimensions_and_project(1) >>> p.minimized_generators() Generator_System {point(3/1, 0/1)} >>> p.add_space_dimensions_and_project( p.max_space_dimension() ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::add_space_dimensions_and_project(m): adding m new space dimensions exceeds the maximum allowed space dimension.
-
affine_dimension()¶ Return the affine dimension of
self.OUTPUT:
An integer. Returns 0 if
selfis empty. Otherwise, returns the affine dimension ofself.Examples:
>>> from ppl import Variable, C_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron( 5*x-2*y == x+y-1 ) >>> p.affine_dimension() 1
-
ascii_dump()¶ Write an ASCII dump to stderr.
Examples:
>>> cmd = 'from ppl import C_Polyhedron, Variable\n' >>> cmd += 'x = Variable(0)\n' >>> cmd += 'y = Variable(1)\n' >>> cmd += 'p = C_Polyhedron(3*x+2*y==1)\n' >>> cmd += 'p.minimized_generators()\n' >>> cmd += 'p.ascii_dump()\n' >>> from subprocess import Popen, PIPE >>> import sys >>> proc = Popen([sys.executable, '-c', cmd], stdout=PIPE, stderr=PIPE) >>> out, err = proc.communicate() >>> len(out) 0 >>> print(str(err.decode('ascii'))) space_dim 2 ... con_sys (up-to-date) topology NECESSARILY_CLOSED ... sat_c 0 x 0 sat_g 2 x 2 0 0 0 1
-
bounds_from_above()¶ Test whether the
expris bounded from above.INPUT:
expr– aLinear_Expression
OUTPUT:
Boolean. Returns
Trueif and only ifexpris bounded from above inself.Raises a
ValueErrorifexprandthisare dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, Linear_Expression >>> x = Variable(0); y = Variable(1) >>> p = C_Polyhedron(y<=0) >>> p.bounds_from_above(x+1) False >>> p.bounds_from_above(Linear_Expression(y)) True >>> p = C_Polyhedron(x<=0) >>> p.bounds_from_above(y+1) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::bounds_from_above(e): this->space_dimension() == 1, e.space_dimension() == 2.
-
bounds_from_below()¶ Test whether the
expris bounded from above.INPUT:
expr– aLinear_Expression
OUTPUT:
Boolean. Returns
Trueif and only ifexpris bounded from above inself.Raises a
ValueErrorifexprandthisare dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, Linear_Expression >>> x = Variable(0); y = Variable(1) >>> p = C_Polyhedron(y>=0) >>> p.bounds_from_below(x+1) False >>> p.bounds_from_below(Linear_Expression(y)) True >>> p = C_Polyhedron(x<=0) >>> p.bounds_from_below(y+1) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::bounds_from_below(e): this->space_dimension() == 1, e.space_dimension() == 2.
-
concatenate_assign()¶ Assign to
selfthe concatenation ofselfandy.This functions returns the Cartiesian product of
selfandy.Viewing a polyhedron as a set of tuples (its points), it is sometimes useful to consider the set of tuples obtained by concatenating an ordered pair of polyhedra. Formally, the concatenation of the polyhedra P and Q (taken in this order) is the polyhedron such that
\[R = \Big\{ (x_0,\dots,x_{n-1},y_0,\dots,y_{m-1})^T \in \mathbb{R}^{n+m} \Big| (x_0,\dots,x_{n-1})^T \in P ,~ (y_0,\dots,y_{m-1})^T \in Q \Big\}\]Another way of seeing it is as follows: first embed polyhedron P into a vector space of dimension n+m and then add a suitably renamed-apart version of the constraints defining Q.
INPUT:
m– integer.
OUTPUT:
This method assigns the concatenated polyhedron to
selfand does not return anything.Raises a
ValueErrorifselfandyare topology-incompatible or if addingy.space_dimension()new space dimensions would cause the vector space to exceed dimensionself.max_space_dimension().Examples:
>>> from ppl import Variable, C_Polyhedron, NNC_Polyhedron, point >>> x = Variable(0) >>> p1 = C_Polyhedron( point(1*x) ) >>> p2 = C_Polyhedron( point(2*x) ) >>> p1.concatenate_assign(p2) >>> p1.minimized_generators() Generator_System {point(1/1, 2/1)}
The polyhedra must be topology-compatible and not exceed the maximum space dimension:
>>> p1.concatenate_assign( NNC_Polyhedron(1, 'universe') ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::concatenate_assign(y): y is a NNC_Polyhedron. >>> p1.concatenate_assign( C_Polyhedron(p1.max_space_dimension(), 'empty') ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::concatenate_assign(y): concatenation exceeds the maximum allowed space dimension.
-
constrains()¶ Test whether
varis constrained inself.INPUT:
var– aVariable.
OUTPUT:
Boolean. Returns
Trueif and only ifvaris constrained inself.Raises a
ValueErrorifvaris not a space dimension ofself.Examples:
>>> from ppl import Variable, C_Polyhedron >>> x = Variable(0) >>> p = C_Polyhedron(1, 'universe') >>> p.constrains(x) False >>> p = C_Polyhedron(x>=0) >>> p.constrains(x) True >>> y = Variable(1) >>> p.constrains(y) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::constrains(v): this->space_dimension() == 1, v.space_dimension() == 2.
-
constraints()¶ Returns the system of constraints.
See also
minimized_constraints().OUTPUT:
Examples:
>>> from ppl import Variable, C_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron(y >= 0) >>> p.add_constraint(x >= 0) >>> p.add_constraint(x+y >= 0) >>> p.constraints() Constraint_System {x1>=0, x0>=0, x0+x1>=0} >>> p.minimized_constraints() Constraint_System {x1>=0, x0>=0}
-
contains()¶ Test whether
selfcontainsy.INPUT:
y– aPolyhedron.
OUTPUT:
Boolean. Returns
Trueif and only ifselfcontainsy.Raises a
ValueErrorifselfandyare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, NNC_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p0 = C_Polyhedron( x>=0 ) >>> p1 = C_Polyhedron( x>=1 ) >>> p0.contains(p1) True >>> p1.contains(p0) False
Errors are raised if the dimension or topology is not compatible:
>>> p0.contains(C_Polyhedron(y>=0)) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::contains(y): this->space_dimension() == 1, y.space_dimension() == 2. >>> p0.contains(NNC_Polyhedron(x>0)) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::contains(y): y is a NNC_Polyhedron.
-
contains_integer_point()¶ Test whether
selfcontains an integer point.OUTPUT:
Boolean. Returns
Trueif and only ifselfcontains an integer point.Examples:
>>> from ppl import Variable, NNC_Polyhedron >>> x = Variable(0) >>> p = NNC_Polyhedron(x>0) >>> p.add_constraint(x<1) >>> p.contains_integer_point() False >>> p.topological_closure_assign() >>> p.contains_integer_point() True
-
difference_assign()¶ Assign to
selfthe poly-difference ofselfandy.For any pair of NNC polyhedra P_1 and P_2 the convex polyhedral difference (or poly-difference) of P_1 and P_2 is defined as the smallest convex polyhedron containing the set-theoretic difference P_1setminus P_2 of P_1 and P_2.
In general, even if P_1 and P_2 are topologically closed polyhedra, their poly-difference may be a convex polyhedron that is not topologically closed. For this reason, when computing the poly-difference of two
C_Polyhedron, the library will enforce the topological closure of the result.INPUT:
y– aPolyhedron
OUTPUT:
This method assigns the poly-difference to
selfand does not return anything.Raises a
ValueErrorifselfand andyare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, point, closure_point, NNC_Polyhedron >>> x = Variable(0) >>> p = NNC_Polyhedron( point(0*x) ) >>> p.add_generator( point(1*x) ) >>> p.poly_difference_assign(NNC_Polyhedron( point(0*x) )) >>> p.minimized_constraints() Constraint_System {-x0+1>=0, x0>0}
The poly-difference of
C_polyhedronis really its closure:>>> p = C_Polyhedron( point(0*x) ) >>> p.add_generator( point(1*x) ) >>> p.poly_difference_assign(C_Polyhedron( point(0*x) )) >>> p.minimized_constraints() Constraint_System {x0>=0, -x0+1>=0}
selfandymust be dimension- and topology-compatible, or an exception is raised:>>> y = Variable(1) >>> p.poly_difference_assign( C_Polyhedron(y>=0) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::poly_difference_assign(y): this->space_dimension() == 1, y.space_dimension() == 2. >>> p.poly_difference_assign( NNC_Polyhedron(x+y<1) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::poly_difference_assign(y): y is a NNC_Polyhedron.
-
drop_some_non_integer_points()¶ Possibly tighten
selfby dropping some points with non-integer coordinates.The modified polyhedron satisfies:
- it is (not necessarily strictly) contained in the original polyhedron.
- integral vertices (generating points with integer coordinates) of the original polyhedron are not removed.
Note
The modified polyhedron is not neccessarily a lattice polyhedron; Some vertices will, in general, still be rational. Lattice points interior to the polyhedron may be lost in the process.
Examples:
>>> from ppl import Variable, NNC_Polyhedron, Constraint_System >>> x = Variable(0) >>> y = Variable(1) >>> cs = Constraint_System() >>> cs.insert( x>=0 ) >>> cs.insert( y>=0 ) >>> cs.insert( 3*x+2*y<5 ) >>> p = NNC_Polyhedron(cs) >>> p.minimized_generators() Generator_System {point(0/1, 0/1), closure_point(0/2, 5/2), closure_point(5/3, 0/3)} >>> p.drop_some_non_integer_points() >>> p.minimized_generators() Generator_System {point(0/1, 0/1), point(0/1, 2/1), point(4/3, 0/3)}
-
generators()¶ Returns the system of generators.
See also
minimized_generators().OUTPUT:
Examples:
>>> from ppl import Variable, C_Polyhedron, point >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron(3,'empty') >>> p.add_generator(point(-x-y)) >>> p.add_generator(point(0)) >>> p.add_generator(point(+x+y)) >>> p.generators() Generator_System {point(-1/1, -1/1, 0/1), point(0/1, 0/1, 0/1), point(1/1, 1/1, 0/1)} >>> p.minimized_generators() Generator_System {point(-1/1, -1/1, 0/1), point(1/1, 1/1, 0/1)}
-
intersection_assign()¶ Assign to
selfthe intersection ofselfandy.INPUT:
y– aPolyhedron
OUTPUT:
This method assigns the intersection to
selfand does not return anything.Raises a
ValueErrorifselfand andyare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, NNC_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron( 1*x+0*y >= 0 ) >>> p.intersection_assign( C_Polyhedron(y>=0) ) >>> p.constraints() Constraint_System {x0>=0, x1>=0} >>> z = Variable(2) >>> p.intersection_assign( C_Polyhedron(z>=0) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::intersection_assign(y): this->space_dimension() == 2, y.space_dimension() == 3. >>> p.intersection_assign( NNC_Polyhedron(x+y<1) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::intersection_assign(y): y is a NNC_Polyhedron.
-
is_bounded()¶ Test whether
selfis bounded.OUTPUT:
Boolean. Returns
Trueif and only ifselfis a bounded polyhedron.Examples:
>>> from ppl import Variable, NNC_Polyhedron, point, closure_point, ray >>> x = Variable(0) >>> p = NNC_Polyhedron( point(0*x) ) >>> p.add_generator( closure_point(1*x) ) >>> p.is_bounded() True >>> p.add_generator( ray(1*x) ) >>> p.is_bounded() False
-
is_discrete()¶ Test whether
selfis discrete.OUTPUT:
Boolean. Returns
Trueif and only ifselfis discrete.Examples:
>>> from ppl import Variable, C_Polyhedron, point, ray >>> x = Variable(0); y = Variable(1) >>> p = C_Polyhedron( point(1*x+2*y) ) >>> p.is_discrete() True >>> p.add_generator( point(x) ) >>> p.is_discrete() False
-
is_disjoint_from()¶ Tests whether
selfandyare disjoint.INPUT:
y– aPolyhedron.
OUTPUT:
Boolean. Returns
Trueif and only ifselfandyare disjoint.Rayises a
ValueErrorifselfandyare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, NNC_Polyhedron >>> x = Variable(0); y = Variable(1) >>> C_Polyhedron(x<=0).is_disjoint_from( C_Polyhedron(x>=1) ) True
This is not allowed:
>>> x = Variable(0); y = Variable(1) >>> poly_1d = C_Polyhedron(x<=0) >>> poly_2d = C_Polyhedron(x+0*y>=1) >>> poly_1d.is_disjoint_from(poly_2d) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::intersection_assign(y): this->space_dimension() == 1, y.space_dimension() == 2.
Nor is this:
>>> x = Variable(0); y = Variable(1) >>> c_poly = C_Polyhedron( x<=0 ) >>> nnc_poly = NNC_Polyhedron( x >0 ) >>> c_poly.is_disjoint_from(nnc_poly) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::intersection_assign(y): y is a NNC_Polyhedron. >>> NNC_Polyhedron(c_poly).is_disjoint_from(nnc_poly) True
-
is_empty()¶ Test if
selfis an empty polyhedron.OUTPUT:
Boolean.
Examples:
>>> from ppl import C_Polyhedron >>> C_Polyhedron(3, 'empty').is_empty() True >>> C_Polyhedron(3, 'universe').is_empty() False
-
is_topologically_closed()¶ Tests if
selfis topologically closed.OUTPUT:
Returns
Trueif and only ifselfis a topologically closed subset of the ambient vector space.Examples:
>>> from ppl import Variable, C_Polyhedron, NNC_Polyhedron >>> x = Variable(0); y = Variable(1) >>> C_Polyhedron(3, 'universe').is_topologically_closed() True >>> C_Polyhedron( x>=1 ).is_topologically_closed() True >>> NNC_Polyhedron( x>1 ).is_topologically_closed() False
-
is_universe()¶ Test if
selfis a universe (space-filling) polyhedron.OUTPUT:
Boolean.
Examples:
>>> from ppl import C_Polyhedron >>> C_Polyhedron(3, 'empty').is_universe() False >>> C_Polyhedron(3, 'universe').is_universe() True
-
max_space_dimension()¶ Return the maximum space dimension all kinds of Polyhedron can handle.
OUTPUT:
Integer.
Examples:
>>> from ppl import C_Polyhedron >>> C_Polyhedron(1, 'empty').max_space_dimension() > 2**20 True
-
maximize()¶ Maximize
expr.INPUT:
expr– aLinear_Expression.
OUTPUT:
A dictionary with the following keyword:value pair:
'bounded': Boolean. Whether the linear expressionexpris bounded from above onself.
If
expris bounded from above, the following additional keyword:value pairs are set to provide information about the supremum:'sup_n': Integer. The numerator of the supremum value.'sup_d': Non-zero integer. The denominator of the supremum value.'maximum': Boolean.Trueif and only if the supremum is also the maximum value.'generator': aGenerator. A point or closure point where expr reaches its supremum value.
Examples:
>>> from ppl import Variable, C_Polyhedron, NNC_Polyhedron, Constraint_System, Linear_Expression >>> x = Variable(0); y = Variable(1) >>> cs = Constraint_System() >>> cs.insert(x >= 0) >>> cs.insert(y >= 0) >>> cs.insert(3*x+5*y <= 10) >>> p = C_Polyhedron(cs) >>> pm = p.maximize(x+y) >>> for key in sorted(pm): ... print("{} {}".format(key, pm[key])) bounded True generator point(10/3, 0/3) maximum True sup_d 3 sup_n 10
Unbounded case:
>>> cs = Constraint_System() >>> cs.insert(x > 0) >>> p = NNC_Polyhedron(cs) >>> p.maximize(+x)
{‘bounded’: False} >>> pm = p.maximize(-x) >>> for key in sorted(pm): ... print(“{} {}”.format(key, pm[key])) bounded True generator closure_point(0/1) maximum False sup_d 1 sup_n 0
-
minimize()¶ Minimize
expr.INPUT:
expr– aLinear_Expression.
OUTPUT:
A dictionary with the following keyword:value pair:
'bounded': Boolean. Whether the linear expressionexpris bounded from below onself.
If
expris bounded from below, the following additional keyword:value pairs are set to provide information about the infimum:'inf_n': Integer. The numerator of the infimum value.'inf_d': Non-zero integer. The denominator of the infimum value.'minimum': Boolean.Trueif and only if the infimum is also the minimum value.'generator': aGenerator. A point or closure point where expr reaches its infimum value.
Examples:
>>> from ppl import Variable, C_Polyhedron, NNC_Polyhedron, Constraint_System, Linear_Expression >>> x = Variable(0); y = Variable(1) >>> cs = Constraint_System() >>> cs.insert( x>=0 ) >>> cs.insert( y>=0 ) >>> cs.insert( 3*x+5*y<=10 ) >>> p = C_Polyhedron(cs) >>> pm = p.minimize( x+y ) >>> for key in sorted(pm): ... print("{} {}".format(key, pm[key])) bounded True generator point(0/1, 0/1) inf_d 1 inf_n 0 minimum True
Unbounded case:
>>> cs = Constraint_System() >>> cs.insert(x > 0) >>> p = NNC_Polyhedron(cs) >>> pm = p.minimize(+x) >>> for key in sorted(pm): ... print("{} {}".format(key, pm[key])) bounded True generator closure_point(0/1) inf_d 1 inf_n 0 minimum False >>> p.minimize( -x ) {'bounded': False}
-
minimized_constraints()¶ Returns the minimized system of constraints.
See also
constraints().OUTPUT:
Examples:
>>> from ppl import Variable, C_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron(y >= 0) >>> p.add_constraint(x >= 0) >>> p.add_constraint(x+y >= 0) >>> p.constraints() Constraint_System {x1>=0, x0>=0, x0+x1>=0} >>> p.minimized_constraints() Constraint_System {x1>=0, x0>=0}
-
minimized_generators()¶ Returns the minimized system of generators.
See also
generators().OUTPUT:
Examples:
>>> from ppl import Variable, C_Polyhedron, point >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron(3,'empty') >>> p.add_generator(point(-x-y)) >>> p.add_generator(point(0)) >>> p.add_generator(point(+x+y)) >>> p.generators() Generator_System {point(-1/1, -1/1, 0/1), point(0/1, 0/1, 0/1), point(1/1, 1/1, 0/1)} >>> p.minimized_generators() Generator_System {point(-1/1, -1/1, 0/1), point(1/1, 1/1, 0/1)}
-
poly_difference_assign()¶ Assign to
selfthe poly-difference ofselfandy.For any pair of NNC polyhedra P_1 and P_2 the convex polyhedral difference (or poly-difference) of P_1 and P_2 is defined as the smallest convex polyhedron containing the set-theoretic difference P_1setminus P_2 of P_1 and P_2.
In general, even if P_1 and P_2 are topologically closed polyhedra, their poly-difference may be a convex polyhedron that is not topologically closed. For this reason, when computing the poly-difference of two
C_Polyhedron, the library will enforce the topological closure of the result.INPUT:
y– aPolyhedron
OUTPUT:
This method assigns the poly-difference to
selfand does not return anything.Raises a
ValueErrorifselfand andyare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, point, closure_point, NNC_Polyhedron >>> x = Variable(0) >>> p = NNC_Polyhedron( point(0*x) ) >>> p.add_generator( point(1*x) ) >>> p.poly_difference_assign(NNC_Polyhedron( point(0*x) )) >>> p.minimized_constraints() Constraint_System {-x0+1>=0, x0>0}
The poly-difference of
C_polyhedronis really its closure:>>> p = C_Polyhedron( point(0*x) ) >>> p.add_generator( point(1*x) ) >>> p.poly_difference_assign(C_Polyhedron( point(0*x) )) >>> p.minimized_constraints() Constraint_System {x0>=0, -x0+1>=0}
selfandymust be dimension- and topology-compatible, or an exception is raised:>>> y = Variable(1) >>> p.poly_difference_assign( C_Polyhedron(y>=0) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::poly_difference_assign(y): this->space_dimension() == 1, y.space_dimension() == 2. >>> p.poly_difference_assign( NNC_Polyhedron(x+y<1) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::poly_difference_assign(y): y is a NNC_Polyhedron.
-
poly_hull_assign()¶ Assign to
selfthe poly-hull ofselfandy.For any pair of NNC polyhedra P_1 and P_2, the convex polyhedral hull (or poly-hull) of is the smallest NNC polyhedron that includes both P_1 and P_2. The poly-hull of any pair of closed polyhedra in is also closed.
INPUT:
y– aPolyhedron
OUTPUT:
This method assigns the poly-hull to
selfand does not return anything.Raises a
ValueErrorifselfand andyare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, point, NNC_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron( point(1*x+0*y) ) >>> p.poly_hull_assign(C_Polyhedron( point(0*x+1*y) )) >>> p.generators() Generator_System {point(0/1, 1/1), point(1/1, 0/1)}
selfandymust be dimension- and topology-compatible, or an exception is raised:>>> z = Variable(2) >>> p.poly_hull_assign( C_Polyhedron(z>=0) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::poly_hull_assign(y): this->space_dimension() == 2, y.space_dimension() == 3. >>> p.poly_hull_assign( NNC_Polyhedron(x+y<1) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::poly_hull_assign(y): y is a NNC_Polyhedron.
-
relation_with()¶ Return the relations holding between the polyhedron
selfand the generator or constraintarg.INPUT:
arg– aGeneratoror aConstraint.
OUTPUT:
A
Poly_Gen_Relationor aPoly_Con_Relationaccording to the type of the input.Raises
ValueErrorifselfand the generator/constraintargare dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, point, ray >>> x = Variable(0); y = Variable(1) >>> p = C_Polyhedron(2, 'empty') >>> p.add_generator( point(1*x+0*y) ) >>> p.add_generator( point(0*x+1*y) ) >>> p.minimized_constraints() Constraint_System {x0+x1-1==0, -x1+1>=0, x1>=0} >>> p.relation_with( point(1*x+1*y) ) nothing >>> p.relation_with( point(1*x+1*y, 2) ) subsumes >>> p.relation_with( x+y==-1 ) is_disjoint >>> p.relation_with( x==y ) strictly_intersects >>> p.relation_with( x+y<=1 ) is_included, saturates >>> p.relation_with( x+y<1 ) is_disjoint, saturates
In a Python program you will usually use
relation_with()together withimplies()orimplies(), for example:>>> from ppl.wrappers import Poly_Con_Relation >>> p.relation_with( x+y<1 ).implies(Poly_Con_Relation.saturates()) True
You can only get relations with dimension-compatible generators or constraints:
>>> z = Variable(2) >>> p.relation_with( point(x+y+z) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::relation_with(g): this->space_dimension() == 2, g.space_dimension() == 3. >>> p.relation_with( z>0 ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::relation_with(c): this->space_dimension() == 2, c.space_dimension() == 3.
-
remove_higher_space_dimensions()¶ Remove the higher dimensions of the vector space so that the resulting space will have dimension
new_dimension.OUTPUT:
This method modifies
selfand does not return anything.Raises a
ValueErrorifnew_dimensionsis greater than the space dimension ofself.Examples:
>>> from ppl import C_Polyhedron, Variable >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron(3*x+0*y==2) >>> p.remove_higher_space_dimensions(1) >>> p.minimized_constraints() Constraint_System {3*x0-2==0} >>> p.remove_higher_space_dimensions(2) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::remove_higher_space_dimensions(nd): this->space_dimension() == 1, required space dimension == 2.
-
space_dimension()¶ Return the dimension of the vector space enclosing
self.OUTPUT:
Integer.
Examples:
>>> from ppl import Variable, C_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron( 5*x-2*y >= x+y-1 ) >>> p.space_dimension() 2
-
strictly_contains()¶ Test whether
selfstrictly containsy.INPUT:
y– aPolyhedron.
OUTPUT:
Boolean. Returns
Trueif and only ifselfcontainsyandselfdoes not equaly.Raises a
ValueErrorifselfandyare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, NNC_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p0 = C_Polyhedron( x>=0 ) >>> p1 = C_Polyhedron( x>=1 ) >>> p0.strictly_contains(p1) True >>> p1.strictly_contains(p0) False
Errors are raised if the dimension or topology is not compatible:
>>> p0.strictly_contains(C_Polyhedron(y>=0)) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::contains(y): this->space_dimension() == 1, y.space_dimension() == 2. >>> p0.strictly_contains(NNC_Polyhedron(x>0)) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::contains(y): y is a NNC_Polyhedron.
-
topological_closure_assign()¶ Assign to
selfits topological closure.Examples:
>>> from ppl import Variable, NNC_Polyhedron >>> x = Variable(0) >>> p = NNC_Polyhedron(x>0) >>> p.is_topologically_closed() False >>> p.topological_closure_assign() >>> p.is_topologically_closed() True >>> p.minimized_constraints() Constraint_System {x0>=0}
-
unconstrain()¶ Compute the cylindrification of
selfwith respect to space dimensionvar.INPUT:
var– aVariable. The space dimension that will be unconstrained. Exceptions:
OUTPUT:
This method assigns the cylindrification to
selfand does not return anything.Raises a
ValueErrorifvaris not a space dimension ofself.Examples:
>>> from ppl import Variable, C_Polyhedron, point >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron( point(x+y) ); p A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point >>> p.unconstrain(x); p A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 1 line >>> z = Variable(2) >>> p.unconstrain(z) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::unconstrain(var): this->space_dimension() == 2, required space dimension == 3.
-
upper_bound_assign()¶ Assign to
selfthe poly-hull ofselfandy.For any pair of NNC polyhedra P_1 and P_2, the convex polyhedral hull (or poly-hull) of is the smallest NNC polyhedron that includes both P_1 and P_2. The poly-hull of any pair of closed polyhedra in is also closed.
INPUT:
y– aPolyhedron
OUTPUT:
This method assigns the poly-hull to
selfand does not return anything.Raises a
ValueErrorifselfand andyare topology-incompatible or dimension-incompatible.Examples:
>>> from ppl import Variable, C_Polyhedron, point, NNC_Polyhedron >>> x = Variable(0) >>> y = Variable(1) >>> p = C_Polyhedron( point(1*x+0*y) ) >>> p.poly_hull_assign(C_Polyhedron( point(0*x+1*y) )) >>> p.generators() Generator_System {point(0/1, 1/1), point(1/1, 0/1)}
selfandymust be dimension- and topology-compatible, or an exception is raised:>>> z = Variable(2) >>> p.poly_hull_assign( C_Polyhedron(z>=0) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::poly_hull_assign(y): this->space_dimension() == 2, y.space_dimension() == 3. >>> p.poly_hull_assign( NNC_Polyhedron(x+y<1) ) Traceback (most recent call last): ... ValueError: PPL::C_Polyhedron::poly_hull_assign(y): y is a NNC_Polyhedron.
-
-
class
ppl.wrappers.Variable¶ Bases:
objectWrapper for PPL’s
Variableclass.A dimension of the vector space.
An object of the class Variable represents a dimension of the space, that is one of the Cartesian axes. Variables are used as basic blocks in order to build more complex linear expressions. Each variable is identified by a non-negative integer, representing the index of the corresponding Cartesian axis (the first axis has index 0). The space dimension of a variable is the dimension of the vector space made by all the Cartesian axes having an index less than or equal to that of the considered variable; thus, if a variable has index i, its space dimension is i+1.
INPUT:
i– integer. The index of the axis.
OUTPUT:
A
VariableExamples:
>>> from ppl import Variable >>> x = Variable(123) >>> x.id() 123 >>> x x123
Note that the “meaning” of an object of the class Variable is completely specified by the integer index provided to its constructor: be careful not to be mislead by C++ language variable names. For instance, in the following example the linear expressions
e1ande2are equivalent, since the two variablesxandzdenote the same Cartesian axis:>>> x = Variable(0) >>> y = Variable(1) >>> z = Variable(0) >>> e1 = x + y; e1 x0+x1 >>> e2 = y + z; e2 x0+x1 >>> e1 - e2 0
-
OK()¶ Checks if all the invariants are satisfied.
OUTPUT:
Boolean.
Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> x.OK() True
-
id()¶ Return the index of the Cartesian axis associated to the variable.
Examples:
>>> from ppl import Variable >>> x = Variable(123) >>> x.id() 123
-
space_dimension()¶ Return the dimension of the vector space enclosing
self.OUPUT:
Integer. The returned value is
self.id()+1.Examples:
>>> from ppl import Variable >>> x = Variable(0) >>> x.space_dimension() 1
-
ppl.wrappers.closure_point()¶ Construct a closure point.
A closure point is a point of the topological closure of a polyhedron that is not a point of the polyhedron itself.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).divisor– an integer.
OUTPUT:
A new
Generatorrepresenting the point.Raises a
ValueError` if ``divisor==0.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.closure_point(2*y+7, 3) closure_point(0/3, 2/3) >>> Generator.closure_point(y+7, 3) closure_point(0/3, 1/3) >>> Generator.closure_point(7, 3) closure_point() >>> Generator.closure_point(0, 0) Traceback (most recent call last): ... ValueError: PPL::closure_point(e, d): d == 0.
-
ppl.wrappers.equation()¶ Constuct an equation.
INPUT:
expression– aLinear_Expression.
OUTPUT:
The equation
expression== 0.Examples:
>>> from ppl import Variable, equation >>> y = Variable(1) >>> 2*y+1 == 0 2*x1+1==0 >>> equation(2*y+1) 2*x1+1==0
-
ppl.wrappers.inequality()¶ Constuct an inequality.
INPUT:
expression– aLinear_Expression.
OUTPUT:
The inequality
expression>= 0.Examples:
>>> from ppl import Variable, inequality >>> y = Variable(1) >>> 2*y+1 >= 0 2*x1+1>=0 >>> inequality(2*y+1) 2*x1+1>=0
-
ppl.wrappers.line()¶ Construct a line.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).
OUTPUT:
A new
Generatorrepresenting the line.Raises a
ValueError` if the homogeneous part of ``expressionrepresents the origin of the vector space.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.line(2*y) line(0, 1) >>> Generator.line(y) line(0, 1) >>> Generator.line(1) Traceback (most recent call last): ... ValueError: PPL::line(e): e == 0, but the origin cannot be a line.
-
ppl.wrappers.point()¶ Construct a point.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).divisor– an integer.
OUTPUT:
A new
Generatorrepresenting the point.Raises a
ValueError` if ``divisor==0.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.point(2*y+7, 3) point(0/3, 2/3) >>> Generator.point(y+7, 3) point(0/3, 1/3) >>> Generator.point(7, 3) point() >>> Generator.point(0, 0) Traceback (most recent call last): ... ValueError: PPL::point(e, d): d == 0.
-
ppl.wrappers.ray()¶ Construct a ray.
INPUT:
expression– aLinear_Expressionor something convertible to it (Variableor integer).
OUTPUT:
A new
Generatorrepresenting the ray.Raises a
ValueError` if the homogeneous part of ``expressionrepresents the origin of the vector space.Examples:
>>> from ppl import Generator, Variable >>> y = Variable(1) >>> Generator.ray(2*y) ray(0, 1) >>> Generator.ray(y) ray(0, 1) >>> Generator.ray(1) Traceback (most recent call last): ... ValueError: PPL::ray(e): e == 0, but the origin cannot be a ray.
-
ppl.wrappers.strict_inequality()¶ Constuct a strict inequality.
INPUT:
expression– aLinear_Expression.
OUTPUT:
The inequality
expression> 0.Examples:
>>> from ppl import Variable, strict_inequality >>> y = Variable(1) >>> 2*y+1 > 0 2*x1+1>0 >>> strict_inequality(2*y+1) 2*x1+1>0