passagemath-polyhedra 10.6.31rc3__cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-polyhedra might be problematic. Click here for more details.
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +367 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +369 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +206 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-e985bcbb.so.1.0.0 +0 -0
- sage/all__sagemath_polyhedra.py +50 -0
- sage/game_theory/all.py +8 -0
- sage/game_theory/catalog.py +6 -0
- sage/game_theory/catalog_normal_form_games.py +923 -0
- sage/game_theory/cooperative_game.py +844 -0
- sage/game_theory/matching_game.py +1181 -0
- sage/game_theory/normal_form_game.py +2697 -0
- sage/game_theory/parser.py +275 -0
- sage/geometry/all__sagemath_polyhedra.py +22 -0
- sage/geometry/cone.py +6940 -0
- sage/geometry/cone_catalog.py +847 -0
- sage/geometry/cone_critical_angles.py +1027 -0
- sage/geometry/convex_set.py +1119 -0
- sage/geometry/fan.py +3743 -0
- sage/geometry/fan_isomorphism.py +389 -0
- sage/geometry/fan_morphism.py +1884 -0
- sage/geometry/hasse_diagram.py +202 -0
- sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
- sage/geometry/hyperplane_arrangement/all.py +1 -0
- sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
- sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
- sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
- sage/geometry/hyperplane_arrangement/library.py +825 -0
- sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
- sage/geometry/hyperplane_arrangement/plot.py +520 -0
- sage/geometry/integral_points.py +35 -0
- sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/integral_points_generic_dense.pyx +7 -0
- sage/geometry/lattice_polytope.py +5894 -0
- sage/geometry/linear_expression.py +773 -0
- sage/geometry/newton_polygon.py +767 -0
- sage/geometry/point_collection.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/point_collection.pyx +1008 -0
- sage/geometry/polyhedral_complex.py +2616 -0
- sage/geometry/polyhedron/all.py +8 -0
- sage/geometry/polyhedron/backend_cdd.py +460 -0
- sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
- sage/geometry/polyhedron/backend_field.py +347 -0
- sage/geometry/polyhedron/backend_normaliz.py +2503 -0
- sage/geometry/polyhedron/backend_number_field.py +168 -0
- sage/geometry/polyhedron/backend_polymake.py +765 -0
- sage/geometry/polyhedron/backend_ppl.py +582 -0
- sage/geometry/polyhedron/base.py +1206 -0
- sage/geometry/polyhedron/base0.py +1444 -0
- sage/geometry/polyhedron/base1.py +886 -0
- sage/geometry/polyhedron/base2.py +812 -0
- sage/geometry/polyhedron/base3.py +1845 -0
- sage/geometry/polyhedron/base4.py +1262 -0
- sage/geometry/polyhedron/base5.py +2700 -0
- sage/geometry/polyhedron/base6.py +1741 -0
- sage/geometry/polyhedron/base7.py +997 -0
- sage/geometry/polyhedron/base_QQ.py +1258 -0
- sage/geometry/polyhedron/base_RDF.py +98 -0
- sage/geometry/polyhedron/base_ZZ.py +934 -0
- sage/geometry/polyhedron/base_mutable.py +215 -0
- sage/geometry/polyhedron/base_number_field.py +122 -0
- sage/geometry/polyhedron/cdd_file_format.py +155 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
- sage/geometry/polyhedron/constructor.py +773 -0
- sage/geometry/polyhedron/double_description.py +753 -0
- sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
- sage/geometry/polyhedron/face.py +1060 -0
- sage/geometry/polyhedron/generating_function.py +1810 -0
- sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
- sage/geometry/polyhedron/library.py +3502 -0
- sage/geometry/polyhedron/misc.py +121 -0
- sage/geometry/polyhedron/modules/all.py +1 -0
- sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
- sage/geometry/polyhedron/palp_database.py +447 -0
- sage/geometry/polyhedron/parent.py +1279 -0
- sage/geometry/polyhedron/plot.py +1986 -0
- sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
- sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
- sage/geometry/polyhedron/representation.py +1723 -0
- sage/geometry/pseudolines.py +515 -0
- sage/geometry/relative_interior.py +445 -0
- sage/geometry/toric_plotter.py +1103 -0
- sage/geometry/triangulation/all.py +2 -0
- sage/geometry/triangulation/base.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/triangulation/base.pyx +963 -0
- sage/geometry/triangulation/data.h +147 -0
- sage/geometry/triangulation/data.pxd +4 -0
- sage/geometry/triangulation/element.py +914 -0
- sage/geometry/triangulation/functions.h +10 -0
- sage/geometry/triangulation/functions.pxd +4 -0
- sage/geometry/triangulation/point_configuration.py +2256 -0
- sage/geometry/triangulation/triangulations.h +49 -0
- sage/geometry/triangulation/triangulations.pxd +7 -0
- sage/geometry/voronoi_diagram.py +319 -0
- sage/interfaces/all__sagemath_polyhedra.py +1 -0
- sage/interfaces/polymake.py +2028 -0
- sage/numerical/all.py +13 -0
- sage/numerical/all__sagemath_polyhedra.py +11 -0
- sage/numerical/backends/all.py +1 -0
- sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
- sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxopt_backend.pyx +1006 -0
- sage/numerical/backends/cvxopt_backend_test.py +19 -0
- sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxpy_backend.pxd +41 -0
- sage/numerical/backends/cvxpy_backend.pyx +934 -0
- sage/numerical/backends/cvxpy_backend_test.py +13 -0
- sage/numerical/backends/generic_backend_test.py +24 -0
- sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/interactivelp_backend.pxd +36 -0
- sage/numerical/backends/interactivelp_backend.pyx +1231 -0
- sage/numerical/backends/interactivelp_backend_test.py +12 -0
- sage/numerical/backends/logging_backend.py +391 -0
- sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
- sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
- sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/ppl_backend.pyx +1126 -0
- sage/numerical/backends/ppl_backend_test.py +13 -0
- sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/scip_backend.pxd +22 -0
- sage/numerical/backends/scip_backend.pyx +1289 -0
- sage/numerical/backends/scip_backend_test.py +13 -0
- sage/numerical/interactive_simplex_method.py +5338 -0
- sage/numerical/knapsack.py +665 -0
- sage/numerical/linear_functions.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/linear_functions.pxd +31 -0
- sage/numerical/linear_functions.pyx +1648 -0
- sage/numerical/linear_tensor.py +470 -0
- sage/numerical/linear_tensor_constraints.py +448 -0
- sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/sdp.pxd +39 -0
- sage/numerical/sdp.pyx +1433 -0
- sage/rings/all__sagemath_polyhedra.py +3 -0
- sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
- sage/rings/polynomial/omega.py +982 -0
- sage/schemes/all__sagemath_polyhedra.py +2 -0
- sage/schemes/toric/all.py +10 -0
- sage/schemes/toric/chow_group.py +1248 -0
- sage/schemes/toric/divisor.py +2082 -0
- sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/schemes/toric/divisor_class.pyx +322 -0
- sage/schemes/toric/fano_variety.py +1606 -0
- sage/schemes/toric/homset.py +650 -0
- sage/schemes/toric/ideal.py +451 -0
- sage/schemes/toric/library.py +1322 -0
- sage/schemes/toric/morphism.py +1958 -0
- sage/schemes/toric/points.py +1032 -0
- sage/schemes/toric/sheaf/all.py +1 -0
- sage/schemes/toric/sheaf/constructor.py +302 -0
- sage/schemes/toric/sheaf/klyachko.py +921 -0
- sage/schemes/toric/toric_subscheme.py +905 -0
- sage/schemes/toric/variety.py +3460 -0
- sage/schemes/toric/weierstrass.py +1078 -0
- sage/schemes/toric/weierstrass_covering.py +457 -0
- sage/schemes/toric/weierstrass_higher.py +288 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
|
@@ -0,0 +1,1444 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
r"""
|
|
3
|
+
Base class for polyhedra: Initialization and access to Vrepresentation and Hrepresentation
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# ****************************************************************************
|
|
7
|
+
# Copyright (C) 2008-2012 Marshall Hampton <hamptonio@gmail.com>
|
|
8
|
+
# Copyright (C) 2011-2015 Volker Braun <vbraun.name@gmail.com>
|
|
9
|
+
# Copyright (C) 2012-2018 Frederic Chapoton
|
|
10
|
+
# Copyright (C) 2013 Andrey Novoseltsev
|
|
11
|
+
# Copyright (C) 2014-2017 Moritz Firsching
|
|
12
|
+
# Copyright (C) 2014-2019 Thierry Monteil
|
|
13
|
+
# Copyright (C) 2015 Nathann Cohen
|
|
14
|
+
# Copyright (C) 2015-2017 Jeroen Demeyer
|
|
15
|
+
# Copyright (C) 2015-2017 Vincent Delecroix
|
|
16
|
+
# Copyright (C) 2015-2018 Dima Pasechnik
|
|
17
|
+
# Copyright (C) 2015-2020 Jean-Philippe Labbe <labbe at math.huji.ac.il>
|
|
18
|
+
# Copyright (C) 2015-2021 Matthias Koeppe
|
|
19
|
+
# Copyright (C) 2016-2019 Daniel Krenn
|
|
20
|
+
# Copyright (C) 2017 Marcelo Forets
|
|
21
|
+
# Copyright (C) 2017-2018 Mark Bell
|
|
22
|
+
# Copyright (C) 2019 Julian Ritter
|
|
23
|
+
# Copyright (C) 2019-2020 Laith Rastanawi
|
|
24
|
+
# Copyright (C) 2019-2020 Sophia Elia
|
|
25
|
+
# Copyright (C) 2019-2021 Jonathan Kliem <jonathan.kliem@gmail.com>
|
|
26
|
+
#
|
|
27
|
+
# This program is free software: you can redistribute it and/or modify
|
|
28
|
+
# it under the terms of the GNU General Public License as published by
|
|
29
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
30
|
+
# (at your option) any later version.
|
|
31
|
+
# https://www.gnu.org/licenses/
|
|
32
|
+
# ****************************************************************************
|
|
33
|
+
|
|
34
|
+
from sage.misc.cachefunc import cached_method
|
|
35
|
+
from sage.misc.abstract_method import abstract_method
|
|
36
|
+
from sage.structure.element import Element
|
|
37
|
+
import sage.geometry.abc
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Polyhedron_base0(Element, sage.geometry.abc.Polyhedron):
|
|
41
|
+
"""
|
|
42
|
+
Initialization and basic access for polyhedra.
|
|
43
|
+
|
|
44
|
+
See :class:`sage.geometry.polyhedron.base.Polyhedron_base`.
|
|
45
|
+
|
|
46
|
+
TESTS::
|
|
47
|
+
|
|
48
|
+
sage: from sage.geometry.polyhedron.base0 import Polyhedron_base0
|
|
49
|
+
sage: P = Polyhedron(rays=[[1, 0, 0]], lines=[[0, 1, 0]])
|
|
50
|
+
sage: Polyhedron_base0.Vrepresentation(P)
|
|
51
|
+
(A line in the direction (0, 1, 0),
|
|
52
|
+
A vertex at (0, 0, 0),
|
|
53
|
+
A ray in the direction (1, 0, 0))
|
|
54
|
+
sage: Polyhedron_base0.vertices.f(P)
|
|
55
|
+
(A vertex at (0, 0, 0),)
|
|
56
|
+
sage: Polyhedron_base0.rays.f(P)
|
|
57
|
+
(A ray in the direction (1, 0, 0),)
|
|
58
|
+
sage: Polyhedron_base0.lines.f(P)
|
|
59
|
+
(A line in the direction (0, 1, 0),)
|
|
60
|
+
sage: Polyhedron_base0.Hrepresentation(P)
|
|
61
|
+
(An equation (0, 0, 1) x + 0 == 0, An inequality (1, 0, 0) x + 0 >= 0)
|
|
62
|
+
sage: Polyhedron_base0.inequalities.f(P)
|
|
63
|
+
(An inequality (1, 0, 0) x + 0 >= 0,)
|
|
64
|
+
sage: Polyhedron_base0.equations.f(P)
|
|
65
|
+
(An equation (0, 0, 1) x + 0 == 0,)
|
|
66
|
+
sage: Polyhedron_base0.base_ring(P)
|
|
67
|
+
Integer Ring
|
|
68
|
+
sage: Polyhedron_base0.backend(P)
|
|
69
|
+
'ppl'
|
|
70
|
+
sage: Polyhedron_base0.change_ring(P, ZZ, backend='field').backend()
|
|
71
|
+
'field'
|
|
72
|
+
sage: Polyhedron_base0.base_extend(P, QQ)
|
|
73
|
+
A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 1 ray, 1 line
|
|
74
|
+
"""
|
|
75
|
+
def __init__(self, parent, Vrep, Hrep, Vrep_minimal=None, Hrep_minimal=None, pref_rep=None, mutable=False, **kwds):
|
|
76
|
+
"""
|
|
77
|
+
Initialize the polyhedron.
|
|
78
|
+
|
|
79
|
+
See :class:`sage.geometry.polyhedron.base.Polyhedron_base` for a description of the input
|
|
80
|
+
data.
|
|
81
|
+
|
|
82
|
+
TESTS::
|
|
83
|
+
|
|
84
|
+
sage: p = Polyhedron() # indirect doctests
|
|
85
|
+
|
|
86
|
+
sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field
|
|
87
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra_field
|
|
88
|
+
sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field
|
|
89
|
+
sage: Vrep = [[[0], [1/2], [1]], [], []]
|
|
90
|
+
sage: Hrep = [[[0, 1], [1, -1]], []]
|
|
91
|
+
sage: p = Polyhedron_field(parent, Vrep, Hrep, # needs sage.rings.number_field
|
|
92
|
+
....: Vrep_minimal=False, Hrep_minimal=True)
|
|
93
|
+
Traceback (most recent call last):
|
|
94
|
+
...
|
|
95
|
+
ValueError: if both Vrep and Hrep are provided, they must be minimal...
|
|
96
|
+
|
|
97
|
+
Illustration of ``pref_rep``.
|
|
98
|
+
Note that ``ppl`` doesn't support precomputed data::
|
|
99
|
+
|
|
100
|
+
sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl
|
|
101
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra_QQ_ppl
|
|
102
|
+
sage: parent = Polyhedra_QQ_ppl(QQ, 1, 'ppl')
|
|
103
|
+
sage: p = Polyhedron_QQ_ppl(parent, Vrep, 'nonsense',
|
|
104
|
+
....: Vrep_minimal=True, Hrep_minimal=True, pref_rep='Vrep')
|
|
105
|
+
sage: p = Polyhedron_QQ_ppl(parent, 'nonsense', Hrep,
|
|
106
|
+
....: Vrep_minimal=True, Hrep_minimal=True, pref_rep='Hrep')
|
|
107
|
+
sage: p = Polyhedron_QQ_ppl(parent, 'nonsense', Hrep,
|
|
108
|
+
....: Vrep_minimal=True, Hrep_minimal=True, pref_rep='Vrepresentation')
|
|
109
|
+
Traceback (most recent call last):
|
|
110
|
+
...
|
|
111
|
+
ValueError: ``pref_rep`` must be one of ``(None, 'Vrep', 'Hrep')``
|
|
112
|
+
|
|
113
|
+
If the backend supports precomputed data, ``pref_rep`` is ignored::
|
|
114
|
+
|
|
115
|
+
sage: p = Polyhedron_field(parent, Vrep, 'nonsense',
|
|
116
|
+
....: Vrep_minimal=True, Hrep_minimal=True, pref_rep='Vrep')
|
|
117
|
+
Traceback (most recent call last):
|
|
118
|
+
...
|
|
119
|
+
TypeError: ..._init_Hrepresentation() takes 3 positional arguments but 9 were given
|
|
120
|
+
|
|
121
|
+
The empty polyhedron is detected when the Vrepresentation is given with generator;
|
|
122
|
+
see :issue:`29899`::
|
|
123
|
+
|
|
124
|
+
sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd
|
|
125
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra_QQ_cdd
|
|
126
|
+
sage: parent = Polyhedra_QQ_cdd(QQ, 0, 'cdd')
|
|
127
|
+
sage: p = Polyhedron_QQ_cdd(parent, [iter([]), iter([]), iter([])], None)
|
|
128
|
+
"""
|
|
129
|
+
Element.__init__(self, parent=parent)
|
|
130
|
+
if Vrep is not None and Hrep is not None:
|
|
131
|
+
if not (Vrep_minimal is True and Hrep_minimal is True):
|
|
132
|
+
raise ValueError("if both Vrep and Hrep are provided, they must be minimal"
|
|
133
|
+
" and Vrep_minimal and Hrep_minimal must both be True")
|
|
134
|
+
if hasattr(self, "_init_from_Vrepresentation_and_Hrepresentation"):
|
|
135
|
+
self._init_from_Vrepresentation_and_Hrepresentation(Vrep, Hrep)
|
|
136
|
+
return
|
|
137
|
+
else:
|
|
138
|
+
if pref_rep is None:
|
|
139
|
+
# Initialize from Hrepresentation if this seems simpler.
|
|
140
|
+
Vrep = [tuple(Vrep[0]), tuple(Vrep[1]), Vrep[2]]
|
|
141
|
+
Hrep = [tuple(Hrep[0]), Hrep[1]]
|
|
142
|
+
if len(Hrep[0]) < len(Vrep[0]) + len(Vrep[1]):
|
|
143
|
+
pref_rep = 'Hrep'
|
|
144
|
+
else:
|
|
145
|
+
pref_rep = 'Vrep'
|
|
146
|
+
if pref_rep == 'Vrep':
|
|
147
|
+
Hrep = None
|
|
148
|
+
elif pref_rep == 'Hrep':
|
|
149
|
+
Vrep = None
|
|
150
|
+
else:
|
|
151
|
+
raise ValueError("``pref_rep`` must be one of ``(None, 'Vrep', 'Hrep')``")
|
|
152
|
+
if Vrep is not None:
|
|
153
|
+
vertices, rays, lines = Vrep
|
|
154
|
+
|
|
155
|
+
# We build tuples out of generators now to detect the empty polyhedron.
|
|
156
|
+
|
|
157
|
+
# The damage is limited:
|
|
158
|
+
# The backend will have to obtain all elements from the generator anyway.
|
|
159
|
+
# The generators are mainly for saving time with initializing from
|
|
160
|
+
# Vrepresentation and Hrepresentation.
|
|
161
|
+
# If we dispose of one of them (see above), it is wasteful to have generated it.
|
|
162
|
+
|
|
163
|
+
# E.g. the dilate will be set up with new Vrepresentation and Hrepresentation
|
|
164
|
+
# regardless of the backend along with the argument ``pref_rep``.
|
|
165
|
+
# As we only use generators, there is no penalty to this approach
|
|
166
|
+
# (and the method ``dilation`` does not have to distinguish by backend).
|
|
167
|
+
|
|
168
|
+
if not isinstance(vertices, (tuple, list)):
|
|
169
|
+
vertices = tuple(vertices)
|
|
170
|
+
if not isinstance(rays, (tuple, list)):
|
|
171
|
+
rays = tuple(rays)
|
|
172
|
+
if not isinstance(lines, (tuple, list)):
|
|
173
|
+
lines = tuple(lines)
|
|
174
|
+
|
|
175
|
+
if vertices or rays or lines:
|
|
176
|
+
self._init_from_Vrepresentation(vertices, rays, lines, **kwds)
|
|
177
|
+
else:
|
|
178
|
+
self._init_empty_polyhedron()
|
|
179
|
+
elif Hrep is not None:
|
|
180
|
+
ieqs, eqns = Hrep
|
|
181
|
+
self._init_from_Hrepresentation(ieqs, eqns, **kwds)
|
|
182
|
+
else:
|
|
183
|
+
self._init_empty_polyhedron()
|
|
184
|
+
|
|
185
|
+
@abstract_method
|
|
186
|
+
def _init_from_Vrepresentation(self, vertices, rays, lines, **kwds):
|
|
187
|
+
"""
|
|
188
|
+
Construct polyhedron from V-representation data.
|
|
189
|
+
|
|
190
|
+
INPUT:
|
|
191
|
+
|
|
192
|
+
- ``vertices`` -- list of point. Each point can be specified
|
|
193
|
+
as any iterable container of
|
|
194
|
+
:meth:`~sage.geometry.polyhedron.base.base_ring` elements.
|
|
195
|
+
|
|
196
|
+
- ``rays`` -- list of rays. Each ray can be specified as any
|
|
197
|
+
iterable container of
|
|
198
|
+
:meth:`~sage.geometry.polyhedron.base.base_ring` elements.
|
|
199
|
+
|
|
200
|
+
- ``lines`` -- list of lines. Each line can be specified as
|
|
201
|
+
any iterable container of
|
|
202
|
+
:meth:`~sage.geometry.polyhedron.base.base_ring` elements.
|
|
203
|
+
|
|
204
|
+
EXAMPLES::
|
|
205
|
+
|
|
206
|
+
sage: p = Polyhedron()
|
|
207
|
+
sage: from sage.geometry.polyhedron.base import Polyhedron_base
|
|
208
|
+
sage: Polyhedron_base._init_from_Vrepresentation(p, [], [], [])
|
|
209
|
+
Traceback (most recent call last):
|
|
210
|
+
...
|
|
211
|
+
TypeError: 'AbstractMethod' object is not callable
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
@abstract_method
|
|
215
|
+
def _init_from_Hrepresentation(self, ieqs, eqns, **kwds):
|
|
216
|
+
"""
|
|
217
|
+
Construct polyhedron from H-representation data.
|
|
218
|
+
|
|
219
|
+
INPUT:
|
|
220
|
+
|
|
221
|
+
- ``ieqs`` -- list of inequalities. Each line can be specified
|
|
222
|
+
as any iterable container of
|
|
223
|
+
:meth:`~sage.geometry.polyhedron.base.base_ring` elements.
|
|
224
|
+
|
|
225
|
+
- ``eqns`` -- list of equalities. Each line can be specified
|
|
226
|
+
as any iterable container of
|
|
227
|
+
:meth:`~sage.geometry.polyhedron.base.base_ring` elements.
|
|
228
|
+
|
|
229
|
+
EXAMPLES::
|
|
230
|
+
|
|
231
|
+
sage: p = Polyhedron()
|
|
232
|
+
sage: from sage.geometry.polyhedron.base import Polyhedron_base
|
|
233
|
+
sage: Polyhedron_base._init_from_Hrepresentation(p, [], [])
|
|
234
|
+
Traceback (most recent call last):
|
|
235
|
+
...
|
|
236
|
+
TypeError: 'AbstractMethod' object is not callable
|
|
237
|
+
"""
|
|
238
|
+
|
|
239
|
+
def _init_empty_polyhedron(self):
|
|
240
|
+
"""
|
|
241
|
+
Initialize an empty polyhedron.
|
|
242
|
+
|
|
243
|
+
TESTS::
|
|
244
|
+
|
|
245
|
+
sage: empty = Polyhedron(); empty
|
|
246
|
+
The empty polyhedron in ZZ^0
|
|
247
|
+
sage: empty.Vrepresentation()
|
|
248
|
+
()
|
|
249
|
+
sage: empty.Hrepresentation()
|
|
250
|
+
(An equation -1 == 0,)
|
|
251
|
+
sage: Polyhedron(vertices = [])
|
|
252
|
+
The empty polyhedron in ZZ^0
|
|
253
|
+
sage: Polyhedron(vertices = [])._init_empty_polyhedron()
|
|
254
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
255
|
+
sage: Polyhedra(QQ,7)()
|
|
256
|
+
A 0-dimensional polyhedron in QQ^7 defined as the convex hull of 1 vertex
|
|
257
|
+
"""
|
|
258
|
+
self._Vrepresentation = []
|
|
259
|
+
self._Hrepresentation = []
|
|
260
|
+
self.parent()._make_Equation(self, [-1] + [0] * self.ambient_dim())
|
|
261
|
+
self._Vrepresentation = tuple(self._Vrepresentation)
|
|
262
|
+
self._Hrepresentation = tuple(self._Hrepresentation)
|
|
263
|
+
|
|
264
|
+
def _delete(self):
|
|
265
|
+
"""
|
|
266
|
+
Delete this polyhedron.
|
|
267
|
+
|
|
268
|
+
This speeds up creation of new polyhedra by reusing
|
|
269
|
+
objects. After recycling a polyhedron object, it is not in a
|
|
270
|
+
consistent state any more and neither the polyhedron nor its
|
|
271
|
+
H/V-representation objects may be used any more.
|
|
272
|
+
|
|
273
|
+
.. SEEALSO::
|
|
274
|
+
|
|
275
|
+
:meth:`~sage.geometry.polyhedron.parent.Polyhedra_base.recycle`
|
|
276
|
+
|
|
277
|
+
EXAMPLES::
|
|
278
|
+
|
|
279
|
+
sage: p = Polyhedron([(0,0),(1,0),(0,1)])
|
|
280
|
+
sage: p._delete()
|
|
281
|
+
|
|
282
|
+
sage: vertices = [(0,0,0,0),(1,0,0,0),(0,1,0,0),(1,1,0,0),(0,0,1,0),(0,0,0,1)]
|
|
283
|
+
sage: def loop_polyhedra():
|
|
284
|
+
....: for i in range(100):
|
|
285
|
+
....: p = Polyhedron(vertices)
|
|
286
|
+
|
|
287
|
+
sage: timeit('loop_polyhedra()') # not tested - random
|
|
288
|
+
5 loops, best of 3: 79.5 ms per loop
|
|
289
|
+
|
|
290
|
+
sage: def loop_polyhedra_with_recycling():
|
|
291
|
+
....: for i in range(100):
|
|
292
|
+
....: p = Polyhedron(vertices)
|
|
293
|
+
....: p._delete()
|
|
294
|
+
|
|
295
|
+
sage: timeit('loop_polyhedra_with_recycling()') # not tested - random
|
|
296
|
+
5 loops, best of 3: 57.3 ms per loop
|
|
297
|
+
"""
|
|
298
|
+
self.parent().recycle(self)
|
|
299
|
+
|
|
300
|
+
def _sage_input_(self, sib, coerced):
|
|
301
|
+
"""
|
|
302
|
+
Return Sage command to reconstruct ``self``.
|
|
303
|
+
|
|
304
|
+
See :mod:`sage.misc.sage_input` for details.
|
|
305
|
+
|
|
306
|
+
.. TODO::
|
|
307
|
+
|
|
308
|
+
Add the option ``preparse`` to the method.
|
|
309
|
+
|
|
310
|
+
EXAMPLES::
|
|
311
|
+
|
|
312
|
+
sage: P = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]], backend='ppl')
|
|
313
|
+
sage: sage_input(P)
|
|
314
|
+
Polyhedron(backend='ppl', base_ring=QQ, rays=[(QQ(1), QQ(1))], vertices=[(QQ(0), QQ(1)), (QQ(1), QQ(0))])
|
|
315
|
+
sage: P = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]], backend='normaliz') # optional - pynormaliz
|
|
316
|
+
sage: sage_input(P) # optional - pynormaliz
|
|
317
|
+
Polyhedron(backend='normaliz', base_ring=QQ, rays=[(QQ(1), QQ(1))], vertices=[(QQ(0), QQ(1)), (QQ(1), QQ(0))])
|
|
318
|
+
sage: P = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]], backend='polymake') # optional - jupymake
|
|
319
|
+
sage: sage_input(P) # optional - jupymake
|
|
320
|
+
Polyhedron(backend='polymake', base_ring=QQ, rays=[(QQ(1), QQ(1))], vertices=[(QQ(1), QQ(0)), (QQ(0), QQ(1))])
|
|
321
|
+
"""
|
|
322
|
+
kwds = dict()
|
|
323
|
+
kwds['base_ring'] = sib(self.base_ring())
|
|
324
|
+
kwds['backend'] = sib(self.backend())
|
|
325
|
+
if self.n_vertices() > 0:
|
|
326
|
+
kwds['vertices'] = [sib(tuple(v)) for v in self.vertices()]
|
|
327
|
+
if self.n_rays() > 0:
|
|
328
|
+
kwds['rays'] = [sib(tuple(r)) for r in self.rays()]
|
|
329
|
+
if self.n_lines() > 0:
|
|
330
|
+
kwds['lines'] = [sib(tuple(l)) for l in self.lines()]
|
|
331
|
+
return sib.name('Polyhedron')(**kwds)
|
|
332
|
+
|
|
333
|
+
def base_extend(self, base_ring, backend=None):
|
|
334
|
+
"""
|
|
335
|
+
Return a new polyhedron over a larger base ring.
|
|
336
|
+
|
|
337
|
+
This method can also be used to change the backend.
|
|
338
|
+
|
|
339
|
+
INPUT:
|
|
340
|
+
|
|
341
|
+
- ``base_ring`` -- the new base ring
|
|
342
|
+
|
|
343
|
+
- ``backend`` -- the new backend, see
|
|
344
|
+
:func:`~sage.geometry.polyhedron.constructor.Polyhedron`
|
|
345
|
+
If ``None`` (the default), attempt to keep the same backend.
|
|
346
|
+
Otherwise, use the same defaulting behavior
|
|
347
|
+
as described there.
|
|
348
|
+
|
|
349
|
+
OUTPUT: the same polyhedron, but over a larger base ring and possibly with a changed backend
|
|
350
|
+
|
|
351
|
+
EXAMPLES::
|
|
352
|
+
|
|
353
|
+
sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)], base_ring=ZZ); P
|
|
354
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices and 1 ray
|
|
355
|
+
sage: P.base_extend(QQ)
|
|
356
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 1 ray
|
|
357
|
+
sage: P.base_extend(QQ) == P
|
|
358
|
+
True
|
|
359
|
+
|
|
360
|
+
TESTS:
|
|
361
|
+
|
|
362
|
+
Test that :issue:`22575` is fixed::
|
|
363
|
+
|
|
364
|
+
sage: Q = P.base_extend(ZZ, backend='field')
|
|
365
|
+
sage: Q.backend()
|
|
366
|
+
'field'
|
|
367
|
+
"""
|
|
368
|
+
new_parent = self.parent().base_extend(base_ring, backend)
|
|
369
|
+
return new_parent(self, copy=True)
|
|
370
|
+
|
|
371
|
+
def change_ring(self, base_ring, backend=None):
|
|
372
|
+
"""
|
|
373
|
+
Return the polyhedron obtained by coercing the entries of the
|
|
374
|
+
vertices/lines/rays of this polyhedron into the given ring.
|
|
375
|
+
|
|
376
|
+
This method can also be used to change the backend.
|
|
377
|
+
|
|
378
|
+
INPUT:
|
|
379
|
+
|
|
380
|
+
- ``base_ring`` -- the new base ring
|
|
381
|
+
|
|
382
|
+
- ``backend`` -- the new backend or ``None`` (default), see
|
|
383
|
+
:func:`~sage.geometry.polyhedron.constructor.Polyhedron`.
|
|
384
|
+
If ``None`` (the default), attempt to keep the same backend.
|
|
385
|
+
Otherwise, use the same defaulting behavior
|
|
386
|
+
as described there.
|
|
387
|
+
|
|
388
|
+
EXAMPLES::
|
|
389
|
+
|
|
390
|
+
sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)], base_ring=QQ); P
|
|
391
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 1 ray
|
|
392
|
+
sage: P.change_ring(ZZ)
|
|
393
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices and 1 ray
|
|
394
|
+
sage: P.change_ring(ZZ) == P
|
|
395
|
+
True
|
|
396
|
+
|
|
397
|
+
sage: # needs cddexec
|
|
398
|
+
sage: P = Polyhedron(vertices=[(-1.3,0), (0,2.3)], base_ring=RDF); P.vertices()
|
|
399
|
+
(A vertex at (-1.3, 0.0), A vertex at (0.0, 2.3))
|
|
400
|
+
sage: P.change_ring(QQ).vertices()
|
|
401
|
+
(A vertex at (-13/10, 0), A vertex at (0, 23/10))
|
|
402
|
+
sage: P == P.change_ring(QQ)
|
|
403
|
+
True
|
|
404
|
+
sage: P.change_ring(ZZ)
|
|
405
|
+
Traceback (most recent call last):
|
|
406
|
+
...
|
|
407
|
+
TypeError: cannot change the base ring to the Integer Ring
|
|
408
|
+
|
|
409
|
+
sage: P = polytopes.regular_polygon(3); P # needs sage.rings.number_field
|
|
410
|
+
A 2-dimensional polyhedron in AA^2 defined as the convex hull of 3 vertices
|
|
411
|
+
sage: P.vertices() # needs sage.rings.number_field
|
|
412
|
+
(A vertex at (0.?e-16, 1.000000000000000?),
|
|
413
|
+
A vertex at (0.866025403784439?, -0.500000000000000?),
|
|
414
|
+
A vertex at (-0.866025403784439?, -0.500000000000000?))
|
|
415
|
+
sage: P.change_ring(QQ) # needs sage.rings.number_field
|
|
416
|
+
Traceback (most recent call last):
|
|
417
|
+
...
|
|
418
|
+
TypeError: cannot change the base ring to the Rational Field
|
|
419
|
+
|
|
420
|
+
.. WARNING::
|
|
421
|
+
|
|
422
|
+
The base ring ``RDF`` should be used with care. As it is
|
|
423
|
+
not an exact ring, certain computations may break or
|
|
424
|
+
silently produce wrong results, for example changing the
|
|
425
|
+
base ring from an exact ring into ``RDF`` may cause a
|
|
426
|
+
loss of data::
|
|
427
|
+
|
|
428
|
+
sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P # needs sage.rings.number_field
|
|
429
|
+
A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices
|
|
430
|
+
sage: Q = P.change_ring(RDF); Q # needs cddexec sage.rings.number_field
|
|
431
|
+
A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex
|
|
432
|
+
sage: P.n_vertices() == Q.n_vertices() # needs cddexec sage.rings.number_field
|
|
433
|
+
False
|
|
434
|
+
"""
|
|
435
|
+
from sage.categories.rings import Rings
|
|
436
|
+
|
|
437
|
+
if base_ring not in Rings():
|
|
438
|
+
raise ValueError("invalid base ring")
|
|
439
|
+
|
|
440
|
+
try:
|
|
441
|
+
vertices = [[base_ring(x) for x in vertex] for vertex in self.vertices_list()]
|
|
442
|
+
rays = [[base_ring(x) for x in ray] for ray in self.rays_list()]
|
|
443
|
+
lines = [[base_ring(x) for x in line] for line in self.lines_list()]
|
|
444
|
+
|
|
445
|
+
except (TypeError, ValueError):
|
|
446
|
+
raise TypeError("cannot change the base ring to the {0}".format(base_ring))
|
|
447
|
+
|
|
448
|
+
new_parent = self.parent().change_ring(base_ring, backend)
|
|
449
|
+
return new_parent([vertices, rays, lines], None)
|
|
450
|
+
|
|
451
|
+
def is_mutable(self):
|
|
452
|
+
r"""
|
|
453
|
+
Return ``True`` if the polyhedron is mutable, i.e. it can be modified in place.
|
|
454
|
+
|
|
455
|
+
EXAMPLES::
|
|
456
|
+
|
|
457
|
+
sage: p = polytopes.cube(backend='field')
|
|
458
|
+
sage: p.is_mutable()
|
|
459
|
+
False
|
|
460
|
+
"""
|
|
461
|
+
return False
|
|
462
|
+
|
|
463
|
+
def is_immutable(self):
|
|
464
|
+
r"""
|
|
465
|
+
Return ``True`` if the polyhedron is immutable, i.e. it cannot be modified in place.
|
|
466
|
+
|
|
467
|
+
EXAMPLES::
|
|
468
|
+
|
|
469
|
+
sage: p = polytopes.cube(backend='field')
|
|
470
|
+
sage: p.is_immutable()
|
|
471
|
+
True
|
|
472
|
+
"""
|
|
473
|
+
return True
|
|
474
|
+
|
|
475
|
+
@cached_method
|
|
476
|
+
def n_equations(self):
|
|
477
|
+
"""
|
|
478
|
+
Return the number of equations. The representation will
|
|
479
|
+
always be minimal, so the number of equations is the
|
|
480
|
+
codimension of the polyhedron in the ambient space.
|
|
481
|
+
|
|
482
|
+
EXAMPLES::
|
|
483
|
+
|
|
484
|
+
sage: p = Polyhedron(vertices = [[1,0,0],[0,1,0],[0,0,1]])
|
|
485
|
+
sage: p.n_equations()
|
|
486
|
+
1
|
|
487
|
+
"""
|
|
488
|
+
return len(self.equations())
|
|
489
|
+
|
|
490
|
+
@cached_method
|
|
491
|
+
def n_inequalities(self):
|
|
492
|
+
"""
|
|
493
|
+
Return the number of inequalities. The representation will
|
|
494
|
+
always be minimal, so the number of inequalities is the
|
|
495
|
+
number of facets of the polyhedron in the ambient space.
|
|
496
|
+
|
|
497
|
+
EXAMPLES::
|
|
498
|
+
|
|
499
|
+
sage: p = Polyhedron(vertices = [[1,0,0],[0,1,0],[0,0,1]])
|
|
500
|
+
sage: p.n_inequalities()
|
|
501
|
+
3
|
|
502
|
+
|
|
503
|
+
sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in range(6)])
|
|
504
|
+
sage: p.n_facets()
|
|
505
|
+
8
|
|
506
|
+
"""
|
|
507
|
+
return len(self.inequalities())
|
|
508
|
+
|
|
509
|
+
n_facets = n_inequalities
|
|
510
|
+
|
|
511
|
+
@cached_method
|
|
512
|
+
def n_vertices(self):
|
|
513
|
+
"""
|
|
514
|
+
Return the number of vertices. The representation will
|
|
515
|
+
always be minimal.
|
|
516
|
+
|
|
517
|
+
.. WARNING::
|
|
518
|
+
|
|
519
|
+
If the polyhedron has lines, return the number of vertices in
|
|
520
|
+
the ``Vrepresentation``. As the represented polyhedron has
|
|
521
|
+
no 0-dimensional faces (i.e. vertices), ``n_vertices`` corresponds
|
|
522
|
+
to the number of `k`-faces, where `k` is the number of lines::
|
|
523
|
+
|
|
524
|
+
sage: P = Polyhedron(rays=[[1,0,0]],lines=[[0,1,0]])
|
|
525
|
+
sage: P.n_vertices()
|
|
526
|
+
1
|
|
527
|
+
sage: P.faces(0)
|
|
528
|
+
()
|
|
529
|
+
sage: P.f_vector()
|
|
530
|
+
(1, 0, 1, 1)
|
|
531
|
+
|
|
532
|
+
sage: P = Polyhedron(rays=[[1,0,0]],lines=[[0,1,0],[0,1,1]])
|
|
533
|
+
sage: P.n_vertices()
|
|
534
|
+
1
|
|
535
|
+
sage: P.f_vector()
|
|
536
|
+
(1, 0, 0, 1, 1)
|
|
537
|
+
|
|
538
|
+
EXAMPLES::
|
|
539
|
+
|
|
540
|
+
sage: p = Polyhedron(vertices = [[1,0],[0,1],[1,1]], rays=[[1,1]])
|
|
541
|
+
sage: p.n_vertices()
|
|
542
|
+
2
|
|
543
|
+
"""
|
|
544
|
+
return len(self.vertices())
|
|
545
|
+
|
|
546
|
+
@cached_method
|
|
547
|
+
def n_rays(self):
|
|
548
|
+
"""
|
|
549
|
+
Return the number of rays. The representation will
|
|
550
|
+
always be minimal.
|
|
551
|
+
|
|
552
|
+
EXAMPLES::
|
|
553
|
+
|
|
554
|
+
sage: p = Polyhedron(vertices = [[1,0],[0,1]], rays=[[1,1]])
|
|
555
|
+
sage: p.n_rays()
|
|
556
|
+
1
|
|
557
|
+
"""
|
|
558
|
+
return len(self.rays())
|
|
559
|
+
|
|
560
|
+
@cached_method
|
|
561
|
+
def n_lines(self):
|
|
562
|
+
"""
|
|
563
|
+
Return the number of lines. The representation will
|
|
564
|
+
always be minimal.
|
|
565
|
+
|
|
566
|
+
EXAMPLES::
|
|
567
|
+
|
|
568
|
+
sage: p = Polyhedron(vertices = [[0,0]], rays=[[0,1],[0,-1]])
|
|
569
|
+
sage: p.n_lines()
|
|
570
|
+
1
|
|
571
|
+
"""
|
|
572
|
+
return len(self.lines())
|
|
573
|
+
|
|
574
|
+
def is_compact(self):
|
|
575
|
+
"""
|
|
576
|
+
Test for boundedness of the polytope.
|
|
577
|
+
|
|
578
|
+
EXAMPLES::
|
|
579
|
+
|
|
580
|
+
sage: p = polytopes.icosahedron() # needs sage.groups sage.rings.number_field
|
|
581
|
+
sage: p.is_compact() # needs sage.groups sage.rings.number_field
|
|
582
|
+
True
|
|
583
|
+
sage: p = Polyhedron(ieqs=[[0,1,0,0],[0,0,1,0],[0,0,0,1],[1,-1,0,0]])
|
|
584
|
+
sage: p.is_compact()
|
|
585
|
+
False
|
|
586
|
+
"""
|
|
587
|
+
return self.n_rays() == 0 and self.n_lines() == 0
|
|
588
|
+
|
|
589
|
+
def Hrepresentation(self, index=None):
|
|
590
|
+
"""
|
|
591
|
+
Return the objects of the H-representation. Each entry is
|
|
592
|
+
either an inequality or a equation.
|
|
593
|
+
|
|
594
|
+
INPUT:
|
|
595
|
+
|
|
596
|
+
- ``index`` -- either an integer or ``None``
|
|
597
|
+
|
|
598
|
+
OUTPUT:
|
|
599
|
+
|
|
600
|
+
The optional argument is an index running from ``0`` to
|
|
601
|
+
``self.n_Hrepresentation()-1``. If present, the
|
|
602
|
+
H-representation object at the given index will be
|
|
603
|
+
returned. Without an argument, returns the list of all
|
|
604
|
+
H-representation objects.
|
|
605
|
+
|
|
606
|
+
EXAMPLES::
|
|
607
|
+
|
|
608
|
+
sage: p = polytopes.hypercube(3, backend='field')
|
|
609
|
+
sage: p.Hrepresentation(0)
|
|
610
|
+
An inequality (-1, 0, 0) x + 1 >= 0
|
|
611
|
+
sage: p.Hrepresentation(0) == p.Hrepresentation()[0]
|
|
612
|
+
True
|
|
613
|
+
"""
|
|
614
|
+
if index is None:
|
|
615
|
+
return self._Hrepresentation
|
|
616
|
+
else:
|
|
617
|
+
return self._Hrepresentation[index]
|
|
618
|
+
|
|
619
|
+
def Hrepresentation_str(self, separator='\n', latex=False, style='>=', align=None, **kwds):
|
|
620
|
+
r"""
|
|
621
|
+
Return a human-readable string representation of the Hrepresentation of this
|
|
622
|
+
polyhedron.
|
|
623
|
+
|
|
624
|
+
INPUT:
|
|
625
|
+
|
|
626
|
+
- ``separator`` -- string (default: ``'\n'``)
|
|
627
|
+
|
|
628
|
+
- ``latex`` -- boolean (default: ``False``)
|
|
629
|
+
|
|
630
|
+
- ``style`` -- either ``'positive'`` (making all coefficients positive)
|
|
631
|
+
or ``'<='``, or ``'>='``; default is ``'>='``
|
|
632
|
+
|
|
633
|
+
- ``align`` -- boolean or ``None''; default is ``None`` in which case
|
|
634
|
+
``align`` is ``True`` if ``separator`` is the newline character.
|
|
635
|
+
If set, then the lines of the output string are aligned
|
|
636
|
+
by the comparison symbol by padding blanks.
|
|
637
|
+
|
|
638
|
+
Keyword parameters of
|
|
639
|
+
:meth:`~sage.geometry.polyhedron.representation.Hrepresentation.repr_pretty`
|
|
640
|
+
are passed on:
|
|
641
|
+
|
|
642
|
+
- ``prefix`` -- string
|
|
643
|
+
|
|
644
|
+
- ``indices`` -- tuple or other iterable
|
|
645
|
+
|
|
646
|
+
OUTPUT: string
|
|
647
|
+
|
|
648
|
+
EXAMPLES::
|
|
649
|
+
|
|
650
|
+
sage: P = polytopes.permutahedron(3)
|
|
651
|
+
sage: print(P.Hrepresentation_str())
|
|
652
|
+
x0 + x1 + x2 == 6
|
|
653
|
+
x0 + x1 >= 3
|
|
654
|
+
-x0 - x1 >= -5
|
|
655
|
+
x1 >= 1
|
|
656
|
+
-x0 >= -3
|
|
657
|
+
x0 >= 1
|
|
658
|
+
-x1 >= -3
|
|
659
|
+
|
|
660
|
+
sage: print(P.Hrepresentation_str(style='<='))
|
|
661
|
+
-x0 - x1 - x2 == -6
|
|
662
|
+
-x0 - x1 <= -3
|
|
663
|
+
x0 + x1 <= 5
|
|
664
|
+
-x1 <= -1
|
|
665
|
+
x0 <= 3
|
|
666
|
+
-x0 <= -1
|
|
667
|
+
x1 <= 3
|
|
668
|
+
|
|
669
|
+
sage: print(P.Hrepresentation_str(style='positive'))
|
|
670
|
+
x0 + x1 + x2 == 6
|
|
671
|
+
x0 + x1 >= 3
|
|
672
|
+
5 >= x0 + x1
|
|
673
|
+
x1 >= 1
|
|
674
|
+
3 >= x0
|
|
675
|
+
x0 >= 1
|
|
676
|
+
3 >= x1
|
|
677
|
+
|
|
678
|
+
sage: print(P.Hrepresentation_str(latex=True))
|
|
679
|
+
\begin{array}{rcl}
|
|
680
|
+
x_{0} + x_{1} + x_{2} & = & 6 \\
|
|
681
|
+
x_{0} + x_{1} & \geq & 3 \\
|
|
682
|
+
-x_{0} - x_{1} & \geq & -5 \\
|
|
683
|
+
x_{1} & \geq & 1 \\
|
|
684
|
+
-x_{0} & \geq & -3 \\
|
|
685
|
+
x_{0} & \geq & 1 \\
|
|
686
|
+
-x_{1} & \geq & -3
|
|
687
|
+
\end{array}
|
|
688
|
+
|
|
689
|
+
sage: print(P.Hrepresentation_str(align=False))
|
|
690
|
+
x0 + x1 + x2 == 6
|
|
691
|
+
x0 + x1 >= 3
|
|
692
|
+
-x0 - x1 >= -5
|
|
693
|
+
x1 >= 1
|
|
694
|
+
-x0 >= -3
|
|
695
|
+
x0 >= 1
|
|
696
|
+
-x1 >= -3
|
|
697
|
+
|
|
698
|
+
sage: c = polytopes.cube()
|
|
699
|
+
sage: c.Hrepresentation_str(separator=', ', style='positive')
|
|
700
|
+
'1 >= x0, 1 >= x1, 1 >= x2, 1 + x0 >= 0, 1 + x2 >= 0, 1 + x1 >= 0'
|
|
701
|
+
"""
|
|
702
|
+
pretty_hs = [h.repr_pretty(split=True, latex=latex, style=style, **kwds) for h in self.Hrepresentation()]
|
|
703
|
+
shift = any(pretty_h[2].startswith('-') for pretty_h in pretty_hs)
|
|
704
|
+
|
|
705
|
+
if align is None:
|
|
706
|
+
align = separator == "\n"
|
|
707
|
+
if align:
|
|
708
|
+
lengths = [(len(s[0]), len(s[1]), len(s[2])) for s in pretty_hs]
|
|
709
|
+
from operator import itemgetter
|
|
710
|
+
length_left = max(lengths, key=itemgetter(0))[0]
|
|
711
|
+
length_middle = max(lengths, key=itemgetter(1))[1]
|
|
712
|
+
length_right = max(lengths, key=itemgetter(2))[2]
|
|
713
|
+
if shift:
|
|
714
|
+
length_right += 1
|
|
715
|
+
if latex:
|
|
716
|
+
h_line = "{:>" + "{}".format(length_left) + "} & {:" + \
|
|
717
|
+
"{}".format(length_middle) + "} & {:" + \
|
|
718
|
+
"{}".format(length_right) + "}\\\\"
|
|
719
|
+
else:
|
|
720
|
+
h_line = "{:>" + "{}".format(length_left) \
|
|
721
|
+
+ "} {:" + "{}".format(length_middle) \
|
|
722
|
+
+ "} {:" + "{}".format(length_right) + "}"
|
|
723
|
+
elif latex:
|
|
724
|
+
h_line = "{} & {} & {}\\\\"
|
|
725
|
+
else:
|
|
726
|
+
h_line = "{} {} {}"
|
|
727
|
+
|
|
728
|
+
def pad_non_minus(s):
|
|
729
|
+
if align and shift and not s.startswith('-'):
|
|
730
|
+
return ' ' + s
|
|
731
|
+
else:
|
|
732
|
+
return s
|
|
733
|
+
h_list = [h_line.format(pretty_h[0], pretty_h[1], pad_non_minus(pretty_h[2]))
|
|
734
|
+
for pretty_h in pretty_hs]
|
|
735
|
+
pretty_print = separator.join(h_list)
|
|
736
|
+
|
|
737
|
+
if not latex:
|
|
738
|
+
return pretty_print
|
|
739
|
+
else:
|
|
740
|
+
# below we remove the 2 unnecessary backslashes at the end of pretty_print
|
|
741
|
+
return "\\begin{array}{rcl}\n" + pretty_print[:-2] + "\n\\end{array}"
|
|
742
|
+
|
|
743
|
+
def Hrep_generator(self):
|
|
744
|
+
"""
|
|
745
|
+
Return an iterator over the objects of the H-representation
|
|
746
|
+
(inequalities or equations).
|
|
747
|
+
|
|
748
|
+
EXAMPLES::
|
|
749
|
+
|
|
750
|
+
sage: p = polytopes.hypercube(3)
|
|
751
|
+
sage: next(p.Hrep_generator())
|
|
752
|
+
An inequality (-1, 0, 0) x + 1 >= 0
|
|
753
|
+
"""
|
|
754
|
+
yield from self.Hrepresentation()
|
|
755
|
+
|
|
756
|
+
@cached_method
|
|
757
|
+
def n_Hrepresentation(self):
|
|
758
|
+
"""
|
|
759
|
+
Return the number of objects that make up the
|
|
760
|
+
H-representation of the polyhedron.
|
|
761
|
+
|
|
762
|
+
OUTPUT: integer
|
|
763
|
+
|
|
764
|
+
EXAMPLES::
|
|
765
|
+
|
|
766
|
+
sage: p = polytopes.cross_polytope(4)
|
|
767
|
+
sage: p.n_Hrepresentation()
|
|
768
|
+
16
|
|
769
|
+
sage: p.n_Hrepresentation() == p.n_inequalities() + p.n_equations()
|
|
770
|
+
True
|
|
771
|
+
"""
|
|
772
|
+
return len(self.Hrepresentation())
|
|
773
|
+
|
|
774
|
+
def Vrepresentation(self, index=None):
|
|
775
|
+
"""
|
|
776
|
+
Return the objects of the V-representation. Each entry is
|
|
777
|
+
either a vertex, a ray, or a line.
|
|
778
|
+
|
|
779
|
+
See :mod:`sage.geometry.polyhedron.constructor` for a
|
|
780
|
+
definition of vertex/ray/line.
|
|
781
|
+
|
|
782
|
+
INPUT:
|
|
783
|
+
|
|
784
|
+
- ``index`` -- either an integer or ``None``
|
|
785
|
+
|
|
786
|
+
OUTPUT:
|
|
787
|
+
|
|
788
|
+
The optional argument is an index running from ``0`` to
|
|
789
|
+
``self.n_Vrepresentation()-1``. If present, the
|
|
790
|
+
V-representation object at the given index will be
|
|
791
|
+
returned. Without an argument, returns the list of all
|
|
792
|
+
V-representation objects.
|
|
793
|
+
|
|
794
|
+
EXAMPLES::
|
|
795
|
+
|
|
796
|
+
sage: p = polytopes.simplex(4, project=True) # needs cddexec
|
|
797
|
+
sage: p.Vrepresentation(0) # needs cddexec
|
|
798
|
+
A vertex at (0.7071067812, 0.4082482905, 0.2886751346, 0.2236067977)
|
|
799
|
+
sage: p.Vrepresentation(0) == p.Vrepresentation() [0] # needs cddexec
|
|
800
|
+
True
|
|
801
|
+
"""
|
|
802
|
+
if index is None:
|
|
803
|
+
return self._Vrepresentation
|
|
804
|
+
else:
|
|
805
|
+
return self._Vrepresentation[index]
|
|
806
|
+
|
|
807
|
+
@cached_method
|
|
808
|
+
def n_Vrepresentation(self):
|
|
809
|
+
"""
|
|
810
|
+
Return the number of objects that make up the
|
|
811
|
+
V-representation of the polyhedron.
|
|
812
|
+
|
|
813
|
+
OUTPUT: integer
|
|
814
|
+
|
|
815
|
+
EXAMPLES::
|
|
816
|
+
|
|
817
|
+
sage: p = polytopes.simplex(4)
|
|
818
|
+
sage: p.n_Vrepresentation()
|
|
819
|
+
5
|
|
820
|
+
sage: p.n_Vrepresentation() == p.n_vertices() + p.n_rays() + p.n_lines()
|
|
821
|
+
True
|
|
822
|
+
"""
|
|
823
|
+
return len(self.Vrepresentation())
|
|
824
|
+
|
|
825
|
+
def Vrep_generator(self):
|
|
826
|
+
"""
|
|
827
|
+
Return an iterator over the objects of the V-representation
|
|
828
|
+
(vertices, rays, and lines).
|
|
829
|
+
|
|
830
|
+
EXAMPLES::
|
|
831
|
+
|
|
832
|
+
sage: p = polytopes.cyclic_polytope(3,4)
|
|
833
|
+
sage: vg = p.Vrep_generator()
|
|
834
|
+
sage: next(vg)
|
|
835
|
+
A vertex at (0, 0, 0)
|
|
836
|
+
sage: next(vg)
|
|
837
|
+
A vertex at (1, 1, 1)
|
|
838
|
+
"""
|
|
839
|
+
yield from self.Vrepresentation()
|
|
840
|
+
|
|
841
|
+
def inequality_generator(self):
|
|
842
|
+
"""
|
|
843
|
+
Return a generator for the defining inequalities of the
|
|
844
|
+
polyhedron.
|
|
845
|
+
|
|
846
|
+
OUTPUT: a generator of the inequality Hrepresentation objects
|
|
847
|
+
|
|
848
|
+
EXAMPLES::
|
|
849
|
+
|
|
850
|
+
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
|
|
851
|
+
sage: for v in triangle.inequality_generator(): print(v)
|
|
852
|
+
An inequality (1, 1) x - 1 >= 0
|
|
853
|
+
An inequality (0, -1) x + 1 >= 0
|
|
854
|
+
An inequality (-1, 0) x + 1 >= 0
|
|
855
|
+
sage: [ v for v in triangle.inequality_generator() ]
|
|
856
|
+
[An inequality (1, 1) x - 1 >= 0,
|
|
857
|
+
An inequality (0, -1) x + 1 >= 0,
|
|
858
|
+
An inequality (-1, 0) x + 1 >= 0]
|
|
859
|
+
sage: [ [v.A(), v.b()] for v in triangle.inequality_generator() ]
|
|
860
|
+
[[(1, 1), -1], [(0, -1), 1], [(-1, 0), 1]]
|
|
861
|
+
"""
|
|
862
|
+
for H in self.Hrepresentation():
|
|
863
|
+
if H.is_inequality():
|
|
864
|
+
yield H
|
|
865
|
+
|
|
866
|
+
@cached_method
|
|
867
|
+
def inequalities(self):
|
|
868
|
+
"""
|
|
869
|
+
Return all inequalities.
|
|
870
|
+
|
|
871
|
+
OUTPUT: a tuple of inequalities
|
|
872
|
+
|
|
873
|
+
EXAMPLES::
|
|
874
|
+
|
|
875
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[0,0,1],[0,1,0],[1,0,0],[2,2,2]])
|
|
876
|
+
sage: p.inequalities()[0:3]
|
|
877
|
+
(An inequality (1, 0, 0) x + 0 >= 0,
|
|
878
|
+
An inequality (0, 1, 0) x + 0 >= 0,
|
|
879
|
+
An inequality (0, 0, 1) x + 0 >= 0)
|
|
880
|
+
|
|
881
|
+
sage: # needs sage.combinat
|
|
882
|
+
sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4]))
|
|
883
|
+
sage: ieqs = p3.inequalities()
|
|
884
|
+
sage: ieqs[0]
|
|
885
|
+
An inequality (0, 1, 1, 1) x - 6 >= 0
|
|
886
|
+
sage: list(_)
|
|
887
|
+
[-6, 0, 1, 1, 1]
|
|
888
|
+
"""
|
|
889
|
+
return tuple(self.inequality_generator())
|
|
890
|
+
|
|
891
|
+
def inequalities_list(self):
|
|
892
|
+
"""
|
|
893
|
+
Return a list of inequalities as coefficient lists.
|
|
894
|
+
|
|
895
|
+
.. NOTE::
|
|
896
|
+
|
|
897
|
+
It is recommended to use :meth:`inequalities` or
|
|
898
|
+
:meth:`inequality_generator` instead to iterate over the
|
|
899
|
+
list of :class:`~sage.geometry.polyhedron.representation.Inequality` objects.
|
|
900
|
+
|
|
901
|
+
EXAMPLES::
|
|
902
|
+
|
|
903
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[0,0,1],[0,1,0],[1,0,0],[2,2,2]])
|
|
904
|
+
sage: p.inequalities_list()[0:3]
|
|
905
|
+
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
|
|
906
|
+
|
|
907
|
+
sage: # needs sage.combinat
|
|
908
|
+
sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4]))
|
|
909
|
+
sage: ieqs = p3.inequalities_list()
|
|
910
|
+
sage: ieqs[0]
|
|
911
|
+
[-6, 0, 1, 1, 1]
|
|
912
|
+
sage: ieqs[-1]
|
|
913
|
+
[-3, 0, 1, 0, 1]
|
|
914
|
+
sage: ieqs == [list(x) for x in p3.inequality_generator()]
|
|
915
|
+
True
|
|
916
|
+
"""
|
|
917
|
+
return [list(x) for x in self.inequality_generator()]
|
|
918
|
+
|
|
919
|
+
def equation_generator(self):
|
|
920
|
+
"""
|
|
921
|
+
Return a generator for the linear equations satisfied by the
|
|
922
|
+
polyhedron.
|
|
923
|
+
|
|
924
|
+
EXAMPLES::
|
|
925
|
+
|
|
926
|
+
sage: # needs cddexec
|
|
927
|
+
sage: p = polytopes.regular_polygon(8, base_ring=RDF)
|
|
928
|
+
sage: p3 = Polyhedron(vertices=[x+[0] for x in p.vertices()], base_ring=RDF)
|
|
929
|
+
sage: next(p3.equation_generator())
|
|
930
|
+
An equation (0.0, 0.0, 1.0) x + 0.0 == 0
|
|
931
|
+
"""
|
|
932
|
+
for H in self.Hrepresentation():
|
|
933
|
+
if H.is_equation():
|
|
934
|
+
yield H
|
|
935
|
+
|
|
936
|
+
@cached_method
|
|
937
|
+
def equations(self):
|
|
938
|
+
"""
|
|
939
|
+
Return all linear constraints of the polyhedron.
|
|
940
|
+
|
|
941
|
+
OUTPUT: a tuple of equations
|
|
942
|
+
|
|
943
|
+
EXAMPLES::
|
|
944
|
+
|
|
945
|
+
sage: test_p = Polyhedron(vertices = [[1,2,3,4],[2,1,3,4],[4,3,2,1],[3,4,1,2]])
|
|
946
|
+
sage: test_p.equations()
|
|
947
|
+
(An equation (1, 1, 1, 1) x - 10 == 0,)
|
|
948
|
+
"""
|
|
949
|
+
return tuple(self.equation_generator())
|
|
950
|
+
|
|
951
|
+
def equations_list(self):
|
|
952
|
+
"""
|
|
953
|
+
Return the linear constraints of the polyhedron. As with
|
|
954
|
+
inequalities, each constraint is given as [b -a1 -a2 ... an]
|
|
955
|
+
where for variables x1, x2,..., xn, the polyhedron satisfies
|
|
956
|
+
the equation b = a1*x1 + a2*x2 + ... + an*xn.
|
|
957
|
+
|
|
958
|
+
.. NOTE::
|
|
959
|
+
|
|
960
|
+
It is recommended to use :meth:`equations` or
|
|
961
|
+
:meth:`equation_generator()` instead to iterate over the
|
|
962
|
+
list of
|
|
963
|
+
:class:`~sage.geometry.polyhedron.representation.Equation`
|
|
964
|
+
objects.
|
|
965
|
+
|
|
966
|
+
EXAMPLES::
|
|
967
|
+
|
|
968
|
+
sage: test_p = Polyhedron(vertices = [[1,2,3,4],[2,1,3,4],[4,3,2,1],[3,4,1,2]])
|
|
969
|
+
sage: test_p.equations_list()
|
|
970
|
+
[[-10, 1, 1, 1, 1]]
|
|
971
|
+
"""
|
|
972
|
+
return [list(eq) for eq in self.equation_generator()]
|
|
973
|
+
|
|
974
|
+
def vertices_list(self):
|
|
975
|
+
"""
|
|
976
|
+
Return a list of vertices of the polyhedron.
|
|
977
|
+
|
|
978
|
+
.. NOTE::
|
|
979
|
+
|
|
980
|
+
It is recommended to use :meth:`vertex_generator` instead to
|
|
981
|
+
iterate over the list of :class:`~sage.geometry.polyhedron.representation.Vertex` objects.
|
|
982
|
+
|
|
983
|
+
.. WARNING::
|
|
984
|
+
|
|
985
|
+
If the polyhedron has lines, return the vertices
|
|
986
|
+
of the ``Vrepresentation``. However, the represented polyhedron
|
|
987
|
+
has no 0-dimensional faces (i.e. vertices)::
|
|
988
|
+
|
|
989
|
+
sage: P = Polyhedron(rays=[[1,0,0]],lines=[[0,1,0]])
|
|
990
|
+
sage: P.vertices_list()
|
|
991
|
+
[[0, 0, 0]]
|
|
992
|
+
sage: P.faces(0)
|
|
993
|
+
()
|
|
994
|
+
|
|
995
|
+
EXAMPLES::
|
|
996
|
+
|
|
997
|
+
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
|
|
998
|
+
sage: triangle.vertices_list()
|
|
999
|
+
[[0, 1], [1, 0], [1, 1]]
|
|
1000
|
+
sage: a_simplex = Polyhedron(ieqs = [
|
|
1001
|
+
....: [0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]
|
|
1002
|
+
....: ], eqns = [[1,-1,-1,-1,-1]])
|
|
1003
|
+
sage: a_simplex.vertices_list()
|
|
1004
|
+
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
|
|
1005
|
+
sage: a_simplex.vertices_list() == [list(v) for v in a_simplex.vertex_generator()]
|
|
1006
|
+
True
|
|
1007
|
+
"""
|
|
1008
|
+
return [list(x) for x in self.vertex_generator()]
|
|
1009
|
+
|
|
1010
|
+
def vertex_generator(self):
|
|
1011
|
+
"""
|
|
1012
|
+
Return a generator for the vertices of the polyhedron.
|
|
1013
|
+
|
|
1014
|
+
.. WARNING::
|
|
1015
|
+
|
|
1016
|
+
If the polyhedron has lines, return a generator for the vertices
|
|
1017
|
+
of the ``Vrepresentation``. However, the represented polyhedron
|
|
1018
|
+
has no 0-dimensional faces (i.e. vertices)::
|
|
1019
|
+
|
|
1020
|
+
sage: P = Polyhedron(rays=[[1,0,0]],lines=[[0,1,0]])
|
|
1021
|
+
sage: list(P.vertex_generator())
|
|
1022
|
+
[A vertex at (0, 0, 0)]
|
|
1023
|
+
sage: P.faces(0)
|
|
1024
|
+
()
|
|
1025
|
+
|
|
1026
|
+
EXAMPLES::
|
|
1027
|
+
|
|
1028
|
+
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
|
|
1029
|
+
sage: for v in triangle.vertex_generator(): print(v)
|
|
1030
|
+
A vertex at (0, 1)
|
|
1031
|
+
A vertex at (1, 0)
|
|
1032
|
+
A vertex at (1, 1)
|
|
1033
|
+
sage: v_gen = triangle.vertex_generator()
|
|
1034
|
+
sage: next(v_gen) # the first vertex
|
|
1035
|
+
A vertex at (0, 1)
|
|
1036
|
+
sage: next(v_gen) # the second vertex
|
|
1037
|
+
A vertex at (1, 0)
|
|
1038
|
+
sage: next(v_gen) # the third vertex
|
|
1039
|
+
A vertex at (1, 1)
|
|
1040
|
+
sage: try: next(v_gen) # there are only three vertices
|
|
1041
|
+
....: except StopIteration: print("STOP")
|
|
1042
|
+
STOP
|
|
1043
|
+
sage: type(v_gen)
|
|
1044
|
+
<... 'generator'>
|
|
1045
|
+
sage: [ v for v in triangle.vertex_generator() ]
|
|
1046
|
+
[A vertex at (0, 1), A vertex at (1, 0), A vertex at (1, 1)]
|
|
1047
|
+
"""
|
|
1048
|
+
for V in self.Vrepresentation():
|
|
1049
|
+
if V.is_vertex():
|
|
1050
|
+
yield V
|
|
1051
|
+
|
|
1052
|
+
@cached_method
|
|
1053
|
+
def vertices(self):
|
|
1054
|
+
"""
|
|
1055
|
+
Return all vertices of the polyhedron.
|
|
1056
|
+
|
|
1057
|
+
OUTPUT: a tuple of vertices
|
|
1058
|
+
|
|
1059
|
+
.. WARNING::
|
|
1060
|
+
|
|
1061
|
+
If the polyhedron has lines, return the vertices
|
|
1062
|
+
of the ``Vrepresentation``. However, the represented polyhedron
|
|
1063
|
+
has no 0-dimensional faces (i.e. vertices)::
|
|
1064
|
+
|
|
1065
|
+
sage: P = Polyhedron(rays=[[1,0,0]],lines=[[0,1,0]])
|
|
1066
|
+
sage: P.vertices()
|
|
1067
|
+
(A vertex at (0, 0, 0),)
|
|
1068
|
+
sage: P.faces(0)
|
|
1069
|
+
()
|
|
1070
|
+
|
|
1071
|
+
EXAMPLES::
|
|
1072
|
+
|
|
1073
|
+
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
|
|
1074
|
+
sage: triangle.vertices()
|
|
1075
|
+
(A vertex at (0, 1), A vertex at (1, 0), A vertex at (1, 1))
|
|
1076
|
+
sage: a_simplex = Polyhedron(ieqs = [
|
|
1077
|
+
....: [0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]
|
|
1078
|
+
....: ], eqns = [[1,-1,-1,-1,-1]])
|
|
1079
|
+
sage: a_simplex.vertices()
|
|
1080
|
+
(A vertex at (1, 0, 0, 0), A vertex at (0, 1, 0, 0),
|
|
1081
|
+
A vertex at (0, 0, 1, 0), A vertex at (0, 0, 0, 1))
|
|
1082
|
+
"""
|
|
1083
|
+
return tuple(self.vertex_generator())
|
|
1084
|
+
|
|
1085
|
+
@cached_method
|
|
1086
|
+
def vertices_matrix(self, base_ring=None):
|
|
1087
|
+
"""
|
|
1088
|
+
Return the coordinates of the vertices as the columns of a matrix.
|
|
1089
|
+
|
|
1090
|
+
INPUT:
|
|
1091
|
+
|
|
1092
|
+
- ``base_ring`` -- a ring or ``None`` (default); the base ring
|
|
1093
|
+
of the returned matrix. If not specified, the base ring of
|
|
1094
|
+
the polyhedron is used.
|
|
1095
|
+
|
|
1096
|
+
OUTPUT:
|
|
1097
|
+
|
|
1098
|
+
A matrix over ``base_ring`` whose columns are the coordinates
|
|
1099
|
+
of the vertices. A :exc:`TypeError` is raised if the coordinates
|
|
1100
|
+
cannot be converted to ``base_ring``.
|
|
1101
|
+
|
|
1102
|
+
.. WARNING::
|
|
1103
|
+
|
|
1104
|
+
If the polyhedron has lines, return the coordinates of the vertices
|
|
1105
|
+
of the ``Vrepresentation``. However, the represented polyhedron
|
|
1106
|
+
has no 0-dimensional faces (i.e. vertices)::
|
|
1107
|
+
|
|
1108
|
+
sage: P = Polyhedron(rays=[[1,0,0]],lines=[[0,1,0]])
|
|
1109
|
+
sage: P.vertices_matrix()
|
|
1110
|
+
[0]
|
|
1111
|
+
[0]
|
|
1112
|
+
[0]
|
|
1113
|
+
sage: P.faces(0)
|
|
1114
|
+
()
|
|
1115
|
+
|
|
1116
|
+
EXAMPLES::
|
|
1117
|
+
|
|
1118
|
+
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
|
|
1119
|
+
sage: triangle.vertices_matrix()
|
|
1120
|
+
[0 1 1]
|
|
1121
|
+
[1 0 1]
|
|
1122
|
+
sage: (triangle/2).vertices_matrix()
|
|
1123
|
+
[ 0 1/2 1/2]
|
|
1124
|
+
[1/2 0 1/2]
|
|
1125
|
+
sage: (triangle/2).vertices_matrix(ZZ)
|
|
1126
|
+
Traceback (most recent call last):
|
|
1127
|
+
...
|
|
1128
|
+
TypeError: no conversion of this rational to integer
|
|
1129
|
+
|
|
1130
|
+
TESTS:
|
|
1131
|
+
|
|
1132
|
+
Check that :issue:`28828` is fixed::
|
|
1133
|
+
|
|
1134
|
+
sage: P.vertices_matrix().is_immutable()
|
|
1135
|
+
True
|
|
1136
|
+
"""
|
|
1137
|
+
from sage.matrix.constructor import matrix
|
|
1138
|
+
|
|
1139
|
+
if base_ring is None:
|
|
1140
|
+
base_ring = self.base_ring()
|
|
1141
|
+
m = matrix(base_ring, self.ambient_dim(), self.n_vertices())
|
|
1142
|
+
for i, v in enumerate(self.vertices()):
|
|
1143
|
+
for j in range(self.ambient_dim()):
|
|
1144
|
+
m[j, i] = v[j]
|
|
1145
|
+
m.set_immutable()
|
|
1146
|
+
return m
|
|
1147
|
+
|
|
1148
|
+
def ray_generator(self):
|
|
1149
|
+
"""
|
|
1150
|
+
Return a generator for the rays of the polyhedron.
|
|
1151
|
+
|
|
1152
|
+
EXAMPLES::
|
|
1153
|
+
|
|
1154
|
+
sage: pi = Polyhedron(ieqs = [[1,1,0],[1,0,1]])
|
|
1155
|
+
sage: pir = pi.ray_generator()
|
|
1156
|
+
sage: [x.vector() for x in pir]
|
|
1157
|
+
[(1, 0), (0, 1)]
|
|
1158
|
+
"""
|
|
1159
|
+
for V in self.Vrepresentation():
|
|
1160
|
+
if V.is_ray():
|
|
1161
|
+
yield V
|
|
1162
|
+
|
|
1163
|
+
@cached_method
|
|
1164
|
+
def rays(self):
|
|
1165
|
+
"""
|
|
1166
|
+
Return a list of rays of the polyhedron.
|
|
1167
|
+
|
|
1168
|
+
OUTPUT: a tuple of rays
|
|
1169
|
+
|
|
1170
|
+
EXAMPLES::
|
|
1171
|
+
|
|
1172
|
+
sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0],[1,1,0,0]])
|
|
1173
|
+
sage: p.rays()
|
|
1174
|
+
(A ray in the direction (1, 0, 0),
|
|
1175
|
+
A ray in the direction (0, 1, 0),
|
|
1176
|
+
A ray in the direction (0, 0, 1))
|
|
1177
|
+
"""
|
|
1178
|
+
return tuple(self.ray_generator())
|
|
1179
|
+
|
|
1180
|
+
def rays_list(self):
|
|
1181
|
+
"""
|
|
1182
|
+
Return a list of rays as coefficient lists.
|
|
1183
|
+
|
|
1184
|
+
.. NOTE::
|
|
1185
|
+
|
|
1186
|
+
It is recommended to use :meth:`rays` or
|
|
1187
|
+
:meth:`ray_generator` instead to iterate over the list of
|
|
1188
|
+
:class:`~sage.geometry.polyhedron.representation.Ray` objects.
|
|
1189
|
+
|
|
1190
|
+
OUTPUT: list of rays as lists of coordinates
|
|
1191
|
+
|
|
1192
|
+
EXAMPLES::
|
|
1193
|
+
|
|
1194
|
+
sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0],[1,1,0,0]])
|
|
1195
|
+
sage: p.rays_list()
|
|
1196
|
+
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
|
|
1197
|
+
sage: p.rays_list() == [list(r) for r in p.ray_generator()]
|
|
1198
|
+
True
|
|
1199
|
+
"""
|
|
1200
|
+
return [list(x) for x in self.ray_generator()]
|
|
1201
|
+
|
|
1202
|
+
def line_generator(self):
|
|
1203
|
+
"""
|
|
1204
|
+
Return a generator for the lines of the polyhedron.
|
|
1205
|
+
|
|
1206
|
+
EXAMPLES::
|
|
1207
|
+
|
|
1208
|
+
sage: pr = Polyhedron(rays = [[1,0],[-1,0],[0,1]], vertices = [[-1,-1]])
|
|
1209
|
+
sage: next(pr.line_generator()).vector()
|
|
1210
|
+
(1, 0)
|
|
1211
|
+
"""
|
|
1212
|
+
for V in self.Vrepresentation():
|
|
1213
|
+
if V.is_line():
|
|
1214
|
+
yield V
|
|
1215
|
+
|
|
1216
|
+
@cached_method
|
|
1217
|
+
def lines(self):
|
|
1218
|
+
"""
|
|
1219
|
+
Return all lines of the polyhedron.
|
|
1220
|
+
|
|
1221
|
+
OUTPUT: a tuple of lines
|
|
1222
|
+
|
|
1223
|
+
EXAMPLES::
|
|
1224
|
+
|
|
1225
|
+
sage: p = Polyhedron(rays = [[1,0],[-1,0],[0,1],[1,1]], vertices = [[-2,-2],[2,3]])
|
|
1226
|
+
sage: p.lines()
|
|
1227
|
+
(A line in the direction (1, 0),)
|
|
1228
|
+
"""
|
|
1229
|
+
return tuple(self.line_generator())
|
|
1230
|
+
|
|
1231
|
+
def lines_list(self):
|
|
1232
|
+
"""
|
|
1233
|
+
Return a list of lines of the polyhedron. The line data is given
|
|
1234
|
+
as a list of coordinates rather than as a Hrepresentation object.
|
|
1235
|
+
|
|
1236
|
+
.. NOTE::
|
|
1237
|
+
|
|
1238
|
+
It is recommended to use :meth:`line_generator` instead to
|
|
1239
|
+
iterate over the list of :class:`~sage.geometry.polyhedron.representation.Line` objects.
|
|
1240
|
+
|
|
1241
|
+
EXAMPLES::
|
|
1242
|
+
|
|
1243
|
+
sage: p = Polyhedron(rays = [[1,0],[-1,0],[0,1],[1,1]], vertices = [[-2,-2],[2,3]])
|
|
1244
|
+
sage: p.lines_list()
|
|
1245
|
+
[[1, 0]]
|
|
1246
|
+
sage: p.lines_list() == [list(x) for x in p.line_generator()]
|
|
1247
|
+
True
|
|
1248
|
+
"""
|
|
1249
|
+
return [list(x) for x in self.line_generator()]
|
|
1250
|
+
|
|
1251
|
+
def base_ring(self):
|
|
1252
|
+
"""
|
|
1253
|
+
Return the base ring.
|
|
1254
|
+
|
|
1255
|
+
OUTPUT:
|
|
1256
|
+
|
|
1257
|
+
The ring over which the polyhedron is defined. Must be a
|
|
1258
|
+
sub-ring of the reals to define a polyhedron, in particular
|
|
1259
|
+
comparison must be defined. Popular choices are
|
|
1260
|
+
|
|
1261
|
+
* ``ZZ`` (the ring of integers, lattice polytope),
|
|
1262
|
+
|
|
1263
|
+
* ``QQ`` (exact arithmetic using gmp),
|
|
1264
|
+
|
|
1265
|
+
* ``RDF`` (double precision floating-point arithmetic), or
|
|
1266
|
+
|
|
1267
|
+
* ``AA`` (real algebraic field).
|
|
1268
|
+
|
|
1269
|
+
EXAMPLES::
|
|
1270
|
+
|
|
1271
|
+
sage: triangle = Polyhedron(vertices = [[1,0],[0,1],[1,1]])
|
|
1272
|
+
sage: triangle.base_ring() == ZZ
|
|
1273
|
+
True
|
|
1274
|
+
"""
|
|
1275
|
+
return self.parent().base_ring()
|
|
1276
|
+
|
|
1277
|
+
def backend(self):
|
|
1278
|
+
"""
|
|
1279
|
+
Return the backend used.
|
|
1280
|
+
|
|
1281
|
+
OUTPUT:
|
|
1282
|
+
|
|
1283
|
+
The name of the backend used for computations. It will be one of
|
|
1284
|
+
the following backends:
|
|
1285
|
+
|
|
1286
|
+
* ``ppl`` the Parma Polyhedra Library
|
|
1287
|
+
|
|
1288
|
+
* ``cdd`` CDD
|
|
1289
|
+
|
|
1290
|
+
* ``normaliz`` normaliz
|
|
1291
|
+
|
|
1292
|
+
* ``polymake`` polymake
|
|
1293
|
+
|
|
1294
|
+
* ``field`` a generic Sage implementation
|
|
1295
|
+
|
|
1296
|
+
EXAMPLES::
|
|
1297
|
+
|
|
1298
|
+
sage: triangle = Polyhedron(vertices=[[1, 0], [0, 1], [1, 1]])
|
|
1299
|
+
sage: triangle.backend()
|
|
1300
|
+
'ppl'
|
|
1301
|
+
sage: D = polytopes.dodecahedron() # needs sage.groups sage.rings.number_field
|
|
1302
|
+
sage: D.backend() # needs sage.groups sage.rings.number_field
|
|
1303
|
+
'field'
|
|
1304
|
+
sage: P = Polyhedron([[1.23]]) # needs cddexec
|
|
1305
|
+
sage: P.backend() # needs cddexec
|
|
1306
|
+
'cdd'
|
|
1307
|
+
"""
|
|
1308
|
+
return self.parent().backend()
|
|
1309
|
+
|
|
1310
|
+
def cdd_Hrepresentation(self):
|
|
1311
|
+
r"""
|
|
1312
|
+
Write the inequalities/equations data of the polyhedron in
|
|
1313
|
+
cdd's H-representation format.
|
|
1314
|
+
|
|
1315
|
+
.. SEEALSO::
|
|
1316
|
+
|
|
1317
|
+
:meth:`write_cdd_Hrepresentation` -- export the polyhedron as a
|
|
1318
|
+
H-representation to a file.
|
|
1319
|
+
|
|
1320
|
+
OUTPUT: string
|
|
1321
|
+
|
|
1322
|
+
EXAMPLES::
|
|
1323
|
+
|
|
1324
|
+
sage: p = polytopes.hypercube(2)
|
|
1325
|
+
sage: print(p.cdd_Hrepresentation())
|
|
1326
|
+
H-representation
|
|
1327
|
+
begin
|
|
1328
|
+
4 3 rational
|
|
1329
|
+
1 -1 0
|
|
1330
|
+
1 0 -1
|
|
1331
|
+
1 1 0
|
|
1332
|
+
1 0 1
|
|
1333
|
+
end
|
|
1334
|
+
<BLANKLINE>
|
|
1335
|
+
|
|
1336
|
+
sage: triangle = Polyhedron(vertices=[[1,0], [0,1], [1,1]], base_ring=AA) # needs sage.rings.number_field
|
|
1337
|
+
sage: triangle.base_ring() # needs sage.rings.number_field
|
|
1338
|
+
Algebraic Real Field
|
|
1339
|
+
sage: triangle.cdd_Hrepresentation() # needs sage.rings.number_field
|
|
1340
|
+
Traceback (most recent call last):
|
|
1341
|
+
...
|
|
1342
|
+
TypeError: the base ring must be ZZ, QQ, or RDF
|
|
1343
|
+
"""
|
|
1344
|
+
from .cdd_file_format import cdd_Hrepresentation
|
|
1345
|
+
try:
|
|
1346
|
+
cdd_type = self._cdd_type
|
|
1347
|
+
except AttributeError:
|
|
1348
|
+
from sage.rings.integer_ring import ZZ
|
|
1349
|
+
from sage.rings.rational_field import QQ
|
|
1350
|
+
if self.base_ring() is ZZ or self.base_ring() is QQ:
|
|
1351
|
+
cdd_type = 'rational'
|
|
1352
|
+
elif isinstance(self.base_ring(), sage.rings.abc.RealDoubleField):
|
|
1353
|
+
cdd_type = 'real'
|
|
1354
|
+
else:
|
|
1355
|
+
raise TypeError('the base ring must be ZZ, QQ, or RDF')
|
|
1356
|
+
return cdd_Hrepresentation(cdd_type,
|
|
1357
|
+
list(self.inequality_generator()),
|
|
1358
|
+
list(self.equation_generator()))
|
|
1359
|
+
|
|
1360
|
+
def write_cdd_Hrepresentation(self, filename):
|
|
1361
|
+
r"""
|
|
1362
|
+
Export the polyhedron as a H-representation to a file.
|
|
1363
|
+
|
|
1364
|
+
INPUT:
|
|
1365
|
+
|
|
1366
|
+
- ``filename`` -- the output file
|
|
1367
|
+
|
|
1368
|
+
.. SEEALSO::
|
|
1369
|
+
|
|
1370
|
+
:meth:`cdd_Hrepresentation` -- return the H-representation of the
|
|
1371
|
+
polyhedron as a string.
|
|
1372
|
+
|
|
1373
|
+
EXAMPLES::
|
|
1374
|
+
|
|
1375
|
+
sage: from sage.misc.temporary_file import tmp_filename
|
|
1376
|
+
sage: filename = tmp_filename(ext='.ext')
|
|
1377
|
+
sage: polytopes.cube().write_cdd_Hrepresentation(filename)
|
|
1378
|
+
"""
|
|
1379
|
+
with open(filename, 'w') as f:
|
|
1380
|
+
f.write(self.cdd_Hrepresentation())
|
|
1381
|
+
|
|
1382
|
+
def cdd_Vrepresentation(self):
|
|
1383
|
+
r"""
|
|
1384
|
+
Write the vertices/rays/lines data of the polyhedron in cdd's
|
|
1385
|
+
V-representation format.
|
|
1386
|
+
|
|
1387
|
+
.. SEEALSO::
|
|
1388
|
+
|
|
1389
|
+
:meth:`write_cdd_Vrepresentation` -- export the polyhedron as a
|
|
1390
|
+
V-representation to a file.
|
|
1391
|
+
|
|
1392
|
+
OUTPUT: string
|
|
1393
|
+
|
|
1394
|
+
EXAMPLES::
|
|
1395
|
+
|
|
1396
|
+
sage: q = Polyhedron(vertices = [[1,1],[0,0],[1,0],[0,1]])
|
|
1397
|
+
sage: print(q.cdd_Vrepresentation())
|
|
1398
|
+
V-representation
|
|
1399
|
+
begin
|
|
1400
|
+
4 3 rational
|
|
1401
|
+
1 0 0
|
|
1402
|
+
1 0 1
|
|
1403
|
+
1 1 0
|
|
1404
|
+
1 1 1
|
|
1405
|
+
end
|
|
1406
|
+
"""
|
|
1407
|
+
from .cdd_file_format import cdd_Vrepresentation
|
|
1408
|
+
try:
|
|
1409
|
+
cdd_type = self._cdd_type
|
|
1410
|
+
except AttributeError:
|
|
1411
|
+
from sage.rings.integer_ring import ZZ
|
|
1412
|
+
from sage.rings.rational_field import QQ
|
|
1413
|
+
if self.base_ring() is ZZ or self.base_ring() is QQ:
|
|
1414
|
+
cdd_type = 'rational'
|
|
1415
|
+
elif isinstance(self.base_ring(), sage.rings.abc.RealDoubleField):
|
|
1416
|
+
cdd_type = 'real'
|
|
1417
|
+
else:
|
|
1418
|
+
raise TypeError('the base ring must be ZZ, QQ, or RDF')
|
|
1419
|
+
return cdd_Vrepresentation(cdd_type,
|
|
1420
|
+
list(self.vertex_generator()),
|
|
1421
|
+
list(self.ray_generator()),
|
|
1422
|
+
list(self.line_generator()))
|
|
1423
|
+
|
|
1424
|
+
def write_cdd_Vrepresentation(self, filename):
|
|
1425
|
+
r"""
|
|
1426
|
+
Export the polyhedron as a V-representation to a file.
|
|
1427
|
+
|
|
1428
|
+
INPUT:
|
|
1429
|
+
|
|
1430
|
+
- ``filename`` -- the output file
|
|
1431
|
+
|
|
1432
|
+
.. SEEALSO::
|
|
1433
|
+
|
|
1434
|
+
:meth:`cdd_Vrepresentation` -- return the V-representation of the
|
|
1435
|
+
polyhedron as a string.
|
|
1436
|
+
|
|
1437
|
+
EXAMPLES::
|
|
1438
|
+
|
|
1439
|
+
sage: from sage.misc.temporary_file import tmp_filename
|
|
1440
|
+
sage: filename = tmp_filename(ext='.ext')
|
|
1441
|
+
sage: polytopes.cube().write_cdd_Vrepresentation(filename)
|
|
1442
|
+
"""
|
|
1443
|
+
with open(filename, 'w') as f:
|
|
1444
|
+
f.write(self.cdd_Vrepresentation())
|