Esempio n. 1
0
def cdd_Hrepresentation(cdd_type, ieqs, eqns):
    r"""
    Return a string containing the H-representation in cddlib's ine format.

    EXAMPLES::

        sage: from sage.geometry.polyhedron.cdd_file_format import cdd_Hrepresentation
        sage: cdd_Hrepresentation('rational', None, [[0,1]])
        'H-representation\nlinearity 1 1\nbegin\n 1 2 rational\n 0 1\nend\n'
    """
    ieqs = _set_to_None_if_empty(ieqs)
    eqns  = _set_to_None_if_empty(eqns)

    num, ambient_dim = _common_length_of(ieqs, eqns)
    ambient_dim -= 1

    s = 'H-representation\n'
    if eqns is not None:
        assert len(eqns)>0
        n = len(eqns)
        s += "linearity " + repr(n) + ' '
        s += _to_space_separated_string(range(1,n+1)) + '\n'
    s += 'begin\n'
    s += ' ' + repr(num) + ' ' + repr(ambient_dim+1) + ' ' + cdd_type + '\n'
    if eqns is not None:
        for e in eqns:
            s += ' ' + _to_space_separated_string(e) + '\n'
    if ieqs is not None:
        for i in ieqs:
            s += ' ' + _to_space_separated_string(i) + '\n'
    s += 'end\n'
    return s
Esempio n. 2
0
def cdd_Vrepresentation(cdd_type, vertices, rays, lines):
    r"""
    Return a string containing the V-representation in cddlib's ext format.

    NOTE:

    If there is no vertex given, then the origin will be implicitly
    added. You cannot write the empty V-representation (which cdd
    would refuse to process).

    EXAMPLES::

        sage: from sage.geometry.polyhedron.cdd_file_format import cdd_Vrepresentation
        sage: print cdd_Vrepresentation('rational', [[0,0]], [[1,0]], [[0,1]])
        V-representation
        linearity 1 1
        begin
          3 3 rational
          0 0 1
          0 1 0
          1 0 0
        end
    """
    vertices = _set_to_None_if_empty(vertices)
    rays     = _set_to_None_if_empty(rays)
    lines    = _set_to_None_if_empty(lines)

    num, ambient_dim = _common_length_of(vertices, rays, lines)

    # cdd implicitly assumes that the origin is a vertex if none is given
    if vertices is None:
        vertices = [[0]*ambient_dim]
        num += 1

    s = 'V-representation\n'
    if lines is not None:
        n = len(lines)
        s += "linearity " + repr(n) + ' '
        s += _to_space_separated_string(range(1,n+1)) + '\n'
    s += 'begin\n'
    s += ' ' + repr(num) + ' ' + repr(ambient_dim+1) + ' ' + cdd_type + '\n'
    if lines is not None:
        for l in lines:
            s += ' 0 ' + _to_space_separated_string(l) + '\n'
    if rays is not None:
        for r in rays:
            s += ' 0 ' + _to_space_separated_string(r) + '\n'
    if vertices is not None:
        for v in vertices:
            s += ' 1 ' + _to_space_separated_string(v) + '\n'
    s += 'end\n'
    return s
Esempio n. 3
0
def cdd_Hrepresentation(cdd_type, ieqs, eqns, file_output=None):
    r"""
    Return a string containing the H-representation in cddlib's ine format.

    INPUT:

    - ``file_output`` (string; optional) -- a filename to which the
      representation should be written. If set to ``None`` (default),
      representation is returned as a string.

    EXAMPLES::

        sage: from sage.geometry.polyhedron.cdd_file_format import cdd_Hrepresentation
        sage: cdd_Hrepresentation('rational', None, [[0,1]])
        'H-representation\nlinearity 1 1\nbegin\n 1 2 rational\n 0 1\nend\n'

    TESTS::

        sage: from sage.misc.temporary_file import tmp_filename
        sage: filename = tmp_filename(ext='.ine')
        sage: cdd_Hrepresentation('rational', None, [[0,1]], file_output=filename)
    """
    ieqs = _set_to_None_if_empty(ieqs)
    eqns = _set_to_None_if_empty(eqns)

    num, ambient_dim = _common_length_of(ieqs, eqns)
    ambient_dim -= 1

    s = 'H-representation\n'
    if eqns is not None:
        assert len(eqns) > 0
        n = len(eqns)
        s += "linearity " + repr(n) + ' '
        s += _to_space_separated_string(range(1, n + 1)) + '\n'
    s += 'begin\n'
    s += ' ' + repr(num) + ' ' + repr(ambient_dim + 1) + ' ' + cdd_type + '\n'
    if eqns is not None:
        for e in eqns:
            s += ' ' + _to_space_separated_string(e) + '\n'
    if ieqs is not None:
        for i in ieqs:
            s += ' ' + _to_space_separated_string(i) + '\n'
    s += 'end\n'

    if file_output is not None:
        in_file = open(file_output, 'w')
        in_file.write(s)
        in_file.close()
    else:
        return s
