Coverage for local/lib/python2.7/site-packages/sage/geometry/polyhedron/double_description.py : 99%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" 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 :mod:`~sage.geometry.polyhedron.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]
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), ....: (-AA(3).sqrt(),-AA(2).sqrt(),1)]) sage: alg = StandardAlgorithm(A) sage: alg.run().R [(-0.4177376677004119?, 0.5822623322995881?, 0.4177376677004119?), (-0.2411809548974793?, -0.2411809548974793?, 0.2411809548974793?), (0.07665629029830300?, 0.07665629029830300?, 0.2411809548974793?), (0.5822623322995881?, -0.4177376677004119?, 0.4177376677004119?)] """
#***************************************************************************** # Copyright (C) 2014 Volker Braun <vbraun.name@gmail.com> # 2015 Vincent Delecroix <20100.delecroix@gmail.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #*****************************************************************************
#***************************************************************************** # TODO # # The adjacency check should use caching and the "combinatorial # criterion" instead of the "algebraic criterion", see [FP1996] # for definition. Since coefficient arithmetic is relatively expensive # we should avoid it as far as possible. # # Also, the variants of the double description algorithm described in # [FP1996] should be implemented. The design of this module is # such that variants of the basic algorithm should be easy to add as # subclasses of DoubleDescriptionPair and Problem. # *****************************************************************************
# Compare with PPL if the base ring is QQ. Can be left enabled since # we don't use the Python fallback for polyhedra over QQ unless you # construct one by hand.
""" 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 inequalites as a :class:`StandardAlgorithm` instance.
EXAMPLES::
sage: from sage.geometry.polyhedron.double_description import random_inequalities sage: P = random_inequalities(5, 10) sage: P.run().verify() """
r""" Base class for a double description pair `(A, R)`
.. warning::
You should use the :meth:`Problem.initial_pair` or :meth:`Problem.run` to generate double description pairs for a set of inequalities, and not generate ``DoubleDescriptionPair`` instances directly.
INPUT:
- ``problem`` -- instance of :class:`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.
TESTS::
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: DoubleDescriptionPair(alg, ....: [(1, 0, 1), (0, 1, 1), (-1, -1, 1)], ....: [(2/3, -1/3, 1/3), (-1/3, 2/3, 1/3), (-1/3, -1/3, 1/3)]) 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] """
# a cache for scalar products (see the method zero_set)
r""" Construct a new double description pair.
INPUT:
- ``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.
OUTPUT:
A new double description pair of the same (sub)class of :class:`DoubleDescriptionProblem`.
EXAMPLES::
sage: from sage.geometry.polyhedron.double_description import \ ....: DoubleDescriptionPair, StandardAlgorithm sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)]) sage: DD = StandardAlgorithm(A).run() sage: DDnew = DD._make_new(DD.A, DD.R); DDnew 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] sage: DDnew is DD False sage: DDnew.__class__ is DD.__class__ True """
r""" Return string representation.
OUTPUT:
String.
EXAMPLES::
sage: from sage.geometry.polyhedron.double_description import \ ....: DoubleDescriptionPair, StandardAlgorithm sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)]) sage: DD = StandardAlgorithm(A).run() sage: DD.__repr__() 'Double description pair (A, R) defined by\n [ 1 0 1] [ 2/3 -1/3 -1/3]\nA = [ 0 1 1], R = [-1/3 2/3 -1/3]\n [-1 -1 1] [ 1/3 1/3 1/3]' """ else: R._baseline = 0
""" 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] """
""" 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 :func:`~sage.geometry.polyhedron.constructor.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) """
return Polyhedron(vertices=[[0] * self.problem.dim()], backend='ppl') else:
r""" 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 """ base_ring=self.problem.base_ring(), backend='ppl')
""" 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)]) """ else:
""" 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)} """
""" 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 """
def matrix_space(self, nrows, ncols): r""" 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 :meth:`add_inequality` and more precisely :meth:`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: 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 """
""" 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 """
# here we try to create a matrix as fast as possible # since the generic matrix constructor is very slow (trac #18231)
""" 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] """
""" 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] """
""" 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.
TESTS::
sage: A = matrix([(1, 1), (-1, 1)]) sage: from sage.geometry.polyhedron.double_description import Problem sage: Problem(A) Pointed cone with inequalities (1, 1) (-1, 1) """
def A(self): """ 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)) """
""" 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] """
""" Return the base field.
OUTPUT:
A field.
EXAMPLES::
sage: A = matrix(AA, [(1, 1), (-1, 1)]) sage: from sage.geometry.polyhedron.double_description import Problem sage: Problem(A).base_ring() Algebraic Real Field """
def dim(self): """ 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 """
r""" Return a string representation.
OUTPUT:
String.
EXAMPLES::
sage: A = matrix(QQ, [(1, 1), (-1, 1)]) sage: from sage.geometry.polyhedron.double_description import Problem sage: Problem(A).__repr__() 'Pointed cone with inequalities\n(1, 1)\n(-1, 1)' """
""" 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:
- ``pair_class`` -- subclass of :class:`DoubleDescriptionPair`.
OUTPUT:
A pair consisting of a :class:`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)] """
""" Double description pair for the "Standard Algorithm".
See :class:`StandardAlgorithm`.
TESTS::
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() """
""" 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] """
""" 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)] """
""" Run the Standard Algorithm.
OUTPUT:
A double description pair `(A, R)` of all inequalities as a :class:`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] """ |