Double Description Algorithm for Cones

This module implements the double description algorithm for extremal vertex enumeration in a pointed cone following [FP1996]. With a little bit of preprocessing (see double_description_inhomogeneous) this defines a backend for polyhedral computations. But as far as this module is concerned, inequality always means without a constant term and the origin is always a point of the cone.

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
sage: alg = StandardAlgorithm(A);  alg
Pointed cone with inequalities
(1, 0, 1)
(0, 1, 1)
(-1, -1, 1)
sage: DD, _ = alg.initial_pair();  DD
Double description pair (A, R) defined by
    [ 1  0  1]        [ 2/3 -1/3 -1/3]
A = [ 0  1  1],   R = [-1/3  2/3 -1/3]
    [-1 -1  1]        [ 1/3  1/3  1/3]
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> A = matrix(QQ, [(Integer(1),Integer(0),Integer(1)), (Integer(0),Integer(1),Integer(1)), (-Integer(1),-Integer(1),Integer(1))])
>>> alg = StandardAlgorithm(A);  alg
Pointed cone with inequalities
(1, 0, 1)
(0, 1, 1)
(-1, -1, 1)
>>> DD, _ = alg.initial_pair();  DD
Double description pair (A, R) defined by
    [ 1  0  1]        [ 2/3 -1/3 -1/3]
A = [ 0  1  1],   R = [-1/3  2/3 -1/3]
    [-1 -1  1]        [ 1/3  1/3  1/3]
from sage.geometry.polyhedron.double_description import StandardAlgorithm
A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
alg = StandardAlgorithm(A);  alg
DD, _ = alg.initial_pair();  DD

The implementation works over any exact field that is embedded in \(\RR\), for example:

sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1),            # needs sage.rings.number_field
....:                 (-AA(3).sqrt(),-AA(2).sqrt(),1)])
sage: alg = StandardAlgorithm(A)
sage: alg.run().R                                                                   # needs sage.rings.number_field
[(-0.4177376677004119?, 0.5822623322995881?, 0.4177376677004119?),
 (-0.2411809548974793?, -0.2411809548974793?, 0.2411809548974793?),
 (0.07665629029830300?, 0.07665629029830300?, 0.2411809548974793?),
 (0.5822623322995881?, -0.4177376677004119?, 0.4177376677004119?)]
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> A = matrix(AA, [(Integer(1),Integer(0),Integer(1)), (Integer(0),Integer(1),Integer(1)), (-AA(Integer(2)).sqrt(),-AA(Integer(3)).sqrt(),Integer(1)),            # needs sage.rings.number_field
...                 (-AA(Integer(3)).sqrt(),-AA(Integer(2)).sqrt(),Integer(1))])
>>> alg = StandardAlgorithm(A)
>>> alg.run().R                                                                   # needs sage.rings.number_field
[(-0.4177376677004119?, 0.5822623322995881?, 0.4177376677004119?),
 (-0.2411809548974793?, -0.2411809548974793?, 0.2411809548974793?),
 (0.07665629029830300?, 0.07665629029830300?, 0.2411809548974793?),
 (0.5822623322995881?, -0.4177376677004119?, 0.4177376677004119?)]
from sage.geometry.polyhedron.double_description import StandardAlgorithm
A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1),            # needs sage.rings.number_field
                (-AA(3).sqrt(),-AA(2).sqrt(),1)])
alg = StandardAlgorithm(A)
alg.run().R                                                                   # needs sage.rings.number_field
class sage.geometry.polyhedron.double_description.DoubleDescriptionPair(problem, A_rows, R_cols)[source]

Bases: object

Base class for a double description pair \((A, R)\).

Warning

You should use the Problem.initial_pair() or Problem.run() to generate double description pairs for a set of inequalities, and not generate DoubleDescriptionPair instances directly.

INPUT:

  • problem – instance of Problem

  • A_rows – list of row vectors of the matrix \(A\); these encode the inequalities

  • R_cols – list of column vectors of the matrix \(R\); these encode the rays

