passagemath-polyhedra 10.6.31rc3__cp314-cp314-musllinux_1_2_aarch64.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 +208 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_polyhedra.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-1ede7ee7.so.1.0.0 +0 -0
- passagemath_polyhedra.libs/libstdc++-85f2cd6d.so.6.0.33 +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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-aarch64-linux-musl.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-aarch64-linux-musl.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-aarch64-linux-musl.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,1279 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
r"""
|
|
3
|
+
Parents for Polyhedra
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# ****************************************************************************
|
|
7
|
+
# Copyright (C) 2014 Volker Braun <vbraun.name@gmail.com>
|
|
8
|
+
#
|
|
9
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
10
|
+
# https://www.gnu.org/licenses/
|
|
11
|
+
# *****************************************************************************
|
|
12
|
+
|
|
13
|
+
import sage.geometry.abc
|
|
14
|
+
|
|
15
|
+
from sage.structure.parent import Parent
|
|
16
|
+
from sage.structure.element import get_coercion_model
|
|
17
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
18
|
+
from sage.modules.free_module import FreeModule, FreeModule_generic
|
|
19
|
+
from sage.misc.cachefunc import cached_method, cached_function
|
|
20
|
+
from sage.misc.lazy_import import lazy_import
|
|
21
|
+
import sage.rings.abc
|
|
22
|
+
from sage.rings.integer_ring import ZZ
|
|
23
|
+
from sage.rings.rational_field import QQ
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
from sage.rings.real_double import RDF
|
|
27
|
+
except ImportError:
|
|
28
|
+
RDF = None
|
|
29
|
+
|
|
30
|
+
from sage.categories.fields import Fields
|
|
31
|
+
from sage.categories.rings import Rings
|
|
32
|
+
from sage.categories.modules import Modules
|
|
33
|
+
from .representation import Inequality, Equation, Vertex, Ray, Line
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, *,
|
|
37
|
+
ambient_space=None, base_ring=None):
|
|
38
|
+
r"""
|
|
39
|
+
Construct a suitable parent class for polyhedra.
|
|
40
|
+
|
|
41
|
+
INPUT:
|
|
42
|
+
|
|
43
|
+
- ``base_ring`` -- a ring; currently there are backends for `\ZZ`,
|
|
44
|
+
`\QQ`, and `\RDF`
|
|
45
|
+
|
|
46
|
+
- ``ambient_dim`` -- integer; the ambient space dimension
|
|
47
|
+
|
|
48
|
+
- ``ambient_space`` -- a free module
|
|
49
|
+
|
|
50
|
+
- ``backend`` -- string. The name of the backend for computations. There are
|
|
51
|
+
several backends implemented:
|
|
52
|
+
|
|
53
|
+
* ``backend="ppl"`` uses the Parma Polyhedra Library
|
|
54
|
+
|
|
55
|
+
* ``backend="cdd"`` uses CDD
|
|
56
|
+
|
|
57
|
+
* ``backend="normaliz"`` uses normaliz
|
|
58
|
+
|
|
59
|
+
* ``backend="polymake"`` uses polymake
|
|
60
|
+
|
|
61
|
+
* ``backend="field"`` a generic Sage implementation
|
|
62
|
+
|
|
63
|
+
OUTPUT:
|
|
64
|
+
|
|
65
|
+
A parent class for polyhedra over the given base ring if the
|
|
66
|
+
backend supports it. If not, the parent base ring can be larger
|
|
67
|
+
(for example, `\QQ` instead of `\ZZ`). If there is no
|
|
68
|
+
implementation at all, a :exc:`ValueError` is raised.
|
|
69
|
+
|
|
70
|
+
EXAMPLES::
|
|
71
|
+
|
|
72
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
73
|
+
sage: Polyhedra(AA, 3) # needs sage.rings.number_field
|
|
74
|
+
Polyhedra in AA^3
|
|
75
|
+
sage: Polyhedra(ZZ, 3)
|
|
76
|
+
Polyhedra in ZZ^3
|
|
77
|
+
sage: type(_)
|
|
78
|
+
<class 'sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category'>
|
|
79
|
+
sage: Polyhedra(QQ, 3, backend='cdd')
|
|
80
|
+
Polyhedra in QQ^3
|
|
81
|
+
sage: type(_)
|
|
82
|
+
<class 'sage.geometry.polyhedron.parent.Polyhedra_QQ_cdd_with_category'>
|
|
83
|
+
|
|
84
|
+
CDD does not support integer polytopes directly::
|
|
85
|
+
|
|
86
|
+
sage: Polyhedra(ZZ, 3, backend='cdd')
|
|
87
|
+
Polyhedra in QQ^3
|
|
88
|
+
|
|
89
|
+
Using a more general form of the constructor::
|
|
90
|
+
|
|
91
|
+
sage: V = VectorSpace(QQ, 3)
|
|
92
|
+
sage: Polyhedra(V) is Polyhedra(QQ, 3)
|
|
93
|
+
True
|
|
94
|
+
sage: Polyhedra(V, backend='field') is Polyhedra(QQ, 3, 'field')
|
|
95
|
+
True
|
|
96
|
+
sage: Polyhedra(backend='field', ambient_space=V) is Polyhedra(QQ, 3, 'field')
|
|
97
|
+
True
|
|
98
|
+
|
|
99
|
+
sage: M = FreeModule(ZZ, 2)
|
|
100
|
+
sage: Polyhedra(M, backend='ppl') is Polyhedra(ZZ, 2, 'ppl')
|
|
101
|
+
True
|
|
102
|
+
|
|
103
|
+
TESTS::
|
|
104
|
+
|
|
105
|
+
sage: Polyhedra(RR, 3, backend='field') # needs sage.rings.real_mpfr
|
|
106
|
+
Traceback (most recent call last):
|
|
107
|
+
...
|
|
108
|
+
ValueError: the 'field' backend for polyhedron cannot be used with non-exact fields
|
|
109
|
+
sage: Polyhedra(RR, 3) # needs sage.rings.real_mpfr
|
|
110
|
+
Traceback (most recent call last):
|
|
111
|
+
...
|
|
112
|
+
ValueError: no default backend for computations with Real Field with 53 bits of precision
|
|
113
|
+
sage: Polyhedra(QQ[I], 2) # needs sage.rings.number_field
|
|
114
|
+
Traceback (most recent call last):
|
|
115
|
+
...
|
|
116
|
+
ValueError: invalid base ring: Number Field in I
|
|
117
|
+
with defining polynomial x^2 + 1 with I = 1*I
|
|
118
|
+
cannot be coerced to a real field
|
|
119
|
+
sage: Polyhedra(AA, 3, backend='polymake') # optional - jupymake # needs sage.rings.number_field
|
|
120
|
+
Traceback (most recent call last):
|
|
121
|
+
...
|
|
122
|
+
ValueError: the 'polymake' backend for polyhedron cannot be used with Algebraic Real Field
|
|
123
|
+
|
|
124
|
+
sage: Polyhedra(QQ, 2, backend='normaliz')
|
|
125
|
+
Polyhedra in QQ^2
|
|
126
|
+
sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz # needs sage.symbolic
|
|
127
|
+
Polyhedra in (Symbolic Ring)^2
|
|
128
|
+
sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic
|
|
129
|
+
sage: Polyhedra(SCR, 2, backend='normaliz') # optional - pynormaliz # needs sage.symbolic
|
|
130
|
+
Polyhedra in (Symbolic Constants Subring)^2
|
|
131
|
+
|
|
132
|
+
sage: Polyhedra(SCR, 2, backend='number_field') # needs sage.symbolic
|
|
133
|
+
Polyhedra in (Symbolic Constants Subring)^2
|
|
134
|
+
"""
|
|
135
|
+
if ambient_space_or_base_ring is not None:
|
|
136
|
+
if ambient_space_or_base_ring in Rings():
|
|
137
|
+
base_ring = ambient_space_or_base_ring
|
|
138
|
+
else:
|
|
139
|
+
ambient_space = ambient_space_or_base_ring
|
|
140
|
+
if ambient_space is not None:
|
|
141
|
+
if ambient_space not in Modules:
|
|
142
|
+
# There is no category of free modules, unfortunately
|
|
143
|
+
# (see https://github.com/sagemath/sage/issues/30164)...
|
|
144
|
+
raise ValueError('ambient_space must be a free module')
|
|
145
|
+
if base_ring is None:
|
|
146
|
+
base_ring = ambient_space.base_ring()
|
|
147
|
+
if ambient_dim is None:
|
|
148
|
+
try:
|
|
149
|
+
ambient_dim = ambient_space.rank()
|
|
150
|
+
except AttributeError:
|
|
151
|
+
# ... so we test whether it is free using the existence of
|
|
152
|
+
# a rank method
|
|
153
|
+
raise ValueError('ambient_space must be a free module')
|
|
154
|
+
if ambient_space is not FreeModule(base_ring, ambient_dim):
|
|
155
|
+
raise NotImplementedError('ambient_space must be a standard free module')
|
|
156
|
+
if backend is None:
|
|
157
|
+
if base_ring is ZZ or base_ring is QQ:
|
|
158
|
+
backend = 'ppl'
|
|
159
|
+
elif base_ring is RDF:
|
|
160
|
+
backend = 'cdd'
|
|
161
|
+
elif base_ring.is_exact():
|
|
162
|
+
# TODO: find a more robust way of checking that the coefficients are indeed
|
|
163
|
+
# real numbers
|
|
164
|
+
if not RDF.has_coerce_map_from(base_ring):
|
|
165
|
+
raise ValueError("invalid base ring: {} cannot be coerced to a real field".format(base_ring))
|
|
166
|
+
backend = 'field'
|
|
167
|
+
else:
|
|
168
|
+
raise ValueError("no default backend for computations with {}".format(base_ring))
|
|
169
|
+
|
|
170
|
+
if backend == 'ppl' and base_ring is QQ:
|
|
171
|
+
return Polyhedra_QQ_ppl(base_ring, ambient_dim, backend)
|
|
172
|
+
elif backend == 'ppl' and base_ring is ZZ:
|
|
173
|
+
return Polyhedra_ZZ_ppl(base_ring, ambient_dim, backend)
|
|
174
|
+
elif backend == 'normaliz' and base_ring is QQ:
|
|
175
|
+
return Polyhedra_QQ_normaliz(base_ring, ambient_dim, backend)
|
|
176
|
+
elif backend == 'normaliz' and base_ring is ZZ:
|
|
177
|
+
return Polyhedra_ZZ_normaliz(base_ring, ambient_dim, backend)
|
|
178
|
+
elif backend == 'normaliz' and (isinstance(base_ring, sage.rings.abc.SymbolicRing) or base_ring.is_exact()):
|
|
179
|
+
return Polyhedra_normaliz(base_ring, ambient_dim, backend)
|
|
180
|
+
elif backend == 'cdd' and base_ring in (ZZ, QQ):
|
|
181
|
+
return Polyhedra_QQ_cdd(QQ, ambient_dim, backend)
|
|
182
|
+
elif backend == 'cdd' and base_ring is RDF:
|
|
183
|
+
return Polyhedra_RDF_cdd(RDF, ambient_dim, backend)
|
|
184
|
+
elif backend == 'polymake':
|
|
185
|
+
base_field = base_ring.fraction_field()
|
|
186
|
+
try:
|
|
187
|
+
from sage.interfaces.polymake import polymake, PolymakeElement
|
|
188
|
+
polymake_base_field = polymake(base_field)
|
|
189
|
+
assert isinstance(polymake_base_field, PolymakeElement) # to muffle pyflakes
|
|
190
|
+
except TypeError:
|
|
191
|
+
raise ValueError(f"the 'polymake' backend for polyhedron cannot be used with {base_field}")
|
|
192
|
+
return Polyhedra_polymake(base_field, ambient_dim, backend)
|
|
193
|
+
elif backend == 'number_field':
|
|
194
|
+
return Polyhedra_number_field(base_ring.fraction_field(), ambient_dim, backend)
|
|
195
|
+
elif backend == 'field':
|
|
196
|
+
if not base_ring.is_exact():
|
|
197
|
+
raise ValueError("the 'field' backend for polyhedron cannot be used with non-exact fields")
|
|
198
|
+
return Polyhedra_field(base_ring.fraction_field(), ambient_dim, backend)
|
|
199
|
+
else:
|
|
200
|
+
raise ValueError('No such backend (=' + str(backend) +
|
|
201
|
+
') implemented for given basering (=' + str(base_ring) + ').')
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class Polyhedra_base(UniqueRepresentation, Parent):
|
|
205
|
+
r"""
|
|
206
|
+
Polyhedra in a fixed ambient space.
|
|
207
|
+
|
|
208
|
+
INPUT:
|
|
209
|
+
|
|
210
|
+
- ``base_ring`` -- either ``ZZ``, ``QQ``, or ``RDF``; the base
|
|
211
|
+
ring of the ambient module/vector space
|
|
212
|
+
|
|
213
|
+
- ``ambient_dim`` -- integer; the ambient space dimension
|
|
214
|
+
|
|
215
|
+
- ``backend`` -- string; the name of the backend for computations. There are
|
|
216
|
+
several backends implemented:
|
|
217
|
+
|
|
218
|
+
* ``backend="ppl"`` uses the Parma Polyhedra Library
|
|
219
|
+
|
|
220
|
+
* ``backend="cdd"`` uses CDD
|
|
221
|
+
|
|
222
|
+
* ``backend="normaliz"`` uses normaliz
|
|
223
|
+
|
|
224
|
+
* ``backend="polymake"`` uses polymake
|
|
225
|
+
|
|
226
|
+
* ``backend="field"`` a generic Sage implementation
|
|
227
|
+
|
|
228
|
+
EXAMPLES::
|
|
229
|
+
|
|
230
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
231
|
+
sage: Polyhedra(ZZ, 3)
|
|
232
|
+
Polyhedra in ZZ^3
|
|
233
|
+
"""
|
|
234
|
+
def __init__(self, base_ring, ambient_dim, backend):
|
|
235
|
+
"""
|
|
236
|
+
The Python constructor.
|
|
237
|
+
|
|
238
|
+
EXAMPLES::
|
|
239
|
+
|
|
240
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
241
|
+
sage: Polyhedra(QQ, 3)
|
|
242
|
+
Polyhedra in QQ^3
|
|
243
|
+
|
|
244
|
+
TESTS::
|
|
245
|
+
|
|
246
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
247
|
+
sage: P = Polyhedra(QQ, 3)
|
|
248
|
+
sage: TestSuite(P).run()
|
|
249
|
+
sage: P = Polyhedra(QQ, 0)
|
|
250
|
+
sage: TestSuite(P).run()
|
|
251
|
+
"""
|
|
252
|
+
self._backend = backend
|
|
253
|
+
self._ambient_dim = ambient_dim
|
|
254
|
+
from sage.categories.polyhedra import PolyhedralSets
|
|
255
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
256
|
+
category = PolyhedralSets(base_ring)
|
|
257
|
+
if ambient_dim == 0:
|
|
258
|
+
category = category & FiniteEnumeratedSets()
|
|
259
|
+
else:
|
|
260
|
+
category = category.Infinite()
|
|
261
|
+
|
|
262
|
+
Parent.__init__(self, base=base_ring, category=category)
|
|
263
|
+
self._Inequality_pool = []
|
|
264
|
+
self._Equation_pool = []
|
|
265
|
+
self._Vertex_pool = []
|
|
266
|
+
self._Ray_pool = []
|
|
267
|
+
self._Line_pool = []
|
|
268
|
+
|
|
269
|
+
def list(self):
|
|
270
|
+
"""
|
|
271
|
+
Return the two polyhedra in ambient dimension 0, raise an error otherwise.
|
|
272
|
+
|
|
273
|
+
EXAMPLES::
|
|
274
|
+
|
|
275
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
276
|
+
sage: P = Polyhedra(QQ, 3)
|
|
277
|
+
sage: P.cardinality()
|
|
278
|
+
+Infinity
|
|
279
|
+
|
|
280
|
+
sage: # needs sage.rings.number_field
|
|
281
|
+
sage: P = Polyhedra(AA, 0)
|
|
282
|
+
sage: P.category()
|
|
283
|
+
Category of finite enumerated polyhedral sets over Algebraic Real Field
|
|
284
|
+
sage: P.list()
|
|
285
|
+
[The empty polyhedron in AA^0,
|
|
286
|
+
A 0-dimensional polyhedron in AA^0 defined as the convex hull of 1 vertex]
|
|
287
|
+
sage: P.cardinality()
|
|
288
|
+
2
|
|
289
|
+
"""
|
|
290
|
+
if self.ambient_dim():
|
|
291
|
+
raise NotImplementedError
|
|
292
|
+
return [self.empty(), self.universe()]
|
|
293
|
+
|
|
294
|
+
def recycle(self, polyhedron):
|
|
295
|
+
"""
|
|
296
|
+
Recycle the H/V-representation objects of a polyhedron.
|
|
297
|
+
|
|
298
|
+
This speeds up creation of new polyhedra by reusing
|
|
299
|
+
objects. After recycling a polyhedron object, it is not in a
|
|
300
|
+
consistent state any more and neither the polyhedron nor its
|
|
301
|
+
H/V-representation objects may be used any more.
|
|
302
|
+
|
|
303
|
+
INPUT:
|
|
304
|
+
|
|
305
|
+
- ``polyhedron`` -- a polyhedron whose parent is ``self``
|
|
306
|
+
|
|
307
|
+
EXAMPLES::
|
|
308
|
+
|
|
309
|
+
sage: p = Polyhedron([(0,0),(1,0),(0,1)])
|
|
310
|
+
sage: p.parent().recycle(p)
|
|
311
|
+
|
|
312
|
+
TESTS::
|
|
313
|
+
|
|
314
|
+
sage: p = Polyhedron([(0,0),(1,0),(0,1)])
|
|
315
|
+
sage: n = len(p.parent()._Vertex_pool)
|
|
316
|
+
sage: p._delete()
|
|
317
|
+
sage: len(p.parent()._Vertex_pool) - n
|
|
318
|
+
3
|
|
319
|
+
"""
|
|
320
|
+
if self is not polyhedron.parent():
|
|
321
|
+
raise TypeError('The polyhedron has the wrong parent class.')
|
|
322
|
+
self._Inequality_pool.extend(polyhedron.inequalities())
|
|
323
|
+
self._Equation_pool.extend(polyhedron.equations())
|
|
324
|
+
self._Vertex_pool.extend(polyhedron.vertices())
|
|
325
|
+
self._Ray_pool.extend(polyhedron.rays())
|
|
326
|
+
self._Line_pool.extend(polyhedron.lines())
|
|
327
|
+
for Hrep in polyhedron.Hrep_generator():
|
|
328
|
+
Hrep._polyhedron = None
|
|
329
|
+
for Vrep in polyhedron.Vrep_generator():
|
|
330
|
+
Vrep._polyhedron = None
|
|
331
|
+
polyhedron._Hrepresentation = None
|
|
332
|
+
polyhedron._Vrepresentation = None
|
|
333
|
+
if polyhedron.is_mutable():
|
|
334
|
+
polyhedron._dependent_objects = []
|
|
335
|
+
|
|
336
|
+
def ambient_dim(self):
|
|
337
|
+
r"""
|
|
338
|
+
Return the dimension of the ambient space.
|
|
339
|
+
|
|
340
|
+
EXAMPLES::
|
|
341
|
+
|
|
342
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
343
|
+
sage: Polyhedra(QQ, 3).ambient_dim()
|
|
344
|
+
3
|
|
345
|
+
"""
|
|
346
|
+
return self._ambient_dim
|
|
347
|
+
|
|
348
|
+
def backend(self):
|
|
349
|
+
r"""
|
|
350
|
+
Return the backend.
|
|
351
|
+
|
|
352
|
+
EXAMPLES::
|
|
353
|
+
|
|
354
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
355
|
+
sage: Polyhedra(QQ, 3).backend()
|
|
356
|
+
'ppl'
|
|
357
|
+
"""
|
|
358
|
+
return self._backend
|
|
359
|
+
|
|
360
|
+
@cached_method
|
|
361
|
+
def an_element(self):
|
|
362
|
+
r"""
|
|
363
|
+
Return a Polyhedron.
|
|
364
|
+
|
|
365
|
+
EXAMPLES::
|
|
366
|
+
|
|
367
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
368
|
+
sage: Polyhedra(QQ, 4).an_element()
|
|
369
|
+
A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices
|
|
370
|
+
"""
|
|
371
|
+
zero = self.base_ring().zero()
|
|
372
|
+
one = self.base_ring().one()
|
|
373
|
+
p = [zero] * self.ambient_dim()
|
|
374
|
+
points = [p]
|
|
375
|
+
for i in range(self.ambient_dim()):
|
|
376
|
+
p = [zero] * self.ambient_dim()
|
|
377
|
+
p[i] = one
|
|
378
|
+
points.append(p)
|
|
379
|
+
return self.element_class(self, [points, [], []], None)
|
|
380
|
+
|
|
381
|
+
@cached_method
|
|
382
|
+
def some_elements(self):
|
|
383
|
+
r"""
|
|
384
|
+
Return a list of some elements of the semigroup.
|
|
385
|
+
|
|
386
|
+
EXAMPLES::
|
|
387
|
+
|
|
388
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
389
|
+
sage: Polyhedra(QQ, 4).some_elements()
|
|
390
|
+
[A 3-dimensional polyhedron in QQ^4
|
|
391
|
+
defined as the convex hull of 4 vertices,
|
|
392
|
+
A 4-dimensional polyhedron in QQ^4
|
|
393
|
+
defined as the convex hull of 1 vertex and 4 rays,
|
|
394
|
+
A 2-dimensional polyhedron in QQ^4
|
|
395
|
+
defined as the convex hull of 2 vertices and 1 ray,
|
|
396
|
+
The empty polyhedron in QQ^4]
|
|
397
|
+
sage: Polyhedra(ZZ, 0).some_elements()
|
|
398
|
+
[The empty polyhedron in ZZ^0,
|
|
399
|
+
A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex]
|
|
400
|
+
"""
|
|
401
|
+
if self.ambient_dim() == 0:
|
|
402
|
+
return [
|
|
403
|
+
self.element_class(self, None, None),
|
|
404
|
+
self.element_class(self, None, [[], []])]
|
|
405
|
+
points = []
|
|
406
|
+
R = self.base_ring()
|
|
407
|
+
for i in range(self.ambient_dim() + 5):
|
|
408
|
+
points.append([R(i*j ^ 2) for j in range(self.ambient_dim())])
|
|
409
|
+
return [
|
|
410
|
+
self.element_class(self, [points[0:self.ambient_dim() + 1], [], []], None),
|
|
411
|
+
self.element_class(self, [points[0:1], points[1:self.ambient_dim() + 1], []], None),
|
|
412
|
+
self.element_class(self, [points[0:3], points[4:5], []], None),
|
|
413
|
+
self.element_class(self, None, None)]
|
|
414
|
+
|
|
415
|
+
@cached_method
|
|
416
|
+
def zero(self):
|
|
417
|
+
r"""
|
|
418
|
+
Return the polyhedron consisting of the origin, which is the
|
|
419
|
+
neutral element for Minkowski addition.
|
|
420
|
+
|
|
421
|
+
EXAMPLES::
|
|
422
|
+
|
|
423
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
424
|
+
sage: p = Polyhedra(QQ, 4).zero(); p
|
|
425
|
+
A 0-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex
|
|
426
|
+
sage: p + p == p
|
|
427
|
+
True
|
|
428
|
+
"""
|
|
429
|
+
Vrep = [[[self.base_ring().zero()] * self.ambient_dim()], [], []]
|
|
430
|
+
return self.element_class(self, Vrep, None)
|
|
431
|
+
|
|
432
|
+
def empty(self):
|
|
433
|
+
"""
|
|
434
|
+
Return the empty polyhedron.
|
|
435
|
+
|
|
436
|
+
EXAMPLES::
|
|
437
|
+
|
|
438
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
439
|
+
sage: P = Polyhedra(QQ, 4)
|
|
440
|
+
sage: P.empty()
|
|
441
|
+
The empty polyhedron in QQ^4
|
|
442
|
+
sage: P.empty().is_empty()
|
|
443
|
+
True
|
|
444
|
+
"""
|
|
445
|
+
return self(None, None)
|
|
446
|
+
|
|
447
|
+
def universe(self):
|
|
448
|
+
"""
|
|
449
|
+
Return the entire ambient space as polyhedron.
|
|
450
|
+
|
|
451
|
+
EXAMPLES::
|
|
452
|
+
|
|
453
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
454
|
+
sage: P = Polyhedra(QQ, 4)
|
|
455
|
+
sage: P.universe()
|
|
456
|
+
A 4-dimensional polyhedron in QQ^4 defined as
|
|
457
|
+
the convex hull of 1 vertex and 4 lines
|
|
458
|
+
sage: P.universe().is_universe()
|
|
459
|
+
True
|
|
460
|
+
"""
|
|
461
|
+
R = self.base_ring()
|
|
462
|
+
return self(None, [[[R.one()] + [R.zero()] * self.ambient_dim()], []], convert=True)
|
|
463
|
+
|
|
464
|
+
@cached_method
|
|
465
|
+
def Vrepresentation_space(self):
|
|
466
|
+
r"""
|
|
467
|
+
Return the ambient vector space.
|
|
468
|
+
|
|
469
|
+
This is the vector space or module containing the
|
|
470
|
+
Vrepresentation vectors.
|
|
471
|
+
|
|
472
|
+
OUTPUT: a free module over the base ring of dimension :meth:`ambient_dim`
|
|
473
|
+
|
|
474
|
+
EXAMPLES::
|
|
475
|
+
|
|
476
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
477
|
+
sage: Polyhedra(QQ, 4).Vrepresentation_space()
|
|
478
|
+
Vector space of dimension 4 over Rational Field
|
|
479
|
+
sage: Polyhedra(QQ, 4).ambient_space()
|
|
480
|
+
Vector space of dimension 4 over Rational Field
|
|
481
|
+
"""
|
|
482
|
+
if self.base_ring() in Fields():
|
|
483
|
+
from sage.modules.free_module import VectorSpace
|
|
484
|
+
return VectorSpace(self.base_ring(), self.ambient_dim())
|
|
485
|
+
from sage.modules.free_module import FreeModule
|
|
486
|
+
return FreeModule(self.base_ring(), self.ambient_dim())
|
|
487
|
+
|
|
488
|
+
ambient_space = Vrepresentation_space
|
|
489
|
+
|
|
490
|
+
@cached_method
|
|
491
|
+
def Hrepresentation_space(self):
|
|
492
|
+
r"""
|
|
493
|
+
Return the linear space containing the H-representation vectors.
|
|
494
|
+
|
|
495
|
+
OUTPUT: a free module over the base ring of dimension :meth:`ambient_dim` + 1
|
|
496
|
+
|
|
497
|
+
EXAMPLES::
|
|
498
|
+
|
|
499
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
500
|
+
sage: Polyhedra(ZZ, 2).Hrepresentation_space()
|
|
501
|
+
Ambient free module of rank 3 over the principal ideal domain Integer Ring
|
|
502
|
+
"""
|
|
503
|
+
if self.base_ring() in Fields():
|
|
504
|
+
from sage.modules.free_module import VectorSpace
|
|
505
|
+
return VectorSpace(self.base_ring(), self.ambient_dim() + 1)
|
|
506
|
+
from sage.modules.free_module import FreeModule
|
|
507
|
+
return FreeModule(self.base_ring(), self.ambient_dim() + 1)
|
|
508
|
+
|
|
509
|
+
def _repr_base_ring(self):
|
|
510
|
+
"""
|
|
511
|
+
Return an abbreviated string representation of the base ring.
|
|
512
|
+
|
|
513
|
+
EXAMPLES::
|
|
514
|
+
|
|
515
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
516
|
+
sage: Polyhedra(QQ, 3)._repr_base_ring()
|
|
517
|
+
'QQ'
|
|
518
|
+
sage: x = polygen(ZZ, 'x')
|
|
519
|
+
sage: K.<sqrt3> = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # needs sage.rings.number_field
|
|
520
|
+
sage: Polyhedra(K, 4)._repr_base_ring() # needs sage.rings.number_field
|
|
521
|
+
'(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)'
|
|
522
|
+
"""
|
|
523
|
+
if self.base_ring() is ZZ:
|
|
524
|
+
return 'ZZ'
|
|
525
|
+
if self.base_ring() is QQ:
|
|
526
|
+
return 'QQ'
|
|
527
|
+
if self.base_ring() is RDF:
|
|
528
|
+
return 'RDF'
|
|
529
|
+
try:
|
|
530
|
+
from sage.rings.qqbar import AA
|
|
531
|
+
except ImportError:
|
|
532
|
+
pass
|
|
533
|
+
else:
|
|
534
|
+
if self.base_ring() is AA:
|
|
535
|
+
return 'AA'
|
|
536
|
+
return f'({self.base_ring()})'
|
|
537
|
+
|
|
538
|
+
def _repr_ambient_module(self) -> str:
|
|
539
|
+
"""
|
|
540
|
+
Return an abbreviated string representation of the ambient
|
|
541
|
+
space.
|
|
542
|
+
|
|
543
|
+
OUTPUT: string
|
|
544
|
+
|
|
545
|
+
EXAMPLES::
|
|
546
|
+
|
|
547
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
548
|
+
sage: Polyhedra(QQ, 3)._repr_ambient_module()
|
|
549
|
+
'QQ^3'
|
|
550
|
+
sage: x = polygen(ZZ, 'x')
|
|
551
|
+
sage: K.<sqrt3> = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # needs sage.rings.number_field
|
|
552
|
+
sage: Polyhedra(K, 4)._repr_ambient_module() # needs sage.rings.number_field
|
|
553
|
+
'(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^4'
|
|
554
|
+
"""
|
|
555
|
+
s = self._repr_base_ring()
|
|
556
|
+
s += '^' + repr(self.ambient_dim())
|
|
557
|
+
return s
|
|
558
|
+
|
|
559
|
+
def _repr_(self):
|
|
560
|
+
"""
|
|
561
|
+
Return a string representation.
|
|
562
|
+
|
|
563
|
+
OUTPUT: string
|
|
564
|
+
|
|
565
|
+
EXAMPLES::
|
|
566
|
+
|
|
567
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
568
|
+
sage: Polyhedra(QQ, 3)
|
|
569
|
+
Polyhedra in QQ^3
|
|
570
|
+
sage: Polyhedra(QQ, 3)._repr_()
|
|
571
|
+
'Polyhedra in QQ^3'
|
|
572
|
+
"""
|
|
573
|
+
return 'Polyhedra in ' + self._repr_ambient_module()
|
|
574
|
+
|
|
575
|
+
def _element_constructor_(self, *args, **kwds):
|
|
576
|
+
"""
|
|
577
|
+
The element (polyhedron) constructor.
|
|
578
|
+
|
|
579
|
+
INPUT:
|
|
580
|
+
|
|
581
|
+
- ``Vrep`` -- list ``[vertices, rays, lines]`` or ``None``
|
|
582
|
+
|
|
583
|
+
- ``Hrep`` -- list ``[ieqs, eqns]`` or ``None``
|
|
584
|
+
|
|
585
|
+
- ``convert`` -- boolean (default: ``True``); whether to convert the
|
|
586
|
+
coordinates into the base ring
|
|
587
|
+
|
|
588
|
+
- ``**kwds`` -- (optional) remaining keywords that are passed to the
|
|
589
|
+
polyhedron constructor
|
|
590
|
+
|
|
591
|
+
EXAMPLES::
|
|
592
|
+
|
|
593
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
594
|
+
sage: P = Polyhedra(QQ, 3)
|
|
595
|
+
sage: P._element_constructor_([[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0,0,1)], [], []], None)
|
|
596
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
|
|
597
|
+
sage: P([[(0,0,0),(1,0,0),(0,1,0),(0,0,1)], [], []], None)
|
|
598
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
|
|
599
|
+
sage: P(0)
|
|
600
|
+
A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex
|
|
601
|
+
|
|
602
|
+
Check that :issue:`21270` is fixed::
|
|
603
|
+
|
|
604
|
+
sage: # needs sage.rings.number_field
|
|
605
|
+
sage: poly = polytopes.regular_polygon(7)
|
|
606
|
+
sage: lp, x = poly.to_linear_program(solver='InteractiveLP',
|
|
607
|
+
....: return_variable=True)
|
|
608
|
+
sage: lp.set_objective(x[0] + x[1])
|
|
609
|
+
sage: b = lp.get_backend()
|
|
610
|
+
sage: P = b.interactive_lp_problem()
|
|
611
|
+
sage: p = P.plot() # needs sage.plot sage.symbolic
|
|
612
|
+
|
|
613
|
+
sage: Q = Polyhedron(ieqs=[[-499999, 1000000], [1499999, -1000000]])
|
|
614
|
+
sage: P = Polyhedron(ieqs=[[0, 1.0], [1.0, -1.0]], base_ring=RDF) # needs cddexec
|
|
615
|
+
sage: Q.intersection(P) # needs cddexec
|
|
616
|
+
A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices
|
|
617
|
+
sage: P.intersection(Q) # needs cddexec
|
|
618
|
+
A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices
|
|
619
|
+
|
|
620
|
+
The default is not to copy an object if the parent is ``self``::
|
|
621
|
+
|
|
622
|
+
sage: p = polytopes.cube(backend='field')
|
|
623
|
+
sage: P = p.parent()
|
|
624
|
+
sage: q = P._element_constructor_(p)
|
|
625
|
+
sage: q is p
|
|
626
|
+
True
|
|
627
|
+
sage: r = P._element_constructor_(p, copy=True)
|
|
628
|
+
sage: r is p
|
|
629
|
+
False
|
|
630
|
+
|
|
631
|
+
When the parent of the object is not ``self``, the default is not to copy::
|
|
632
|
+
|
|
633
|
+
sage: # needs sage.rings.number_field
|
|
634
|
+
sage: Q = P.base_extend(AA)
|
|
635
|
+
sage: q = Q._element_constructor_(p)
|
|
636
|
+
sage: q is p
|
|
637
|
+
False
|
|
638
|
+
sage: q = Q._element_constructor_(p, copy=False)
|
|
639
|
+
Traceback (most recent call last):
|
|
640
|
+
...
|
|
641
|
+
ValueError: you need to make a copy when changing the parent
|
|
642
|
+
|
|
643
|
+
For mutable polyhedra either ``copy`` or ``mutable`` must be specified::
|
|
644
|
+
|
|
645
|
+
sage: p = Polyhedron(vertices=[[0, 1], [1, 0]], mutable=True)
|
|
646
|
+
sage: P = p.parent()
|
|
647
|
+
sage: q = P._element_constructor_(p)
|
|
648
|
+
Traceback (most recent call last):
|
|
649
|
+
...
|
|
650
|
+
ValueError: must make a copy to obtain immutable object from mutable input
|
|
651
|
+
sage: q = P._element_constructor_(p, mutable=True)
|
|
652
|
+
sage: q is p
|
|
653
|
+
True
|
|
654
|
+
sage: r = P._element_constructor_(p, copy=True)
|
|
655
|
+
sage: r.is_mutable()
|
|
656
|
+
False
|
|
657
|
+
sage: r is p
|
|
658
|
+
False
|
|
659
|
+
"""
|
|
660
|
+
nargs = len(args)
|
|
661
|
+
convert = kwds.pop('convert', True)
|
|
662
|
+
|
|
663
|
+
def convert_base_ring(lstlst):
|
|
664
|
+
return [[self.base_ring()(x) for x in lst] for lst in lstlst]
|
|
665
|
+
|
|
666
|
+
# renormalize before converting when going from QQ to RDF, see trac 21270
|
|
667
|
+
def convert_base_ring_Hrep(lstlst):
|
|
668
|
+
newlstlst = []
|
|
669
|
+
for lst in lstlst:
|
|
670
|
+
if all(c in QQ for c in lst):
|
|
671
|
+
m = max(abs(w) for w in lst)
|
|
672
|
+
if m == 0:
|
|
673
|
+
newlstlst.append(lst)
|
|
674
|
+
else:
|
|
675
|
+
newlstlst.append([q / m for q in lst])
|
|
676
|
+
else:
|
|
677
|
+
newlstlst.append(lst)
|
|
678
|
+
return convert_base_ring(newlstlst)
|
|
679
|
+
if nargs == 2:
|
|
680
|
+
Vrep, Hrep = args
|
|
681
|
+
if convert and Hrep:
|
|
682
|
+
if self.base_ring == RDF:
|
|
683
|
+
Hrep = [convert_base_ring_Hrep(_) for _ in Hrep]
|
|
684
|
+
else:
|
|
685
|
+
Hrep = [convert_base_ring(_) for _ in Hrep]
|
|
686
|
+
if convert and Vrep:
|
|
687
|
+
Vrep = [convert_base_ring(_) for _ in Vrep]
|
|
688
|
+
return self.element_class(self, Vrep, Hrep, **kwds)
|
|
689
|
+
if nargs == 1 and isinstance(args[0], sage.geometry.abc.Polyhedron):
|
|
690
|
+
copy = kwds.pop('copy', args[0].parent() is not self)
|
|
691
|
+
mutable = kwds.pop('mutable', False)
|
|
692
|
+
|
|
693
|
+
if not copy and args[0].parent() is not self:
|
|
694
|
+
raise ValueError("you need to make a copy when changing the parent")
|
|
695
|
+
if args[0].is_mutable() and not copy and not mutable:
|
|
696
|
+
raise ValueError("must make a copy to obtain immutable object from mutable input")
|
|
697
|
+
if not copy and mutable is args[0].is_mutable():
|
|
698
|
+
return args[0]
|
|
699
|
+
|
|
700
|
+
polyhedron = args[0]
|
|
701
|
+
return self._element_constructor_polyhedron(polyhedron, mutable=mutable, **kwds)
|
|
702
|
+
if nargs == 1 and args[0] == 0:
|
|
703
|
+
return self.zero()
|
|
704
|
+
raise ValueError('cannot convert to polyhedron object')
|
|
705
|
+
|
|
706
|
+
def _element_constructor_polyhedron(self, polyhedron, **kwds):
|
|
707
|
+
"""
|
|
708
|
+
The element (polyhedron) constructor for the case of 1 argument, a polyhedron.
|
|
709
|
+
|
|
710
|
+
Set up the element using both representations,
|
|
711
|
+
if the backend can handle it.
|
|
712
|
+
|
|
713
|
+
Otherwise set up the element from Hrepresentation.
|
|
714
|
+
|
|
715
|
+
EXAMPLES::
|
|
716
|
+
|
|
717
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
718
|
+
sage: P = Polyhedra(QQ, 3, backend='cdd')
|
|
719
|
+
sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)])
|
|
720
|
+
sage: p
|
|
721
|
+
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
|
|
722
|
+
sage: P(p) # needs cddexec_gmp
|
|
723
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
|
|
724
|
+
|
|
725
|
+
sage: P = Polyhedra(AA, 3, backend='field') # needs sage.rings.number_field
|
|
726
|
+
sage: vertices = [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)]
|
|
727
|
+
sage: p = Polyhedron(vertices=vertices)
|
|
728
|
+
sage: P(p) # needs sage.rings.number_field
|
|
729
|
+
A 3-dimensional polyhedron in AA^3 defined as the convex hull of 4 vertices
|
|
730
|
+
"""
|
|
731
|
+
Vrep = None
|
|
732
|
+
if hasattr(self.Element, '_init_from_Vrepresentation_and_Hrepresentation'):
|
|
733
|
+
Vrep = [polyhedron.vertex_generator(), polyhedron.ray_generator(),
|
|
734
|
+
polyhedron.line_generator()]
|
|
735
|
+
Hrep = [polyhedron.inequality_generator(), polyhedron.equation_generator()]
|
|
736
|
+
return self._element_constructor_(Vrep, Hrep, Vrep_minimal=True, Hrep_minimal=True, **kwds)
|
|
737
|
+
|
|
738
|
+
def base_extend(self, base_ring, backend=None, ambient_dim=None):
|
|
739
|
+
"""
|
|
740
|
+
Return the base extended parent.
|
|
741
|
+
|
|
742
|
+
INPUT:
|
|
743
|
+
|
|
744
|
+
- ``base_ring``, ``backend`` -- see
|
|
745
|
+
:func:`~sage.geometry.polyhedron.constructor.Polyhedron`
|
|
746
|
+
- ``ambient_dim`` -- if not ``None`` change ambient dimension
|
|
747
|
+
accordingly
|
|
748
|
+
|
|
749
|
+
EXAMPLES::
|
|
750
|
+
|
|
751
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
752
|
+
sage: Polyhedra(ZZ, 3).base_extend(QQ)
|
|
753
|
+
Polyhedra in QQ^3
|
|
754
|
+
sage: Polyhedra(ZZ, 3).an_element().base_extend(QQ)
|
|
755
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
|
|
756
|
+
sage: Polyhedra(QQ, 2).base_extend(ZZ)
|
|
757
|
+
Polyhedra in QQ^2
|
|
758
|
+
|
|
759
|
+
TESTS:
|
|
760
|
+
|
|
761
|
+
Test that :issue:`22575` is fixed::
|
|
762
|
+
|
|
763
|
+
sage: P = Polyhedra(ZZ,3).base_extend(QQ, backend='field')
|
|
764
|
+
sage: P.backend()
|
|
765
|
+
'field'
|
|
766
|
+
"""
|
|
767
|
+
if self.base_ring().has_coerce_map_from(base_ring):
|
|
768
|
+
new_ring = self.base_ring()
|
|
769
|
+
else:
|
|
770
|
+
new_ring = self._coerce_base_ring(base_ring)
|
|
771
|
+
|
|
772
|
+
return self.change_ring(new_ring, backend=backend, ambient_dim=ambient_dim)
|
|
773
|
+
|
|
774
|
+
def change_ring(self, base_ring, backend=None, ambient_dim=None):
|
|
775
|
+
"""
|
|
776
|
+
Return the parent with the new base ring.
|
|
777
|
+
|
|
778
|
+
INPUT:
|
|
779
|
+
|
|
780
|
+
- ``base_ring``, ``backend`` -- see
|
|
781
|
+
:func:`~sage.geometry.polyhedron.constructor.Polyhedron`
|
|
782
|
+
- ``ambient_dim`` -- if not ``None`` change ambient dimension
|
|
783
|
+
accordingly
|
|
784
|
+
|
|
785
|
+
EXAMPLES::
|
|
786
|
+
|
|
787
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
788
|
+
sage: Polyhedra(ZZ, 3).change_ring(QQ)
|
|
789
|
+
Polyhedra in QQ^3
|
|
790
|
+
sage: Polyhedra(ZZ, 3).an_element().change_ring(QQ)
|
|
791
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
|
|
792
|
+
|
|
793
|
+
sage: Polyhedra(RDF, 3).change_ring(QQ).backend()
|
|
794
|
+
'cdd'
|
|
795
|
+
sage: Polyhedra(QQ, 3).change_ring(ZZ, ambient_dim=4)
|
|
796
|
+
Polyhedra in ZZ^4
|
|
797
|
+
sage: Polyhedra(QQ, 3, backend='cdd').change_ring(QQ, ambient_dim=4).backend()
|
|
798
|
+
'cdd'
|
|
799
|
+
"""
|
|
800
|
+
if ambient_dim is None:
|
|
801
|
+
ambient_dim = self.ambient_dim()
|
|
802
|
+
|
|
803
|
+
if base_ring == self.base_ring() and \
|
|
804
|
+
ambient_dim == self.ambient_dim() and \
|
|
805
|
+
(backend is None or backend == self.backend()):
|
|
806
|
+
return self
|
|
807
|
+
|
|
808
|
+
# if not specified try the same backend
|
|
809
|
+
if backend is None and does_backend_handle_base_ring(base_ring, self.backend()):
|
|
810
|
+
return Polyhedra(base_ring, ambient_dim, backend=self.backend())
|
|
811
|
+
|
|
812
|
+
return Polyhedra(base_ring, ambient_dim, backend=backend)
|
|
813
|
+
|
|
814
|
+
def _coerce_base_ring(self, other):
|
|
815
|
+
r"""
|
|
816
|
+
Return the common base ring for both ``self`` and ``other``.
|
|
817
|
+
|
|
818
|
+
This method is not part of the coercion framework, but only a
|
|
819
|
+
convenience function for :class:`Polyhedra_base`.
|
|
820
|
+
|
|
821
|
+
INPUT:
|
|
822
|
+
|
|
823
|
+
- ``other`` -- must be either:
|
|
824
|
+
|
|
825
|
+
* another ``Polyhedron`` object
|
|
826
|
+
|
|
827
|
+
* `\ZZ`, `\QQ`, `RDF`, or a ring that can be coerced into them.
|
|
828
|
+
|
|
829
|
+
* a constant that can be coerced to `\ZZ`, `\QQ`, or `RDF`.
|
|
830
|
+
|
|
831
|
+
OUTPUT:
|
|
832
|
+
|
|
833
|
+
Either `\ZZ`, `\QQ`, or `RDF`. Raises :exc:`TypeError` if
|
|
834
|
+
``other`` is not a suitable input.
|
|
835
|
+
|
|
836
|
+
.. NOTE::
|
|
837
|
+
|
|
838
|
+
"Real" numbers in sage are not necessarily elements of
|
|
839
|
+
``RDF``. For example, the literal `1.0` is not.
|
|
840
|
+
|
|
841
|
+
EXAMPLES::
|
|
842
|
+
|
|
843
|
+
sage: triangle_QQ = Polyhedron(vertices=[[1,0],[0,1],[1,1]], base_ring=QQ).parent()
|
|
844
|
+
sage: triangle_RDF = Polyhedron(vertices=[[1,0],[0,1],[1,1]], base_ring=RDF).parent() # needs cddexec
|
|
845
|
+
sage: triangle_QQ._coerce_base_ring(QQ)
|
|
846
|
+
Rational Field
|
|
847
|
+
sage: triangle_QQ._coerce_base_ring(triangle_RDF) # needs cddexec
|
|
848
|
+
Real Double Field
|
|
849
|
+
sage: triangle_RDF._coerce_base_ring(triangle_QQ) # needs cddexec
|
|
850
|
+
Real Double Field
|
|
851
|
+
sage: triangle_QQ._coerce_base_ring(RDF) # needs cddexec
|
|
852
|
+
Real Double Field
|
|
853
|
+
sage: triangle_QQ._coerce_base_ring(ZZ)
|
|
854
|
+
Rational Field
|
|
855
|
+
sage: triangle_QQ._coerce_base_ring(1/2)
|
|
856
|
+
Rational Field
|
|
857
|
+
sage: triangle_QQ._coerce_base_ring(0.5) # needs cddexec
|
|
858
|
+
Real Double Field
|
|
859
|
+
|
|
860
|
+
TESTS:
|
|
861
|
+
|
|
862
|
+
Test that :issue:`28770` is fixed::
|
|
863
|
+
|
|
864
|
+
sage: z = QQ['z'].0
|
|
865
|
+
sage: K = NumberField(z^2 - 2, 's') # needs sage.rings.number_field
|
|
866
|
+
sage: triangle_QQ._coerce_base_ring(K) # needs sage.rings.number_field
|
|
867
|
+
Number Field in s with defining polynomial z^2 - 2
|
|
868
|
+
sage: triangle_QQ._coerce_base_ring(K.gen()) # needs sage.rings.number_field
|
|
869
|
+
Number Field in s with defining polynomial z^2 - 2
|
|
870
|
+
|
|
871
|
+
sage: z = QQ['z'].0
|
|
872
|
+
sage: K = NumberField(z^2 - 2, 's') # needs sage.rings.number_field
|
|
873
|
+
sage: K.gen() * polytopes.simplex(backend='field') # needs sage.rings.number_field
|
|
874
|
+
A 3-dimensional polyhedron in
|
|
875
|
+
(Number Field in s with defining polynomial z^2 - 2)^4
|
|
876
|
+
defined as the convex hull of 4 vertices
|
|
877
|
+
"""
|
|
878
|
+
from sage.structure.element import Element
|
|
879
|
+
if isinstance(other, Element):
|
|
880
|
+
other = other.parent()
|
|
881
|
+
if other in Rings():
|
|
882
|
+
other_ring = other
|
|
883
|
+
else:
|
|
884
|
+
try:
|
|
885
|
+
other_ring = other.base_ring()
|
|
886
|
+
except AttributeError:
|
|
887
|
+
try:
|
|
888
|
+
# other is a constant?
|
|
889
|
+
other_ring = other.parent()
|
|
890
|
+
except AttributeError:
|
|
891
|
+
other_ring = None
|
|
892
|
+
for ring in (ZZ, QQ, RDF):
|
|
893
|
+
try:
|
|
894
|
+
ring.coerce(other)
|
|
895
|
+
other_ring = ring
|
|
896
|
+
break
|
|
897
|
+
except TypeError:
|
|
898
|
+
pass
|
|
899
|
+
if other_ring is None:
|
|
900
|
+
raise TypeError(f'Could not coerce {other} into ZZ, QQ, or RDF.')
|
|
901
|
+
|
|
902
|
+
if not other_ring.is_exact():
|
|
903
|
+
other_ring = RDF # the only supported floating-point numbers for now
|
|
904
|
+
|
|
905
|
+
cm_map, cm_ring = get_coercion_model().analyse(self.base_ring(), other_ring)
|
|
906
|
+
if cm_ring is None:
|
|
907
|
+
raise TypeError(f'Could not coerce type {other} into ZZ, QQ, or RDF.')
|
|
908
|
+
return cm_ring
|
|
909
|
+
|
|
910
|
+
def _coerce_map_from_(self, X):
|
|
911
|
+
r"""
|
|
912
|
+
Return whether there is a coercion from ``X``.
|
|
913
|
+
|
|
914
|
+
INPUT:
|
|
915
|
+
|
|
916
|
+
- ``X`` -- anything
|
|
917
|
+
|
|
918
|
+
OUTPUT: boolean
|
|
919
|
+
|
|
920
|
+
EXAMPLES::
|
|
921
|
+
|
|
922
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
923
|
+
sage: Polyhedra(QQ, 3).has_coerce_map_from(Polyhedra(ZZ, 3)) # indirect doctest
|
|
924
|
+
True
|
|
925
|
+
sage: Polyhedra(ZZ, 3).has_coerce_map_from(Polyhedra(QQ, 3))
|
|
926
|
+
False
|
|
927
|
+
"""
|
|
928
|
+
if not isinstance(X, Polyhedra_base):
|
|
929
|
+
return False
|
|
930
|
+
if self.ambient_dim() != X.ambient_dim():
|
|
931
|
+
return False
|
|
932
|
+
return self.base_ring().has_coerce_map_from(X.base_ring())
|
|
933
|
+
|
|
934
|
+
def _get_action_(self, other, op, self_is_left):
|
|
935
|
+
"""
|
|
936
|
+
Register actions with the coercion model.
|
|
937
|
+
|
|
938
|
+
The monoid actions are Minkowski sum and Cartesian product. In
|
|
939
|
+
addition, we want multiplication by a scalar to be dilation
|
|
940
|
+
and addition by a vector to be translation. This is
|
|
941
|
+
implemented as an action in the coercion model.
|
|
942
|
+
|
|
943
|
+
INPUT:
|
|
944
|
+
|
|
945
|
+
- ``other`` -- a scalar or a vector
|
|
946
|
+
|
|
947
|
+
- ``op`` -- the operator
|
|
948
|
+
|
|
949
|
+
- ``self_is_left`` -- boolean; whether ``self`` is on the left
|
|
950
|
+
of the operator
|
|
951
|
+
|
|
952
|
+
OUTPUT: an action that is used by the coercion model
|
|
953
|
+
|
|
954
|
+
EXAMPLES::
|
|
955
|
+
|
|
956
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
957
|
+
sage: PZZ2 = Polyhedra(ZZ, 2)
|
|
958
|
+
sage: PZZ2.get_action(ZZ) # indirect doctest
|
|
959
|
+
Right action by Integer Ring on Polyhedra in ZZ^2
|
|
960
|
+
sage: PZZ2.get_action(QQ)
|
|
961
|
+
Right action by Rational Field on Polyhedra in QQ^2
|
|
962
|
+
with precomposition on left by Coercion map:
|
|
963
|
+
From: Polyhedra in ZZ^2
|
|
964
|
+
To: Polyhedra in QQ^2
|
|
965
|
+
with precomposition on right by Identity endomorphism of Rational Field
|
|
966
|
+
sage: PQQ2 = Polyhedra(QQ, 2)
|
|
967
|
+
sage: PQQ2.get_action(ZZ)
|
|
968
|
+
Right action by Integer Ring on Polyhedra in QQ^2
|
|
969
|
+
sage: PQQ2.get_action(QQ)
|
|
970
|
+
Right action by Rational Field on Polyhedra in QQ^2
|
|
971
|
+
|
|
972
|
+
sage: Polyhedra(ZZ,2).an_element() * 2
|
|
973
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
|
|
974
|
+
sage: Polyhedra(ZZ,2).an_element() * (2/3)
|
|
975
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
|
|
976
|
+
sage: Polyhedra(QQ,2).an_element() * 2
|
|
977
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
|
|
978
|
+
sage: Polyhedra(QQ,2).an_element() * (2/3)
|
|
979
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
|
|
980
|
+
|
|
981
|
+
sage: 2 * Polyhedra(ZZ,2).an_element()
|
|
982
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
|
|
983
|
+
sage: (2/3) * Polyhedra(ZZ,2).an_element()
|
|
984
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
|
|
985
|
+
sage: 2 * Polyhedra(QQ,2).an_element()
|
|
986
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
|
|
987
|
+
sage: (2/3) * Polyhedra(QQ,2).an_element()
|
|
988
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
|
|
989
|
+
|
|
990
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
991
|
+
sage: PZZ2.get_action(ZZ^2, op=operator.add)
|
|
992
|
+
Right action by Ambient free module of rank 2 over the principal ideal domain Integer Ring on Polyhedra in ZZ^2
|
|
993
|
+
with precomposition on left by
|
|
994
|
+
Identity endomorphism of Polyhedra in ZZ^2
|
|
995
|
+
with precomposition on right by
|
|
996
|
+
Generic endomorphism of Ambient free module of rank 2 over the principal ideal domain Integer Ring
|
|
997
|
+
"""
|
|
998
|
+
import operator
|
|
999
|
+
from sage.structure.coerce_actions import ActedUponAction
|
|
1000
|
+
from sage.categories.action import PrecomposedAction
|
|
1001
|
+
|
|
1002
|
+
if op is operator.add and isinstance(other, FreeModule_generic):
|
|
1003
|
+
base_ring = self._coerce_base_ring(other)
|
|
1004
|
+
extended_self = self.base_extend(base_ring)
|
|
1005
|
+
extended_other = other.base_extend(base_ring)
|
|
1006
|
+
action = ActedUponAction(extended_other, extended_self, not self_is_left)
|
|
1007
|
+
if self_is_left:
|
|
1008
|
+
action = PrecomposedAction(action,
|
|
1009
|
+
extended_self._internal_coerce_map_from(self).__copy__(),
|
|
1010
|
+
extended_other._internal_coerce_map_from(other).__copy__())
|
|
1011
|
+
else:
|
|
1012
|
+
action = PrecomposedAction(action,
|
|
1013
|
+
extended_other._internal_coerce_map_from(other).__copy__(),
|
|
1014
|
+
extended_self._internal_coerce_map_from(self).__copy__())
|
|
1015
|
+
return action
|
|
1016
|
+
|
|
1017
|
+
if op is operator.mul and other in Rings().Commutative():
|
|
1018
|
+
ring = self._coerce_base_ring(other)
|
|
1019
|
+
if ring is self.base_ring():
|
|
1020
|
+
return ActedUponAction(other, self, not self_is_left)
|
|
1021
|
+
extended = self.base_extend(ring)
|
|
1022
|
+
action = ActedUponAction(ring, extended, not self_is_left)
|
|
1023
|
+
if self_is_left:
|
|
1024
|
+
action = PrecomposedAction(action,
|
|
1025
|
+
extended._internal_coerce_map_from(self).__copy__(),
|
|
1026
|
+
ring._internal_coerce_map_from(other).__copy__())
|
|
1027
|
+
else:
|
|
1028
|
+
action = PrecomposedAction(action,
|
|
1029
|
+
ring._internal_coerce_map_from(other).__copy__(),
|
|
1030
|
+
extended._internal_coerce_map_from(self).__copy__())
|
|
1031
|
+
return action
|
|
1032
|
+
|
|
1033
|
+
def _make_Inequality(self, polyhedron, data):
|
|
1034
|
+
"""
|
|
1035
|
+
Create a new inequality object.
|
|
1036
|
+
|
|
1037
|
+
INPUT:
|
|
1038
|
+
|
|
1039
|
+
- ``polyhedron`` -- the new polyhedron
|
|
1040
|
+
|
|
1041
|
+
- ``data`` -- the H-representation data
|
|
1042
|
+
|
|
1043
|
+
OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Inequality` object
|
|
1044
|
+
|
|
1045
|
+
EXAMPLES::
|
|
1046
|
+
|
|
1047
|
+
sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)]) # indirect doctest
|
|
1048
|
+
sage: next(p.inequality_generator())
|
|
1049
|
+
An inequality (0, 0, -1) x + 3 >= 0
|
|
1050
|
+
"""
|
|
1051
|
+
try:
|
|
1052
|
+
obj = self._Inequality_pool.pop()
|
|
1053
|
+
except IndexError:
|
|
1054
|
+
obj = Inequality(self)
|
|
1055
|
+
obj._set_data(polyhedron, data)
|
|
1056
|
+
return obj
|
|
1057
|
+
|
|
1058
|
+
def _make_Equation(self, polyhedron, data):
|
|
1059
|
+
"""
|
|
1060
|
+
Create a new equation object.
|
|
1061
|
+
|
|
1062
|
+
INPUT:
|
|
1063
|
+
|
|
1064
|
+
- ``polyhedron`` -- the new polyhedron
|
|
1065
|
+
|
|
1066
|
+
- ``data`` -- the H-representation data
|
|
1067
|
+
|
|
1068
|
+
OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Equation` object
|
|
1069
|
+
|
|
1070
|
+
EXAMPLES::
|
|
1071
|
+
|
|
1072
|
+
sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)]) # indirect doctest
|
|
1073
|
+
sage: next(p.equation_generator())
|
|
1074
|
+
An equation (0, 44, -25) x - 13 == 0
|
|
1075
|
+
"""
|
|
1076
|
+
try:
|
|
1077
|
+
obj = self._Equation_pool.pop()
|
|
1078
|
+
except IndexError:
|
|
1079
|
+
obj = Equation(self)
|
|
1080
|
+
obj._set_data(polyhedron, data)
|
|
1081
|
+
return obj
|
|
1082
|
+
|
|
1083
|
+
def _make_Vertex(self, polyhedron, data):
|
|
1084
|
+
"""
|
|
1085
|
+
Create a new vertex object.
|
|
1086
|
+
|
|
1087
|
+
INPUT:
|
|
1088
|
+
|
|
1089
|
+
- ``polyhedron`` -- the new polyhedron
|
|
1090
|
+
|
|
1091
|
+
- ``data`` -- the V-representation data
|
|
1092
|
+
|
|
1093
|
+
OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Vertex` object
|
|
1094
|
+
|
|
1095
|
+
EXAMPLES::
|
|
1096
|
+
|
|
1097
|
+
sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest
|
|
1098
|
+
sage: next(p.vertex_generator())
|
|
1099
|
+
A vertex at (1, 2, 3)
|
|
1100
|
+
"""
|
|
1101
|
+
try:
|
|
1102
|
+
obj = self._Vertex_pool.pop()
|
|
1103
|
+
except IndexError:
|
|
1104
|
+
obj = Vertex(self)
|
|
1105
|
+
obj._set_data(polyhedron, data)
|
|
1106
|
+
return obj
|
|
1107
|
+
|
|
1108
|
+
def _make_Ray(self, polyhedron, data):
|
|
1109
|
+
"""
|
|
1110
|
+
Create a new ray object.
|
|
1111
|
+
|
|
1112
|
+
INPUT:
|
|
1113
|
+
|
|
1114
|
+
- ``polyhedron`` -- the new polyhedron
|
|
1115
|
+
|
|
1116
|
+
- ``data`` -- the V-representation data
|
|
1117
|
+
|
|
1118
|
+
OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Ray` object
|
|
1119
|
+
|
|
1120
|
+
EXAMPLES::
|
|
1121
|
+
|
|
1122
|
+
sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest
|
|
1123
|
+
sage: next(p.ray_generator())
|
|
1124
|
+
A ray in the direction (140, 144, 147)
|
|
1125
|
+
"""
|
|
1126
|
+
try:
|
|
1127
|
+
obj = self._Ray_pool.pop()
|
|
1128
|
+
except IndexError:
|
|
1129
|
+
obj = Ray(self)
|
|
1130
|
+
obj._set_data(polyhedron, data)
|
|
1131
|
+
return obj
|
|
1132
|
+
|
|
1133
|
+
def _make_Line(self, polyhedron, data):
|
|
1134
|
+
"""
|
|
1135
|
+
Create a new line object.
|
|
1136
|
+
|
|
1137
|
+
INPUT:
|
|
1138
|
+
|
|
1139
|
+
- ``polyhedron`` -- the new polyhedron
|
|
1140
|
+
|
|
1141
|
+
- ``data`` -- the V-representation data
|
|
1142
|
+
|
|
1143
|
+
OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Line` object
|
|
1144
|
+
|
|
1145
|
+
EXAMPLES::
|
|
1146
|
+
|
|
1147
|
+
sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], lines=[(5/6,6/7,7/8)]) # indirect doctest
|
|
1148
|
+
sage: next(p.line_generator())
|
|
1149
|
+
A line in the direction (140, 144, 147)
|
|
1150
|
+
"""
|
|
1151
|
+
try:
|
|
1152
|
+
obj = self._Line_pool.pop()
|
|
1153
|
+
except IndexError:
|
|
1154
|
+
obj = Line(self)
|
|
1155
|
+
obj._set_data(polyhedron, data)
|
|
1156
|
+
return obj
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd
|
|
1160
|
+
lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', 'Polyhedron_RDF_cdd')
|
|
1161
|
+
from sage.geometry.polyhedron.backend_ppl import Polyhedron_ZZ_ppl, Polyhedron_QQ_ppl
|
|
1162
|
+
from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz, Polyhedron_ZZ_normaliz, Polyhedron_QQ_normaliz
|
|
1163
|
+
from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake
|
|
1164
|
+
from sage.geometry.polyhedron.backend_field import Polyhedron_field
|
|
1165
|
+
from sage.geometry.polyhedron.backend_number_field import Polyhedron_number_field
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
class Polyhedra_ZZ_ppl(Polyhedra_base):
|
|
1169
|
+
Element = Polyhedron_ZZ_ppl
|
|
1170
|
+
|
|
1171
|
+
def _element_constructor_polyhedron(self, polyhedron, **kwds):
|
|
1172
|
+
"""
|
|
1173
|
+
The element (polyhedron) constructor for the case of 1 argument, a polyhedron.
|
|
1174
|
+
|
|
1175
|
+
Set up with the ``ppl_polyhedron`` of ``self``, if available.
|
|
1176
|
+
|
|
1177
|
+
EXAMPLES::
|
|
1178
|
+
|
|
1179
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
1180
|
+
sage: P = Polyhedra(ZZ, 3)
|
|
1181
|
+
sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)], base_ring=QQ)
|
|
1182
|
+
sage: p
|
|
1183
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
|
|
1184
|
+
sage: P(p)
|
|
1185
|
+
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
|
|
1186
|
+
|
|
1187
|
+
sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)], backend='cdd') # needs cddexec_gmp
|
|
1188
|
+
sage: P(p)
|
|
1189
|
+
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
|
|
1190
|
+
"""
|
|
1191
|
+
from copy import copy
|
|
1192
|
+
if polyhedron.backend() == "ppl":
|
|
1193
|
+
return self._element_constructor_(None, None, ppl_polyhedron=copy(polyhedron._ppl_polyhedron), **kwds)
|
|
1194
|
+
else:
|
|
1195
|
+
return Polyhedra_base._element_constructor_polyhedron(self, polyhedron, **kwds)
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
class Polyhedra_ZZ_normaliz(Polyhedra_base):
|
|
1199
|
+
Element = Polyhedron_ZZ_normaliz
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
class Polyhedra_QQ_ppl(Polyhedra_base):
|
|
1203
|
+
Element = Polyhedron_QQ_ppl
|
|
1204
|
+
|
|
1205
|
+
def _element_constructor_polyhedron(self, polyhedron, **kwds):
|
|
1206
|
+
"""
|
|
1207
|
+
The element (polyhedron) constructor for the case of 1 argument, a polyhedron.
|
|
1208
|
+
|
|
1209
|
+
Set up with the ``ppl_polyhedron`` of ``self``, if available.
|
|
1210
|
+
|
|
1211
|
+
EXAMPLES::
|
|
1212
|
+
|
|
1213
|
+
sage: from sage.geometry.polyhedron.parent import Polyhedra
|
|
1214
|
+
sage: P = Polyhedra(QQ, 3)
|
|
1215
|
+
sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)])
|
|
1216
|
+
sage: p
|
|
1217
|
+
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
|
|
1218
|
+
sage: P(p)
|
|
1219
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
|
|
1220
|
+
|
|
1221
|
+
sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)], backend='cdd') # needs cddexec_gmp
|
|
1222
|
+
sage: P(p)
|
|
1223
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
|
|
1224
|
+
"""
|
|
1225
|
+
from copy import copy
|
|
1226
|
+
if polyhedron.backend() == "ppl":
|
|
1227
|
+
return self._element_constructor_(None, None, ppl_polyhedron=copy(polyhedron._ppl_polyhedron), **kwds)
|
|
1228
|
+
else:
|
|
1229
|
+
return Polyhedra_base._element_constructor_polyhedron(self, polyhedron, **kwds)
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
class Polyhedra_QQ_normaliz(Polyhedra_base):
|
|
1233
|
+
Element = Polyhedron_QQ_normaliz
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
class Polyhedra_QQ_cdd(Polyhedra_base):
|
|
1237
|
+
Element = Polyhedron_QQ_cdd
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
class Polyhedra_RDF_cdd(Polyhedra_base):
|
|
1241
|
+
Element = Polyhedron_RDF_cdd
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
class Polyhedra_normaliz(Polyhedra_base):
|
|
1245
|
+
Element = Polyhedron_normaliz
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
class Polyhedra_polymake(Polyhedra_base):
|
|
1249
|
+
Element = Polyhedron_polymake
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
class Polyhedra_field(Polyhedra_base):
|
|
1253
|
+
Element = Polyhedron_field
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
class Polyhedra_number_field(Polyhedra_base):
|
|
1257
|
+
Element = Polyhedron_number_field
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
@cached_function
|
|
1261
|
+
def does_backend_handle_base_ring(base_ring, backend):
|
|
1262
|
+
r"""
|
|
1263
|
+
Return true, if ``backend`` can handle ``base_ring``.
|
|
1264
|
+
|
|
1265
|
+
EXAMPLES::
|
|
1266
|
+
|
|
1267
|
+
sage: from sage.geometry.polyhedron.parent import does_backend_handle_base_ring
|
|
1268
|
+
sage: does_backend_handle_base_ring(QQ, 'ppl')
|
|
1269
|
+
True
|
|
1270
|
+
sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'ppl') # needs sage.rings.number_field sage.symbolic
|
|
1271
|
+
False
|
|
1272
|
+
sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'field') # needs sage.rings.number_field sage.symbolic
|
|
1273
|
+
True
|
|
1274
|
+
"""
|
|
1275
|
+
try:
|
|
1276
|
+
Polyhedra(base_ring, 0, backend)
|
|
1277
|
+
except ValueError:
|
|
1278
|
+
return False
|
|
1279
|
+
return True
|