Esempio n. 4
0
def cdd_Hrepresentation(cdd_type, ieqs, eqns, file_output=None):
    r"""
    Return a string containing the H-representation in cddlib's ine format.

    INPUT:

    - ``file_output`` (string; optional) -- a filename to which the
      representation should be written. If set to ``None`` (default),
      representation is returned as a string.

    EXAMPLES::

        sage: from sage.geometry.polyhedron.cdd_file_format import cdd_Hrepresentation
        sage: cdd_Hrepresentation('rational', None, [[0,1]])
        'H-representation\nlinearity 1 1\nbegin\n 1 2 rational\n 0 1\nend\n'

    TESTS::

        sage: from sage.misc.temporary_file import tmp_filename
        sage: filename = tmp_filename(ext='.ine')
        sage: cdd_Hrepresentation('rational', None, [[0,1]], file_output=filename)
    """
    ieqs = _set_to_None_if_empty(ieqs)
    eqns = _set_to_None_if_empty(eqns)

    num, ambient_dim = _common_length_of(ieqs, eqns)
    ambient_dim -= 1

    s = "H-representation\n"
    if eqns is not None:
        assert len(eqns) > 0
        n = len(eqns)
        s += "linearity " + repr(n) + " "
        s += _to_space_separated_string(range(1, n + 1)) + "\n"
    s += "begin\n"
    s += " " + repr(num) + " " + repr(ambient_dim + 1) + " " + cdd_type + "\n"
    if eqns is not None:
        for e in eqns:
            s += " " + _to_space_separated_string(e) + "\n"
    if ieqs is not None:
        for i in ieqs:
            s += " " + _to_space_separated_string(i) + "\n"
    s += "end\n"

    if file_output is not None:
        in_file = open(file_output, "w")
        in_file.write(s)
        in_file.close()
    else:
        return s
Esempio n. 5
0
def cdd_Vrepresentation(cdd_type, vertices, rays, lines, file_output=None):
    r"""
    Return a string containing the V-representation in cddlib's ext format.

    INPUT:

    - ``file_output`` (string; optional) -- a filename to which the
      representation should be written. If set to ``None`` (default),
      representation is returned as a string.

    .. NOTE::

        If there is no vertex given, then the origin will be implicitly
        added. You cannot write the empty V-representation (which cdd would
        refuse to process).

    EXAMPLES::

        sage: from sage.geometry.polyhedron.cdd_file_format import cdd_Vrepresentation
        sage: print cdd_Vrepresentation('rational', [[0,0]], [[1,0]], [[0,1]])
        V-representation
        linearity 1 1
        begin
          3 3 rational
          0 0 1
          0 1 0
          1 0 0
        end

    TESTS::

        sage: from sage.misc.temporary_file import tmp_filename
        sage: filename = tmp_filename(ext='.ext')
        sage: cdd_Vrepresentation('rational', [[0,0]], [[1,0]], [[0,1]], file_output=filename)
    """
    vertices = _set_to_None_if_empty(vertices)
    rays = _set_to_None_if_empty(rays)
    lines = _set_to_None_if_empty(lines)

    num, ambient_dim = _common_length_of(vertices, rays, lines)

    # cdd implicitly assumes that the origin is a vertex if none is given
    if vertices is None:
        vertices = [[0] * ambient_dim]
        num += 1

    s = 'V-representation\n'
    if lines is not None:
        n = len(lines)
        s += "linearity " + repr(n) + ' '
        s += _to_space_separated_string(range(1, n + 1)) + '\n'
    s += 'begin\n'
    s += ' ' + repr(num) + ' ' + repr(ambient_dim + 1) + ' ' + cdd_type + '\n'
    if lines is not None:
        for l in lines:
            s += ' 0 ' + _to_space_separated_string(l) + '\n'
    if rays is not None:
        for r in rays:
            s += ' 0 ' + _to_space_separated_string(r) + '\n'
    if vertices is not None:
        for v in vertices:
            s += ' 1 ' + _to_space_separated_string(v) + '\n'
    s += 'end\n'

    if file_output is not None:
        in_file = open(file_output, 'w')
        in_file.write(s)
        in_file.close()
    else:
        return s