R_by_sign(a)[source]

Classify the rays into those that are positive, zero, and negative on \(a\).

INPUT:

  • a – vector; coefficient vector of a homogeneous inequality

OUTPUT:

A triple consisting of the rays (columns of \(R\)) that are positive, zero, and negative on \(a\). In that order.

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
sage: DD, _ = StandardAlgorithm(A).initial_pair()
sage: DD.R_by_sign(vector([1,-1,0]))
([(2/3, -1/3, 1/3)], [(-1/3, -1/3, 1/3)], [(-1/3, 2/3, 1/3)])
sage: DD.R_by_sign(vector([1,1,1]))
([(2/3, -1/3, 1/3), (-1/3, 2/3, 1/3)], [], [(-1/3, -1/3, 1/3)])
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> A = matrix(QQ, [(Integer(1),Integer(0),Integer(1)), (Integer(0),Integer(1),Integer(1)), (-Integer(1),-Integer(1),Integer(1))])
>>> DD, _ = StandardAlgorithm(A).initial_pair()
>>> DD.R_by_sign(vector([Integer(1),-Integer(1),Integer(0)]))
([(2/3, -1/3, 1/3)], [(-1/3, -1/3, 1/3)], [(-1/3, 2/3, 1/3)])
>>> DD.R_by_sign(vector([Integer(1),Integer(1),Integer(1)]))
([(2/3, -1/3, 1/3), (-1/3, 2/3, 1/3)], [], [(-1/3, -1/3, 1/3)])
from sage.geometry.polyhedron.double_description import StandardAlgorithm
A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
DD, _ = StandardAlgorithm(A).initial_pair()
DD.R_by_sign(vector([1,-1,0]))
DD.R_by_sign(vector([1,1,1]))
are_adjacent(r1, r2)[source]

Return whether the two rays are adjacent.

INPUT:

  • r1, r2 – two rays

OUTPUT: boolean; whether the two rays are adjacent

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
sage: DD = StandardAlgorithm(A).run()
sage: DD.are_adjacent(DD.R[0], DD.R[1])
True
sage: DD.are_adjacent(DD.R[0], DD.R[2])
True
sage: DD.are_adjacent(DD.R[0], DD.R[3])
False
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> A = matrix(QQ, [(Integer(0),Integer(1),Integer(0)), (Integer(1),Integer(0),Integer(0)), (Integer(0),-Integer(1),Integer(1)), (-Integer(1),Integer(0),Integer(1))])
>>> DD = StandardAlgorithm(A).run()
>>> DD.are_adjacent(DD.R[Integer(0)], DD.R[Integer(1)])
True
>>> DD.are_adjacent(DD.R[Integer(0)], DD.R[Integer(2)])
True
>>> DD.are_adjacent(DD.R[Integer(0)], DD.R[Integer(3)])
False
from sage.geometry.polyhedron.double_description import StandardAlgorithm
A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
DD = StandardAlgorithm(A).run()
DD.are_adjacent(DD.R[0], DD.R[1])
DD.are_adjacent(DD.R[0], DD.R[2])
DD.are_adjacent(DD.R[0], DD.R[3])
cone()[source]

Return the cone defined by \(A\).

This method is for debugging only. Assumes that the base ring is \(\QQ\).

OUTPUT:

The cone defined by the inequalities as a Polyhedron(), using the PPL backend.

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
sage: DD, _ = StandardAlgorithm(A).initial_pair()
sage: DD.cone().Hrepresentation()
(An inequality (-1, -1, 1) x + 0 >= 0,
 An inequality (0, 1, 1) x + 0 >= 0,
 An inequality (1, 0, 1) x + 0 >= 0)
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> A = matrix(QQ, [(Integer(1),Integer(0),Integer(1)), (Integer(0),Integer(1),Integer(1)), (-Integer(1),-Integer(1),Integer(1))])
>>> DD, _ = StandardAlgorithm(A).initial_pair()
>>> DD.cone().Hrepresentation()
(An inequality (-1, -1, 1) x + 0 >= 0,
 An inequality (0, 1, 1) x + 0 >= 0,
 An inequality (1, 0, 1) x + 0 >= 0)
from sage.geometry.polyhedron.double_description import StandardAlgorithm
A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
DD, _ = StandardAlgorithm(A).initial_pair()
DD.cone().Hrepresentation()
dual()[source]

Return the dual.

OUTPUT:

For the double description pair \((A, R)\) this method returns the dual double description pair \((R^T, A^T)\)

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import Problem
sage: A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
sage: DD, _ = Problem(A).initial_pair()
sage: DD
Double description pair (A, R) defined by
    [ 0  1  0]        [0 1 0]
A = [ 1  0  0],   R = [1 0 0]
    [ 0 -1  1]        [1 0 1]
sage: DD.dual()
 Double description pair (A, R) defined by
    [0 1 1]        [ 0  1  0]
A = [1 0 0],   R = [ 1  0 -1]
    [0 0 1]        [ 0  0  1]
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import Problem
>>> A = matrix(QQ, [(Integer(0),Integer(1),Integer(0)), (Integer(1),Integer(0),Integer(0)), (Integer(0),-Integer(1),Integer(1)), (-Integer(1),Integer(0),Integer(1))])
>>> DD, _ = Problem(A).initial_pair()
>>> DD
Double description pair (A, R) defined by
    [ 0  1  0]        [0 1 0]
A = [ 1  0  0],   R = [1 0 0]
    [ 0 -1  1]        [1 0 1]
>>> DD.dual()
 Double description pair (A, R) defined by
    [0 1 1]        [ 0  1  0]
A = [1 0 0],   R = [ 1  0 -1]
    [0 0 1]        [ 0  0  1]
from sage.geometry.polyhedron.double_description import Problem
A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
DD, _ = Problem(A).initial_pair()
DD
DD.dual()
first_coordinate_plane()[source]

Restrict to the first coordinate plane.

OUTPUT:

A new double description pair with the constraint \(x_0 = 0\) added.

EXAMPLES:

sage: A = matrix([(1, 1), (-1, 1)])
sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: DD, _ = StandardAlgorithm(A).initial_pair()
sage: DD
Double description pair (A, R) defined by
A = [ 1  1],   R = [ 1/2 -1/2]
    [-1  1]        [ 1/2  1/2]
sage: DD.first_coordinate_plane()
Double description pair (A, R) defined by
    [ 1  1]
A = [-1  1],   R = [  0]
    [-1  0]        [1/2]
    [ 1  0]
>>> from sage.all import *
>>> A = matrix([(Integer(1), Integer(1)), (-Integer(1), Integer(1))])
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> DD, _ = StandardAlgorithm(A).initial_pair()
>>> DD
Double description pair (A, R) defined by
A = [ 1  1],   R = [ 1/2 -1/2]
    [-1  1]        [ 1/2  1/2]
>>> DD.first_coordinate_plane()
Double description pair (A, R) defined by
    [ 1  1]
A = [-1  1],   R = [  0]
    [-1  0]        [1/2]
    [ 1  0]
A = matrix([(1, 1), (-1, 1)])
from sage.geometry.polyhedron.double_description import StandardAlgorithm
DD, _ = StandardAlgorithm(A).initial_pair()
DD
DD.first_coordinate_plane()
inner_product_matrix()[source]

Return the inner product matrix between the rows of \(A\) and the columns of \(R\).

OUTPUT:

A matrix over the base ring. There is one row for each row of \(A\) and one column for each column of \(R\).

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
sage: alg = StandardAlgorithm(A)
sage: DD, _ = alg.initial_pair()
sage: DD.inner_product_matrix()
[1 0 0]
[0 1 0]
[0 0 1]
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> A = matrix(QQ, [(Integer(1),Integer(0),Integer(1)), (Integer(0),Integer(1),Integer(1)), (-Integer(1),-Integer(1),Integer(1))])
>>> alg = StandardAlgorithm(A)
>>> DD, _ = alg.initial_pair()
>>> DD.inner_product_matrix()
[1 0 0]
[0 1 0]
[0 0 1]
from sage.geometry.polyhedron.double_description import StandardAlgorithm
A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
alg = StandardAlgorithm(A)
DD, _ = alg.initial_pair()
DD.inner_product_matrix()
is_extremal(ray)[source]