Esempio n. 6
0
def Polyhedron(vertices=None,
               rays=None,
               lines=None,
               ieqs=None,
               eqns=None,
               ambient_dim=None,
               base_ring=None,
               minimize=True,
               verbose=False,
               backend=None):
    """
    Construct a polyhedron object.

    You may either define it with vertex/ray/line or
    inequalities/equations data, but not both. Redundant data will
    automatically be removed (unless ``minimize=False``), and the
    complementary representation will be computed.

    INPUT:

    - ``vertices`` -- list of point. Each point can be specified as
      any iterable container of ``base_ring`` elements. If ``rays`` or
      ``lines`` are specified but no ``vertices``, the origin is
      taken to be the single vertex.

    - ``rays`` -- list of rays. Each ray can be specified as any
      iterable container of ``base_ring`` elements.

    - ``lines`` -- list of lines. Each line can be specified as any
      iterable container of ``base_ring`` elements.

    - ``ieqs`` -- list of inequalities. Each line can be specified as any
      iterable container of ``base_ring`` elements. An entry equal to
      ``[-1,7,3,4]`` represents the inequality `7x_1+3x_2+4x_3\geq 1`.

    - ``eqns`` -- list of equalities. Each line can be specified as
      any iterable container of ``base_ring`` elements. An entry equal to
      ``[-1,7,3,4]`` represents the equality `7x_1+3x_2+4x_3= 1`.

    - ``base_ring`` -- a sub-field of the reals implemented in
      Sage. The field over which the polyhedron will be defined. For
      ``QQ`` and algebraic extensions, exact arithmetic will be
      used. For ``RDF``, floating point numbers will be used. Floating
      point arithmetic is faster but might give the wrong result for
      degenerate input.

    - ``ambient_dim`` -- integer. The ambient space dimension. Usually
      can be figured out automatically from the H/Vrepresentation
      dimensions.

    - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are

      * ``'cdd'``: use cdd
        (:mod:`~sage.geometry.polyhedron.backend_cdd`) with `\QQ` or
        `\RDF` coefficients depending on ``base_ring``.

      * ``'ppl'``: use ppl
        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\ZZ` or
        `\QQ` coefficients depending on ``base_ring``.

      * ``'field'``: use python implementation
        (:mod:`~sage.geometry.polyhedron.backend_field`) for any field

    Some backends support further optional arguments:

    - ``minimize`` -- boolean (default: ``True``). Whether to
      immediately remove redundant H/V-representation data. Currently
      not used.

    - ``verbose`` -- boolean (default: ``False``). Whether to print
      verbose output for debugging purposes. Only supported by the cdd
      backends.

    OUTPUT:

    The polyhedron defined by the input data.

    EXAMPLES:

    Construct some polyhedra::

        sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]])
        sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]])
        sage: list(square_from_ieqs.vertex_generator())
        [A vertex at (1, -1),
         A vertex at (1, 1),
         A vertex at (-1, 1),
         A vertex at (-1, -1)]
        sage: list(square_from_vertices.inequality_generator())
        [An inequality (1, 0) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0]
        sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF)
        sage: p.n_inequalities()
        2

    The same polyhedron given in two ways::

        sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]])
        sage: p.Vrepresentation()
        (A line in the direction (0, 0, 1),
         A ray in the direction (1, 0, 0),
         A ray in the direction (0, 1, 0),
         A vertex at (0, 0, 0))
        sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]])
        sage: q.Hrepresentation()
        (An inequality (1, 0, 0) x + 0 >= 0,
         An inequality (0, 1, 0) x + 0 >= 0)

    Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with
    coordinates `a, b, \dots, f` and

      * The inequality `e+b \geq c+d`
      * The inequality `e+c \geq b+d`
      * The equation `a+b+c+d+e+f = 31`

    ::

        sage: positive_coords = Polyhedron(ieqs=[
        ...       [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
        ...       [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
        sage: P = Polyhedron(ieqs=positive_coords.inequalities() + (
        ...       [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]), eqns=[[-31,1,1,1,1,1,1]])
        sage: P
        A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
        sage: P.dim()
        5
        sage: P.Vrepresentation()
        (A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31),
         A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0),
         A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0),
         A vertex at (0, 0, 0, 31/2, 31/2, 0))

    .. NOTE::

      * Once constructed, a ``Polyhedron`` object is immutable.

      * Although the option ``field=RDF`` allows numerical data to
        be used, it might not give the right answer for degenerate
        input data - the results can depend upon the tolerance
        setting of cdd.
    """
    # Clean up the arguments
    vertices = _make_listlist(vertices)
    rays = _make_listlist(rays)
    lines = _make_listlist(lines)
    ieqs = _make_listlist(ieqs)
    eqns = _make_listlist(eqns)

    got_Vrep = (len(vertices + rays + lines) > 0)
    got_Hrep = (len(ieqs + eqns) > 0)

    if got_Vrep and got_Hrep:
        raise ValueError('You cannot specify both H- and V-representation.')
    elif got_Vrep:
        deduced_ambient_dim = _common_length_of(vertices, rays, lines)[1]
    elif got_Hrep:
        deduced_ambient_dim = _common_length_of(ieqs, eqns)[1] - 1
    else:
        if ambient_dim is None:
            deduced_ambient_dim = 0
        else:
            deduced_ambient_dim = ambient_dim
        if base_ring is None:
            base_ring = ZZ

    # set ambient_dim
    if ambient_dim is not None and deduced_ambient_dim != ambient_dim:
        raise ValueError(
            'Ambient space dimension mismatch. Try removing the "ambient_dim" parameter.'
        )
    ambient_dim = deduced_ambient_dim

    # figure out base_ring
    from sage.misc.flatten import flatten
    values = flatten(vertices + rays + lines + ieqs + eqns)
    if base_ring is not None:
        try:
            convert = not all(x.parent() is base_ring for x in values)
        except AttributeError:  # No x.parent() method?
            convert = True
    else:
        from sage.rings.integer import is_Integer
        from sage.rings.rational import is_Rational
        from sage.rings.real_double import is_RealDoubleElement
        if all(is_Integer(x) for x in values):
            if got_Vrep:
                base_ring = ZZ
            else:  # integral inequalities usually do not determine a latice polytope!
                base_ring = QQ
            convert = False
        elif all(is_Rational(x) for x in values):
            base_ring = QQ
            convert = False
        elif all(is_RealDoubleElement(x) for x in values):
            base_ring = RDF
            convert = False
        else:
            try:
                for v in values:
                    ZZ(v)
                if got_Vrep:
                    base_ring = ZZ
                else:
                    base_ring = QQ
                convert = True
            except (TypeError, ValueError):
                from sage.structure.sequence import Sequence
                values = Sequence(values)
                common_ring = values.universe()
                if QQ.has_coerce_map_from(common_ring):
                    base_ring = QQ
                    convert = True
                elif common_ring is RR:  # DWIM: replace with RDF
                    base_ring = RDF
                    convert = True
                else:
                    base_ring = common_ring
                    convert = True

    # Add the origin if necesarry
    if got_Vrep and len(vertices) == 0:
        vertices = [[0] * ambient_dim]

    # Specific backends can override the base_ring
    from sage.geometry.polyhedron.parent import Polyhedra
    parent = Polyhedra(base_ring, ambient_dim, backend=backend)
    base_ring = parent.base_ring()

    # finally, construct the Polyhedron
    Hrep = Vrep = None
    if got_Hrep:
        Hrep = [ieqs, eqns]
    if got_Vrep:
        Vrep = [vertices, rays, lines]
    return parent(Vrep, Hrep, convert=convert, verbose=verbose)
Esempio n. 7
0
def Polyhedron(vertices=None, rays=None, lines=None,
               ieqs=None, eqns=None,
               ambient_dim=None, base_ring=None, minimize=True, verbose=False,
               backend=None):
    """
    Construct a polyhedron object.

    You may either define it with vertex/ray/line or
    inequalities/equations data, but not both. Redundant data will
    automatically be removed (unless ``minimize=False``), and the
    complementary representation will be computed.

    INPUT:

    - ``vertices`` -- list of point. Each point can be specified as
      any iterable container of ``base_ring`` elements. If ``rays`` or
      ``lines`` are specified but no ``vertices``, the origin is
      taken to be the single vertex.

    - ``rays`` -- list of rays. Each ray can be specified as any
      iterable container of ``base_ring`` elements.

    - ``lines`` -- list of lines. Each line can be specified as any
      iterable container of ``base_ring`` elements.

    - ``ieqs`` -- list of inequalities. Each line can be specified as any
      iterable container of ``base_ring`` elements. An entry equal to
      ``[-1,7,3,4]`` represents the inequality `7x_1+3x_2+4x_3\geq 1`.

    - ``eqns`` -- list of equalities. Each line can be specified as
      any iterable container of ``base_ring`` elements. An entry equal to
      ``[-1,7,3,4]`` represents the equality `7x_1+3x_2+4x_3= 1`.

    - ``base_ring`` -- either ``QQ`` or ``RDF``. The field over which
      the polyhedron will be defined. For ``QQ``, exact arithmetic
      will be used. For ``RDF``, floating point numbers will be
      used. Floating point arithmetic is faster but might give the
      wrong result for degenerate input.

    - ``ambient_dim`` -- integer. The ambient space dimension. Usually
      can be figured out automatically from the H/Vrepresentation
      dimensions.

    - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are

      * ``'cdd'``: use cdd
        (:mod:`~sage.geometry.polyhedron.backend_cdd`) with `\QQ` or
        `\RDF` coefficients depending on ``base_ring``.


      * ``'ppl'``: use ppl
        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\ZZ` or
        `\QQ` coefficients depending on ``base_ring``.

    Some backends support further optional arguments:

    - ``minimize`` -- boolean (default: ``True``). Whether to
      immediately remove redundant H/V-representation data. Currently
      not used.

    - ``verbose`` -- boolean (default: ``False``). Whether to print
      verbose output for debugging purposes. Only supported by the cdd
      backends.

    OUTPUT:

    The polyhedron defined by the input data.

    EXAMPLES:

    Construct some polyhedra::

        sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]])
        sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]])
        sage: list(square_from_ieqs.vertex_generator())
        [A vertex at (1, -1),
         A vertex at (1, 1),
         A vertex at (-1, 1),
         A vertex at (-1, -1)]
        sage: list(square_from_vertices.inequality_generator())
        [An inequality (1, 0) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0]
        sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF)
        sage: p.n_inequalities()
        2

    The same polyhedron given in two ways::

        sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]])
        sage: p.Vrepresentation()
        (A line in the direction (0, 0, 1),
         A ray in the direction (1, 0, 0),
         A ray in the direction (0, 1, 0),
         A vertex at (0, 0, 0))
        sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]])
        sage: q.Hrepresentation()
        (An inequality (1, 0, 0) x + 0 >= 0,
         An inequality (0, 1, 0) x + 0 >= 0)

    Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with
    coordinates `a, b, \dots, f` and

      * The inequality `e+b \geq c+d`
      * The inequality `e+c \geq b+d`
      * The equation `a+b+c+d+e+f = 31`

    ::

        sage: positive_coords = Polyhedron(ieqs=[
        ...       [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
        ...       [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
        sage: P = Polyhedron(ieqs=positive_coords.inequalities() + (
        ...       [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]), eqns=[[-31,1,1,1,1,1,1]])
        sage: P
        A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
        sage: P.dim()
        5
        sage: P.Vrepresentation()
        (A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31),
         A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0),
         A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0),
         A vertex at (0, 0, 0, 31/2, 31/2, 0))

    .. NOTE::

      * Once constructed, a ``Polyhedron`` object is immutable.
      * Although the option ``field=RDF`` allows numerical data to
        be used, it might not give the right answer for degenerate
        input data - the results can depend upon the tolerance
        setting of cdd.
    """
    # Clean up the arguments
    vertices = _make_listlist(vertices)
    rays     = _make_listlist(rays)
    lines    = _make_listlist(lines)
    ieqs     = _make_listlist(ieqs)
    eqns     = _make_listlist(eqns)

    got_Vrep = (len(vertices+rays+lines) > 0)
    got_Hrep = (len(ieqs+eqns) > 0)

    if got_Vrep and got_Hrep:
        raise ValueError('You cannot specify both H- and V-representation.')
    elif got_Vrep:
        deduced_ambient_dim = _common_length_of(vertices, rays, lines)[1]
    elif got_Hrep:
        deduced_ambient_dim = _common_length_of(ieqs, eqns)[1] - 1
    else:
        if ambient_dim is None:
            deduced_ambient_dim = 0
        else:
            deduced_ambient_dim = ambient_dim
        if base_ring is None:
            base_ring = ZZ

    # set ambient_dim
    if ambient_dim is not None and deduced_ambient_dim!=ambient_dim:
        raise ValueError('Ambient space dimension mismatch. Try removing the "ambient_dim" parameter.')
    ambient_dim = deduced_ambient_dim

    # figure out base_ring
    from sage.misc.flatten import flatten
    values = flatten(vertices+rays+lines+ieqs+eqns)
    if base_ring is not None:
        try:
            convert = not all(x.parent() is base_ring for x in values)
        except AttributeError:   # No x.parent() method?
            convert = True
    else:
        from sage.rings.integer import is_Integer
        from sage.rings.rational import is_Rational
        from sage.rings.real_double import is_RealDoubleElement
        if all(is_Integer(x) for x in values):
            if got_Vrep:
                base_ring = ZZ
            else:   # integral inequalities usually do not determine a latice polytope!
                base_ring = QQ
            convert=False
        elif all(is_Rational(x) for x in values):
            base_ring = QQ
            convert=False
        elif all(is_RealDoubleElement(x) for x in values):
            base_ring = RDF
            convert=False
        else:
            try:
                map(ZZ, values)
                if got_Vrep:
                    base_ring = ZZ
                else:
                    base_ring = QQ
                convert = True
            except TypeError:
                from sage.structure.sequence import Sequence
                values = Sequence(values)
                if QQ.has_coerce_map_from(values.universe()):
                    base_ring = QQ
                    convert = True
                else:
                    base_ring = RDF
                    convert = True

    # Add the origin if necesarry
    if got_Vrep and len(vertices)==0:
        vertices = [ [0]*ambient_dim ]

    # Specific backends can override the base_ring
    from sage.geometry.polyhedron.parent import Polyhedra
    parent = Polyhedra(base_ring, ambient_dim, backend=backend)
    base_ring = parent.base_ring()

    # Convert into base_ring if necessary
    def convert_base_ring(lstlst):
        return [ [base_ring(x) for x in lst] for lst in lstlst]
    Hrep = Vrep = None
    if got_Hrep:
        Hrep = [ieqs, eqns]
    if got_Vrep:
        Vrep = [vertices, rays, lines]

    # finally, construct the Polyhedron
    return parent(Vrep, Hrep, convert=convert)