Test whether the ray is extremal.

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
sage: DD = StandardAlgorithm(A).run()
sage: DD.is_extremal(DD.R[0])
True
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> A = matrix(QQ, [(Integer(0),Integer(1),Integer(0)), (Integer(1),Integer(0),Integer(0)), (Integer(0),-Integer(1),Integer(1)), (-Integer(1),Integer(0),Integer(1))])
>>> DD = StandardAlgorithm(A).run()
>>> DD.is_extremal(DD.R[Integer(0)])
True
from sage.geometry.polyhedron.double_description import StandardAlgorithm
A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
DD = StandardAlgorithm(A).run()
DD.is_extremal(DD.R[0])
matrix_space(nrows, ncols)[source]

Return a matrix space of size nrows and ncols over the base ring of self.

These matrix spaces are cached to avoid their creation in the very demanding add_inequality() and more precisely are_adjacent().

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import Problem
sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
sage: DD, _ = Problem(A).initial_pair()
sage: DD.matrix_space(2,2)
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: DD.matrix_space(3,2)
Full MatrixSpace of 3 by 2 dense matrices over Rational Field

sage: # needs sage.rings.number_field
sage: K.<sqrt2> = QuadraticField(2)
sage: A = matrix([[1,sqrt2],[2,0]])
sage: DD, _  = Problem(A).initial_pair()
sage: DD.matrix_space(1,2)
Full MatrixSpace of 1 by 2 dense matrices
 over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import Problem
>>> A = matrix(QQ, [(Integer(1),Integer(0),Integer(1)), (Integer(0),Integer(1),Integer(1)), (-Integer(1),-Integer(1),Integer(1))])
>>> DD, _ = Problem(A).initial_pair()
>>> DD.matrix_space(Integer(2),Integer(2))
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
>>> DD.matrix_space(Integer(3),Integer(2))
Full MatrixSpace of 3 by 2 dense matrices over Rational Field

>>> # needs sage.rings.number_field
>>> K = QuadraticField(Integer(2), names=('sqrt2',)); (sqrt2,) = K._first_ngens(1)
>>> A = matrix([[Integer(1),sqrt2],[Integer(2),Integer(0)]])
>>> DD, _  = Problem(A).initial_pair()
>>> DD.matrix_space(Integer(1),Integer(2))
Full MatrixSpace of 1 by 2 dense matrices
 over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?
from sage.geometry.polyhedron.double_description import Problem
A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
DD, _ = Problem(A).initial_pair()
DD.matrix_space(2,2)
DD.matrix_space(3,2)
# needs sage.rings.number_field
K.<sqrt2> = QuadraticField(2)
A = matrix([[1,sqrt2],[2,0]])
DD, _  = Problem(A).initial_pair()
DD.matrix_space(1,2)
verify()[source]

Validate the double description pair.

This method used the PPL backend to check that the double description pair is valid. An assertion is triggered if it is not. Does nothing if the base ring is not \(\QQ\).

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import \
....:     DoubleDescriptionPair, Problem
sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
sage: alg = Problem(A)
sage: DD = DoubleDescriptionPair(alg,
....:     [(1, 0, 3), (0, 1, 1), (-1, -1, 1)],
....:     [(2/3, -1/3, 1/3), (-1/3, 2/3, 1/3), (-1/3, -1/3, 1/3)])
sage: DD.verify()
Traceback (most recent call last):
...
    assert A_cone == R_cone
AssertionError
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import     DoubleDescriptionPair, Problem
>>> A = matrix(QQ, [(Integer(1),Integer(0),Integer(1)), (Integer(0),Integer(1),Integer(1)), (-Integer(1),-Integer(1),Integer(1))])
>>> alg = Problem(A)
>>> DD = DoubleDescriptionPair(alg,
...     [(Integer(1), Integer(0), Integer(3)), (Integer(0), Integer(1), Integer(1)), (-Integer(1), -Integer(1), Integer(1))],
...     [(Integer(2)/Integer(3), -Integer(1)/Integer(3), Integer(1)/Integer(3)), (-Integer(1)/Integer(3), Integer(2)/Integer(3), Integer(1)/Integer(3)), (-Integer(1)/Integer(3), -Integer(1)/Integer(3), Integer(1)/Integer(3))])
>>> DD.verify()
Traceback (most recent call last):
...
    assert A_cone == R_cone
AssertionError
from sage.geometry.polyhedron.double_description import \
    DoubleDescriptionPair, Problem
A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
alg = Problem(A)
DD = DoubleDescriptionPair(alg,
    [(1, 0, 3), (0, 1, 1), (-1, -1, 1)],
    [(2/3, -1/3, 1/3), (-1/3, 2/3, 1/3), (-1/3, -1/3, 1/3)])
DD.verify()
zero_set(ray)[source]

Return the zero set (active set) \(Z(r)\).

INPUT:

  • ray – a ray vector

OUTPUT: a set containing the inequality vectors that are zero on ray

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import Problem
sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
sage: DD, _ = Problem(A).initial_pair()
sage: r = DD.R[0];  r
(2/3, -1/3, 1/3)
sage: DD.zero_set(r)
{(-1, -1, 1), (0, 1, 1)}
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import Problem
>>> A = matrix(QQ, [(Integer(1),Integer(0),Integer(1)), (Integer(0),Integer(1),Integer(1)), (-Integer(1),-Integer(1),Integer(1))])
>>> DD, _ = Problem(A).initial_pair()
>>> r = DD.R[Integer(0)];  r
(2/3, -1/3, 1/3)
>>> DD.zero_set(r)
{(-1, -1, 1), (0, 1, 1)}
from sage.geometry.polyhedron.double_description import Problem
A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
DD, _ = Problem(A).initial_pair()
r = DD.R[0];  r
DD.zero_set(r)
class sage.geometry.polyhedron.double_description.Problem(A)[source]

Bases: object

Base class for implementations of the double description algorithm.

It does not make sense to instantiate the base class directly, it just provides helpers for implementations.

INPUT:

  • A – a matrix; the rows of the matrix are interpreted as homogeneous inequalities \(A x \geq 0\). Must have maximal rank.

A()[source]

Return the rows of the defining matrix \(A\).

OUTPUT: the matrix \(A\) whose rows are the inequalities

EXAMPLES:

sage: A = matrix([(1, 1), (-1, 1)])
sage: from sage.geometry.polyhedron.double_description import Problem
sage: Problem(A).A()
((1, 1), (-1, 1))
>>> from sage.all import *
>>> A = matrix([(Integer(1), Integer(1)), (-Integer(1), Integer(1))])
>>> from sage.geometry.polyhedron.double_description import Problem
>>> Problem(A).A()
((1, 1), (-1, 1))
A = matrix([(1, 1), (-1, 1)])
from sage.geometry.polyhedron.double_description import Problem
Problem(A).A()
A_matrix()[source]

Return the defining matrix \(A\).

OUTPUT: matrix whose rows are the inequalities

EXAMPLES:

sage: A = matrix([(1, 1), (-1, 1)])
sage: from sage.geometry.polyhedron.double_description import Problem
sage: Problem(A).A_matrix()
[ 1  1]
[-1  1]
>>> from sage.all import *
>>> A = matrix([(Integer(1), Integer(1)), (-Integer(1), Integer(1))])
>>> from sage.geometry.polyhedron.double_description import Problem
>>> Problem(A).A_matrix()
[ 1  1]
[-1  1]
A = matrix([(1, 1), (-1, 1)])
from sage.geometry.polyhedron.double_description import Problem
Problem(A).A_matrix()
base_ring()[source]