Esempio n. 8
0
def Polyhedron(vertices=None,
               rays=None,
               lines=None,
               ieqs=None,
               eqns=None,
               base_ring=QQ,
               minimize=True,
               verbose=False,
               backend=None):
    """
    Construct a polyhedron object.

    You may either define it with vertex/ray/line or
    inequalities/equations data, but not both. Redundant data will
    automatically be removed (unless ``minimize=False``), and the
    complementary representation will be computed.

    INPUT:

    - ``vertices`` -- list of point. Each point can be specified as
      any iterable container of ``base_ring`` elements.
        
    - ``rays`` -- list of rays. Each ray can be specified as any
      iterable container of ``base_ring`` elements.
        
    - ``lines`` -- list of lines. Each line can be specified as any
      iterable container of ``base_ring`` elements.

    - ``ieqs`` -- list of inequalities. Each line can be specified as
      any iterable container of ``base_ring`` elements.

    - ``eqns`` -- list of equalities. Each line can be specified as
      any iterable container of ``base_ring`` elements.

    - ``base_ring`` -- either ``QQ`` or ``RDF``. The field over which
      the polyhedron will be defined. For ``QQ``, exact arithmetic
      will be used. For ``RDF``, floating point numbers will be
      used. Floating point arithmetic is faster but might give the
      wrong result for degenerate input.

    - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are

      * ``'cddr'``: cdd (:mod:`~sage.geometry.polyhedron.backend_cdd`)
        with rational coefficients

      * ``'cddf'``: cdd with floating-point coefficients

      * ``'ppl'``: use ppl
        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\QQ`
        coefficients.

    Some backends support further optional arguments:

    - ``minimize`` -- boolean (default: ``True``). Whether to
      immediately remove redundant H/V-representation data. Currently
      not used.

    - ``verbose`` -- boolean (default: ``False``). Whether to print
      verbose output for debugging purposes. Only supported by the cdd
      backends.

    OUTPUT:

    The polyhedron defined by the input data.

    EXAMPLES:

    Construct some polyhedra::

        sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]])
        sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]])
        sage: list(square_from_ieqs.vertex_generator())
        [A vertex at (1, -1),
         A vertex at (1, 1),
         A vertex at (-1, 1),
         A vertex at (-1, -1)]
        sage: list(square_from_vertices.inequality_generator())
        [An inequality (1, 0) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0]
        sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF)
        sage: p.n_inequalities()
        2

    The same polyhedron given in two ways::

        sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]])
        sage: p.Vrepresentation()
        (A line in the direction (0, 0, 1),
         A ray in the direction (1, 0, 0),
         A ray in the direction (0, 1, 0),
         A vertex at (0, 0, 0))
        sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]])
        sage: q.Hrepresentation()
        (An inequality (1, 0, 0) x + 0 >= 0,
         An inequality (0, 1, 0) x + 0 >= 0)

    Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with
    coordinates `a, b, \dots, f` and

      * The inequality `e+b \geq c+d`
      * The inequality `e+c \geq b+d`
      * The equation `a+b+c+d+e+f = 31`
      
    ::

        sage: positive_coords = Polyhedron(ieqs=[
        ...       [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
        ...       [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
        sage: P = Polyhedron(ieqs=positive_coords.inequalities() + [
        ...       [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]], eqns=[[-31,1,1,1,1,1,1]])
        sage: P
        A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
        sage: P.dim()
        5
        sage: P.Vrepresentation()
        (A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31),
         A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0),
         A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0),
         A vertex at (0, 0, 0, 31/2, 31/2, 0))

    .. NOTE::
    
      * Once constructed, a ``Polyhedron`` object is immutable.
      * Although the option ``field=RDF`` allows numerical data to
        be used, it might not give the right answer for degenerate
        input data - the results can depend upon the tolerance
        setting of cdd.
    """
    # Clean up the arguments
    vertices = _set_to_None_if_empty(vertices)
    rays = _set_to_None_if_empty(rays)
    lines = _set_to_None_if_empty(lines)
    ieqs = _set_to_None_if_empty(ieqs)
    eqns = _set_to_None_if_empty(eqns)

    got_Vrep = (vertices is not None or rays is not None or lines is not None)
    got_Hrep = (ieqs is not None or eqns is not None)

    if got_Vrep and got_Hrep:
        raise ValueError('You cannot specify both H- and V-representation.')
    elif got_Vrep:
        vertices = _set_to_empty_if_None(vertices)
        rays = _set_to_empty_if_None(rays)
        lines = _set_to_empty_if_None(lines)
        Vrep = [vertices, rays, lines]
        Hrep = None
        ambient_dim = _common_length_of(*Vrep)[1]
    elif got_Hrep:
        ieqs = _set_to_empty_if_None(ieqs)
        eqns = _set_to_empty_if_None(eqns)
        Vrep = None
        Hrep = [ieqs, eqns]
        ambient_dim = _common_length_of(*Hrep)[1] - 1
    else:
        Vrep = None
        Hrep = None
        ambient_dim = 0

    if backend is not None:
        if backend == 'ppl':
            from backend_ppl import Polyhedron_QQ_ppl
            return Polyhedron_QQ_ppl(ambient_dim,
                                     Vrep,
                                     Hrep,
                                     minimize=minimize)
        if backend == 'cddr':
            from backend_cdd import Polyhedron_QQ_cdd
            return Polyhedron_QQ_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
        if backend == 'cddf':
            from backend_cdd import Polyhedron_RDF_cdd
            return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)

    if base_ring is QQ:
        from backend_ppl import Polyhedron_QQ_ppl
        return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
    elif base_ring is RDF:
        from backend_cdd import Polyhedron_RDF_cdd
        return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
    else:
        raise ValueError(
            'Polyhedron objects can only be constructed over QQ and RDF')
Esempio n. 9
0
def Polyhedron(vertices=None, rays=None, lines=None,
               ieqs=None, eqns=None,
               base_ring=QQ, minimize=True, verbose=False,
               backend=None):
    """
    Construct a polyhedron object.

    You may either define it with vertex/ray/line or
    inequalities/equations data, but not both. Redundant data will
    automatically be removed (unless ``minimize=False``), and the
    complementary representation will be computed.

    INPUT:

    - ``vertices`` -- list of point. Each point can be specified as
      any iterable container of ``base_ring`` elements.
        
    - ``rays`` -- list of rays. Each ray can be specified as any
      iterable container of ``base_ring`` elements.
        
    - ``lines`` -- list of lines. Each line can be specified as any
      iterable container of ``base_ring`` elements.

    - ``ieqs`` -- list of inequalities. Each line can be specified as
      any iterable container of ``base_ring`` elements.

    - ``eqns`` -- list of equalities. Each line can be specified as
      any iterable container of ``base_ring`` elements.

    - ``base_ring`` -- either ``QQ`` or ``RDF``. The field over which
      the polyhedron will be defined. For ``QQ``, exact arithmetic
      will be used. For ``RDF``, floating point numbers will be
      used. Floating point arithmetic is faster but might give the
      wrong result for degenerate input.

    - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are

      * ``'cddr'``: cdd (:mod:`~sage.geometry.polyhedron.backend_cdd`)
        with rational coefficients

      * ``'cddf'``: cdd with floating-point coefficients

      * ``'ppl'``: use ppl
        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\QQ`
        coefficients.

    Some backends support further optional arguments:

    - ``minimize`` -- boolean (default: ``True``). Whether to
      immediately remove redundant H/V-representation data. Currently
      not used.

    - ``verbose`` -- boolean (default: ``False``). Whether to print
      verbose output for debugging purposes. Only supported by the cdd
      backends.

    OUTPUT:

    The polyhedron defined by the input data.

    EXAMPLES:

    Construct some polyhedra::

        sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]])
        sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]])
        sage: list(square_from_ieqs.vertex_generator())
        [A vertex at (1, -1),
         A vertex at (1, 1),
         A vertex at (-1, 1),
         A vertex at (-1, -1)]
        sage: list(square_from_vertices.inequality_generator())
        [An inequality (1, 0) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0]
        sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF)
        sage: p.n_inequalities()
        2

    The same polyhedron given in two ways::

        sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]])
        sage: p.Vrepresentation()
        (A line in the direction (0, 0, 1),
         A ray in the direction (1, 0, 0),
         A ray in the direction (0, 1, 0),
         A vertex at (0, 0, 0))
        sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]])
        sage: q.Hrepresentation()
        (An inequality (1, 0, 0) x + 0 >= 0,
         An inequality (0, 1, 0) x + 0 >= 0)

    Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with
    coordinates `a, b, \dots, f` and

      * The inequality `e+b \geq c+d`
      * The inequality `e+c \geq b+d`
      * The equation `a+b+c+d+e+f = 31`
      
    ::

        sage: positive_coords = Polyhedron(ieqs=[
        ...       [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
        ...       [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
        sage: P = Polyhedron(ieqs=positive_coords.inequalities() + [
        ...       [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]], eqns=[[-31,1,1,1,1,1,1]])
        sage: P
        A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
        sage: P.dim()
        5
        sage: P.Vrepresentation()
        (A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31),
         A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0),
         A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0),
         A vertex at (0, 0, 0, 31/2, 31/2, 0))

    .. NOTE::
    
      * Once constructed, a ``Polyhedron`` object is immutable.
      * Although the option ``field=RDF`` allows numerical data to
        be used, it might not give the right answer for degenerate
        input data - the results can depend upon the tolerance
        setting of cdd.
    """
    # Clean up the arguments
    vertices = _set_to_None_if_empty(vertices)
    rays     = _set_to_None_if_empty(rays)
    lines    = _set_to_None_if_empty(lines)
    ieqs     = _set_to_None_if_empty(ieqs)
    eqns     = _set_to_None_if_empty(eqns)

    got_Vrep = (vertices is not None or rays is not None or lines is not None)
    got_Hrep = (ieqs is not None or eqns is not None)
    
    if got_Vrep and got_Hrep:
        raise ValueError('You cannot specify both H- and V-representation.')
    elif got_Vrep:
        vertices = _set_to_empty_if_None(vertices)
        rays     = _set_to_empty_if_None(rays)
        lines    = _set_to_empty_if_None(lines)
        Vrep = [vertices, rays, lines]
        Hrep = None
        ambient_dim = _common_length_of(*Vrep)[1]
    elif got_Hrep:
        ieqs = _set_to_empty_if_None(ieqs)
        eqns = _set_to_empty_if_None(eqns)
        Vrep = None
        Hrep = [ieqs, eqns]
        ambient_dim = _common_length_of(*Hrep)[1] - 1
    else:
        Vrep = None
        Hrep = None
        ambient_dim = 0

    if backend is not None:
        if backend=='ppl':
            from backend_ppl import Polyhedron_QQ_ppl
            return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
        if backend=='cddr':
            from backend_cdd import Polyhedron_QQ_cdd
            return Polyhedron_QQ_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
        if backend=='cddf':
            from backend_cdd import Polyhedron_RDF_cdd
            return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)

    if base_ring is QQ:
        from backend_ppl import Polyhedron_QQ_ppl
        return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
    elif base_ring is RDF:
        from backend_cdd import Polyhedron_RDF_cdd
        return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
    else:
        raise ValueError('Polyhedron objects can only be constructed over QQ and RDF')