Return the base field.

OUTPUT: a field

EXAMPLES:

sage: A = matrix(AA, [(1, 1), (-1, 1)])                                     # needs sage.rings.number_field
sage: from sage.geometry.polyhedron.double_description import Problem
sage: Problem(A).base_ring()                                                # needs sage.rings.number_field
Algebraic Real Field
>>> from sage.all import *
>>> A = matrix(AA, [(Integer(1), Integer(1)), (-Integer(1), Integer(1))])                                     # needs sage.rings.number_field
>>> from sage.geometry.polyhedron.double_description import Problem
>>> Problem(A).base_ring()                                                # needs sage.rings.number_field
Algebraic Real Field
A = matrix(AA, [(1, 1), (-1, 1)])                                     # needs sage.rings.number_field
from sage.geometry.polyhedron.double_description import Problem
Problem(A).base_ring()                                                # needs sage.rings.number_field
dim()[source]

Return the ambient space dimension.

OUTPUT: integer; the ambient space dimension of the cone

EXAMPLES:

sage: A = matrix(QQ, [(1, 1), (-1, 1)])
sage: from sage.geometry.polyhedron.double_description import Problem
sage: Problem(A).dim()
2
>>> from sage.all import *
>>> A = matrix(QQ, [(Integer(1), Integer(1)), (-Integer(1), Integer(1))])
>>> from sage.geometry.polyhedron.double_description import Problem
>>> Problem(A).dim()
2
A = matrix(QQ, [(1, 1), (-1, 1)])
from sage.geometry.polyhedron.double_description import Problem
Problem(A).dim()
initial_pair()[source]

Return an initial double description pair.

Picks an initial set of rays by selecting a basis. This is probably the most efficient way to select the initial set.

INPUT:

OUTPUT:

A pair consisting of a DoubleDescriptionPair instance and the tuple of remaining unused inequalities.

EXAMPLES:

sage: A = matrix([(-1, 1), (-1, 2), (1/2, -1/2), (1/2, 2)])
sage: from sage.geometry.polyhedron.double_description import Problem
sage: DD, remaining = Problem(A).initial_pair()
sage: DD.verify()
sage: remaining
[(1/2, -1/2), (1/2, 2)]
>>> from sage.all import *
>>> A = matrix([(-Integer(1), Integer(1)), (-Integer(1), Integer(2)), (Integer(1)/Integer(2), -Integer(1)/Integer(2)), (Integer(1)/Integer(2), Integer(2))])
>>> from sage.geometry.polyhedron.double_description import Problem
>>> DD, remaining = Problem(A).initial_pair()
>>> DD.verify()
>>> remaining
[(1/2, -1/2), (1/2, 2)]
A = matrix([(-1, 1), (-1, 2), (1/2, -1/2), (1/2, 2)])
from sage.geometry.polyhedron.double_description import Problem
DD, remaining = Problem(A).initial_pair()
DD.verify()
remaining
pair_class[source]

alias of DoubleDescriptionPair

class sage.geometry.polyhedron.double_description.StandardAlgorithm(A)[source]

Bases: Problem

Standard implementation of the double description algorithm.

See [FP1996] for the definition of the “Standard Algorithm”.

EXAMPLES:

sage: A = matrix(QQ, [(1, 1), (-1, 1)])
sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: DD = StandardAlgorithm(A).run()
sage: DD.R    # the extremal rays
[(1/2, 1/2), (-1/2, 1/2)]
>>> from sage.all import *
>>> A = matrix(QQ, [(Integer(1), Integer(1)), (-Integer(1), Integer(1))])
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> DD = StandardAlgorithm(A).run()
>>> DD.R    # the extremal rays
[(1/2, 1/2), (-1/2, 1/2)]
A = matrix(QQ, [(1, 1), (-1, 1)])
from sage.geometry.polyhedron.double_description import StandardAlgorithm
DD = StandardAlgorithm(A).run()
DD.R    # the extremal rays
pair_class[source]

alias of StandardDoubleDescriptionPair

run()[source]

Run the Standard Algorithm.

OUTPUT:

A double description pair \((A, R)\) of all inequalities as a DoubleDescriptionPair. By virtue of the double description algorithm, the columns of \(R\) are the extremal rays.

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
sage: StandardAlgorithm(A).run()
Double description pair (A, R) defined by
    [ 0  1  0]        [0 0 1 1]
A = [ 1  0  0],   R = [1 0 1 0]
    [ 0 -1  1]        [1 1 1 1]
    [-1  0  1]
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> A = matrix(QQ, [(Integer(0),Integer(1),Integer(0)), (Integer(1),Integer(0),Integer(0)), (Integer(0),-Integer(1),Integer(1)), (-Integer(1),Integer(0),Integer(1))])
>>> StandardAlgorithm(A).run()
Double description pair (A, R) defined by
    [ 0  1  0]        [0 0 1 1]
A = [ 1  0  0],   R = [1 0 1 0]
    [ 0 -1  1]        [1 1 1 1]
    [-1  0  1]
from sage.geometry.polyhedron.double_description import StandardAlgorithm
A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
StandardAlgorithm(A).run()
class sage.geometry.polyhedron.double_description.StandardDoubleDescriptionPair(problem, A_rows, R_cols)[source]

Bases: DoubleDescriptionPair

Double description pair for the “Standard Algorithm”.

See StandardAlgorithm.

add_inequality(a)[source]

Add the inequality a to the matrix \(A\) of the double description.

INPUT:

  • a – vector; an inequality

EXAMPLES:

sage: A = matrix([(-1, 1, 0), (-1, 2, 1), (1/2, -1/2, -1)])
sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
sage: DD, _ = StandardAlgorithm(A).initial_pair()
sage: DD.add_inequality(vector([1,0,0]))
sage: DD
Double description pair (A, R) defined by
    [  -1    1    0]        [   1    1    0    0]
A = [  -1    2    1],   R = [   1    1    1    1]
    [ 1/2 -1/2   -1]        [   0   -1 -1/2   -2]
    [   1    0    0]
>>> from sage.all import *
>>> A = matrix([(-Integer(1), Integer(1), Integer(0)), (-Integer(1), Integer(2), Integer(1)), (Integer(1)/Integer(2), -Integer(1)/Integer(2), -Integer(1))])
>>> from sage.geometry.polyhedron.double_description import StandardAlgorithm
>>> DD, _ = StandardAlgorithm(A).initial_pair()
>>> DD.add_inequality(vector([Integer(1),Integer(0),Integer(0)]))
>>> DD
Double description pair (A, R) defined by
    [  -1    1    0]        [   1    1    0    0]
A = [  -1    2    1],   R = [   1    1    1    1]
    [ 1/2 -1/2   -1]        [   0   -1 -1/2   -2]
    [   1    0    0]
A = matrix([(-1, 1, 0), (-1, 2, 1), (1/2, -1/2, -1)])
from sage.geometry.polyhedron.double_description import StandardAlgorithm
DD, _ = StandardAlgorithm(A).initial_pair()
DD.add_inequality(vector([1,0,0]))
DD
sage.geometry.polyhedron.double_description.random_inequalities(d, n)[source]

Random collections of inequalities for testing purposes.

INPUT:

  • d – integer; the dimension

  • n – integer; the number of random inequalities to generate

OUTPUT: a random set of inequalities as a StandardAlgorithm instance

EXAMPLES:

sage: from sage.geometry.polyhedron.double_description import random_inequalities
sage: P = random_inequalities(5, 10)
sage: P.run().verify()
>>> from sage.all import *
>>> from sage.geometry.polyhedron.double_description import random_inequalities
>>> P = random_inequalities(Integer(5), Integer(10))
>>> P.run().verify()
from sage.geometry.polyhedron.double_description import random_inequalities
P = random_inequalities(5, 10)
P.run().verify()