Esempio n. 10
0
def cdd_Vrepresentation(cdd_type, vertices, rays, lines, file_output=None):
    r"""
    Return a string containing the V-representation in cddlib's ext format.

    INPUT:

    - ``file_output`` (string; optional) -- a filename to which the
      representation should be written. If set to ``None`` (default),
      representation is returned as a string.

    .. NOTE::

        If there is no vertex given, then the origin will be implicitly
        added. You cannot write the empty V-representation (which cdd would
        refuse to process).

    EXAMPLES::

        sage: from sage.geometry.polyhedron.cdd_file_format import cdd_Vrepresentation
        sage: print cdd_Vrepresentation('rational', [[0,0]], [[1,0]], [[0,1]])
        V-representation
        linearity 1 1
        begin
          3 3 rational
          0 0 1
          0 1 0
          1 0 0
        end

    TESTS::

        sage: from sage.misc.temporary_file import tmp_filename
        sage: filename = tmp_filename(ext='.ext')
        sage: cdd_Vrepresentation('rational', [[0,0]], [[1,0]], [[0,1]], file_output=filename)
    """
    vertices = _set_to_None_if_empty(vertices)
    rays = _set_to_None_if_empty(rays)
    lines = _set_to_None_if_empty(lines)

    num, ambient_dim = _common_length_of(vertices, rays, lines)

    # cdd implicitly assumes that the origin is a vertex if none is given
    if vertices is None:
        vertices = [[0] * ambient_dim]
        num += 1

    s = "V-representation\n"
    if lines is not None:
        n = len(lines)
        s += "linearity " + repr(n) + " "
        s += _to_space_separated_string(range(1, n + 1)) + "\n"
    s += "begin\n"
    s += " " + repr(num) + " " + repr(ambient_dim + 1) + " " + cdd_type + "\n"
    if lines is not None:
        for l in lines:
            s += " 0 " + _to_space_separated_string(l) + "\n"
    if rays is not None:
        for r in rays:
            s += " 0 " + _to_space_separated_string(r) + "\n"
    if vertices is not None:
        for v in vertices:
            s += " 1 " + _to_space_separated_string(v) + "\n"
    s += "end\n"

    if file_output is not None:
        in_file = open(file_output, "w")
        in_file.write(s)
        in_file.close()
    else:
        return s