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,2028 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
r"""
|
|
3
|
+
Interface to polymake
|
|
4
|
+
|
|
5
|
+
polymake (https://polymake.org) is a mature open source package for
|
|
6
|
+
research in polyhedral geometry and related fields, developed since 1997
|
|
7
|
+
by Ewgenij Gawrilow and Michael Joswig and various contributors.
|
|
8
|
+
|
|
9
|
+
polymake has been described in [GJ1997]_, [GJ2006]_, [JMP2009]_, [GJRW2010]_,
|
|
10
|
+
[GHJ2016]_, and [AGHJLPR2017]_.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# ****************************************************************************
|
|
15
|
+
# Copyright (C) 2017 Simon King <simon.king@uni-jena.de>
|
|
16
|
+
#
|
|
17
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
18
|
+
#
|
|
19
|
+
# This code is distributed in the hope that it will be useful,
|
|
20
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
21
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
22
|
+
# General Public License for more details.
|
|
23
|
+
#
|
|
24
|
+
# The full text of the GPL is available at:
|
|
25
|
+
#
|
|
26
|
+
# https://www.gnu.org/licenses/
|
|
27
|
+
# ****************************************************************************
|
|
28
|
+
|
|
29
|
+
import os
|
|
30
|
+
import re
|
|
31
|
+
|
|
32
|
+
from .interface import (Interface, InterfaceElement, InterfaceFunctionElement)
|
|
33
|
+
from sage.misc.verbose import get_verbose
|
|
34
|
+
from sage.misc.cachefunc import cached_method
|
|
35
|
+
from sage.interfaces.tab_completion import ExtraTabCompletion
|
|
36
|
+
from sage.structure.richcmp import rich_to_bool
|
|
37
|
+
|
|
38
|
+
_name_pattern = re.compile('SAGE[0-9]+')
|
|
39
|
+
|
|
40
|
+
_available_polymake_answers = {
|
|
41
|
+
0: "returns prompt",
|
|
42
|
+
1: "returns continuation prompt",
|
|
43
|
+
2: "requests interactive input",
|
|
44
|
+
3: "kills computation",
|
|
45
|
+
4: "raises error",
|
|
46
|
+
5: "issues warning",
|
|
47
|
+
6: "shows additional information",
|
|
48
|
+
7: "lost connection",
|
|
49
|
+
8: "fails to respond timely"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class PolymakeError(RuntimeError):
|
|
54
|
+
"""
|
|
55
|
+
Raised if polymake yields an error message.
|
|
56
|
+
|
|
57
|
+
TESTS::
|
|
58
|
+
|
|
59
|
+
sage: polymake.eval('print foo;') # optional - jupymake
|
|
60
|
+
Traceback (most recent call last):
|
|
61
|
+
...
|
|
62
|
+
PolymakeError: Unquoted string "foo" may clash with future reserved word...
|
|
63
|
+
"""
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def polymake_console(command=''):
|
|
68
|
+
"""
|
|
69
|
+
Spawn a new polymake command-line session.
|
|
70
|
+
|
|
71
|
+
EXAMPLES::
|
|
72
|
+
|
|
73
|
+
sage: from sage.interfaces.polymake import polymake_console
|
|
74
|
+
sage: polymake_console() # not tested
|
|
75
|
+
Welcome to polymake version ...
|
|
76
|
+
...
|
|
77
|
+
Ewgenij Gawrilow, Michael Joswig (TU Berlin)
|
|
78
|
+
http://www.polymake.org
|
|
79
|
+
|
|
80
|
+
This is free software licensed under GPL; see the source for copying conditions.
|
|
81
|
+
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
82
|
+
|
|
83
|
+
Press F1 or enter 'help;' for basic instructions.
|
|
84
|
+
|
|
85
|
+
Application polytope currently uses following third-party software packages:
|
|
86
|
+
4ti2, bliss, cdd, latte, libnormaliz, lrs, permlib, ppl, sketch, sympol, threejs, tikz, topcom, tosimplex
|
|
87
|
+
For more details: show_credits;
|
|
88
|
+
polytope >
|
|
89
|
+
"""
|
|
90
|
+
from sage.repl.rich_output.display_manager import get_display_manager
|
|
91
|
+
if not get_display_manager().is_in_terminal():
|
|
92
|
+
raise RuntimeError('Can use the console only in the terminal. Try %%polymake magics instead.')
|
|
93
|
+
os.system(command or os.getenv('SAGE_POLYMAKE_COMMAND') or 'polymake')
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class PolymakeAbstract(ExtraTabCompletion, Interface):
|
|
97
|
+
r"""
|
|
98
|
+
Abstract interface to the polymake interpreter.
|
|
99
|
+
|
|
100
|
+
This class should not be instantiated directly,
|
|
101
|
+
but through its subclasses Polymake (Pexpect interface)
|
|
102
|
+
or PolymakeJuPyMake (JuPyMake interface).
|
|
103
|
+
|
|
104
|
+
EXAMPLES::
|
|
105
|
+
|
|
106
|
+
sage: from sage.interfaces.polymake import PolymakeAbstract, polymake_jupymake
|
|
107
|
+
|
|
108
|
+
We test the verbosity management with very early doctests
|
|
109
|
+
because messages will not be repeated.
|
|
110
|
+
|
|
111
|
+
Testing the JuPyMake interface::
|
|
112
|
+
|
|
113
|
+
sage: isinstance(polymake_jupymake, PolymakeAbstract)
|
|
114
|
+
True
|
|
115
|
+
sage: p = polymake_jupymake.rand_sphere(4, 20, seed=5) # optional - jupymake
|
|
116
|
+
sage: p # optional - jupymake
|
|
117
|
+
Random spherical polytope of dimension 4; seed=5...
|
|
118
|
+
sage: set_verbose(3)
|
|
119
|
+
sage: p.H_VECTOR # optional - jupymake
|
|
120
|
+
polymake: used package ppl
|
|
121
|
+
The Parma Polyhedra Library ...
|
|
122
|
+
1 16 40 16 1
|
|
123
|
+
sage: set_verbose(0)
|
|
124
|
+
sage: p.F_VECTOR # optional - jupymake
|
|
125
|
+
20 94 148 74
|
|
126
|
+
"""
|
|
127
|
+
def __init__(self, seed=None):
|
|
128
|
+
"""
|
|
129
|
+
TESTS::
|
|
130
|
+
|
|
131
|
+
sage: from sage.interfaces.polymake import PolymakeAbstract
|
|
132
|
+
sage: PolymakeAbstract()
|
|
133
|
+
Polymake
|
|
134
|
+
"""
|
|
135
|
+
Interface.__init__(self, "polymake")
|
|
136
|
+
self._seed = seed
|
|
137
|
+
self.__tab_completion = {}
|
|
138
|
+
|
|
139
|
+
@cached_method
|
|
140
|
+
def version(self):
|
|
141
|
+
"""
|
|
142
|
+
Version of the polymake installation.
|
|
143
|
+
|
|
144
|
+
EXAMPLES::
|
|
145
|
+
|
|
146
|
+
sage: polymake.version() # optional - jupymake # random
|
|
147
|
+
'4...'
|
|
148
|
+
"""
|
|
149
|
+
return self.get('$Polymake::Version')
|
|
150
|
+
|
|
151
|
+
# Pickling, etc.
|
|
152
|
+
|
|
153
|
+
def __reduce__(self):
|
|
154
|
+
"""
|
|
155
|
+
EXAMPLES::
|
|
156
|
+
|
|
157
|
+
sage: from sage.interfaces.polymake import polymake
|
|
158
|
+
sage: loads(dumps(polymake)) is polymake
|
|
159
|
+
True
|
|
160
|
+
"""
|
|
161
|
+
return reduce_load_Polymake, ()
|
|
162
|
+
|
|
163
|
+
def _object_class(self):
|
|
164
|
+
"""
|
|
165
|
+
Return the class by which elements in this interface are implemented.
|
|
166
|
+
|
|
167
|
+
TESTS::
|
|
168
|
+
|
|
169
|
+
sage: C = polymake('cube(3)') # indirect doctest # optional - jupymake
|
|
170
|
+
sage: C # optional - jupymake
|
|
171
|
+
cube of dimension 3
|
|
172
|
+
sage: type(C) # optional - jupymake
|
|
173
|
+
<class 'sage.interfaces.polymake.PolymakeElement'>
|
|
174
|
+
"""
|
|
175
|
+
return PolymakeElement
|
|
176
|
+
|
|
177
|
+
def _function_element_class(self):
|
|
178
|
+
"""
|
|
179
|
+
Return the class by which member functions of this interface are implemented.
|
|
180
|
+
|
|
181
|
+
TESTS:
|
|
182
|
+
|
|
183
|
+
We use ellipses in the tests, to make it more robust against future
|
|
184
|
+
changes in polymake::
|
|
185
|
+
|
|
186
|
+
sage: p = polymake.rand_sphere(4, 20, seed=5) # optional - jupymake
|
|
187
|
+
sage: p.get_schedule # optional - jupymake # indirect doctest
|
|
188
|
+
Member function 'get_schedule' of Polymake::polytope::Polytope__Rational object
|
|
189
|
+
sage: p.get_schedule('"F_VECTOR"') # optional - jupymake # random
|
|
190
|
+
CONE_DIM : RAYS | INPUT_RAYS
|
|
191
|
+
precondition : BOUNDED ( POINTED : )
|
|
192
|
+
POINTED :
|
|
193
|
+
N_INPUT_RAYS : INPUT_RAYS
|
|
194
|
+
precondition : N_RAYS | N_INPUT_RAYS ( ppl.convex_hull.primal: FACETS, LINEAR_SPAN : RAYS | INPUT_RAYS )
|
|
195
|
+
sensitivity check for FacetPerm
|
|
196
|
+
ppl.convex_hull.primal: FACETS, LINEAR_SPAN : RAYS | INPUT_RAYS
|
|
197
|
+
INPUT_RAYS_IN_FACETS : INPUT_RAYS, FACETS
|
|
198
|
+
sensitivity check for VertexPerm
|
|
199
|
+
RAYS_IN_FACETS, RAYS, LINEALITY_SPACE : INPUT_RAYS_IN_FACETS, INPUT_RAYS
|
|
200
|
+
GRAPH.ADJACENCY : RAYS_IN_FACETS
|
|
201
|
+
DUAL_GRAPH.ADJACENCY : RAYS_IN_FACETS
|
|
202
|
+
N_EDGES : ADJACENCY ( applied to GRAPH )
|
|
203
|
+
N_EDGES : ADJACENCY ( applied to DUAL_GRAPH )
|
|
204
|
+
precondition : POINTED ( LINEALITY_DIM, LINEALITY_SPACE : )
|
|
205
|
+
LINEALITY_DIM, LINEALITY_SPACE :
|
|
206
|
+
COMBINATORIAL_DIM : CONE_DIM, LINEALITY_DIM
|
|
207
|
+
N_RAYS : RAYS
|
|
208
|
+
N_FACETS : FACETS
|
|
209
|
+
precondition : COMBINATORIAL_DIM ( F_VECTOR : N_FACETS, N_RAYS, GRAPH.N_EDGES, DUAL_GRAPH.N_EDGES, COMBINATORIAL_DIM )
|
|
210
|
+
F_VECTOR : N_FACETS, N_RAYS, GRAPH.N_EDGES, DUAL_GRAPH.N_EDGES, COMBINATORIAL_DIM
|
|
211
|
+
"""
|
|
212
|
+
return PolymakeFunctionElement
|
|
213
|
+
|
|
214
|
+
def function_call(self, function, args=None, kwds=None):
|
|
215
|
+
"""
|
|
216
|
+
EXAMPLES::
|
|
217
|
+
|
|
218
|
+
sage: polymake.rand_sphere(4, 30, seed=15) # optional - jupymake # indirect doctest
|
|
219
|
+
Random spherical polytope of dimension 4; seed=15...
|
|
220
|
+
"""
|
|
221
|
+
args, kwds = self._convert_args_kwds(args, kwds)
|
|
222
|
+
self._check_valid_function_name(function)
|
|
223
|
+
s = self._function_call_string(function,
|
|
224
|
+
[s.name() for s in args],
|
|
225
|
+
['{}=>{}'.format(key, value.name()) for key, value in kwds.items()])
|
|
226
|
+
return self(s)
|
|
227
|
+
|
|
228
|
+
def _function_call_string(self, function, args, kwds):
|
|
229
|
+
"""
|
|
230
|
+
Return the string used to make function calls.
|
|
231
|
+
|
|
232
|
+
EXAMPLES::
|
|
233
|
+
|
|
234
|
+
sage: # optional - jupymake
|
|
235
|
+
sage: polymake._function_call_string('cube', ['2','7','3'], ['group=>1'])
|
|
236
|
+
'cube(2,7,3, group=>1);'
|
|
237
|
+
sage: c = polymake('cube(2,7,3, group=>1)')
|
|
238
|
+
sage: c.VERTICES
|
|
239
|
+
1 3 3
|
|
240
|
+
1 7 3
|
|
241
|
+
1 3 7
|
|
242
|
+
1 7 7
|
|
243
|
+
sage: c.GROUP
|
|
244
|
+
full combinatorial group
|
|
245
|
+
"""
|
|
246
|
+
if kwds:
|
|
247
|
+
if args:
|
|
248
|
+
call_str = "{}({}, {});".format(function, ",".join(list(args)), ",".join(list(kwds)))
|
|
249
|
+
return call_str
|
|
250
|
+
return "{}({});".format(function, ",".join(list(kwds)))
|
|
251
|
+
return "{}({});".format(function, ",".join(list(args)))
|
|
252
|
+
|
|
253
|
+
def _coerce_impl(self, x, use_special=True):
|
|
254
|
+
"""
|
|
255
|
+
Implementation of coercion.
|
|
256
|
+
|
|
257
|
+
TESTS:
|
|
258
|
+
|
|
259
|
+
Test that dictionaries are converted to hashes::
|
|
260
|
+
|
|
261
|
+
sage: h = polymake({'"a"': 1, '"b"': 2}) # optional - jupymake
|
|
262
|
+
sage: h # optional - jupymake
|
|
263
|
+
HASH(0x...)
|
|
264
|
+
sage: h['"a"'] # optional - jupymake
|
|
265
|
+
1
|
|
266
|
+
"""
|
|
267
|
+
if isinstance(x, dict):
|
|
268
|
+
# Convert dictionaries to hashes.
|
|
269
|
+
# This is an adaptation of the list/tuple code from Interface._coerce_impl
|
|
270
|
+
A = []
|
|
271
|
+
z = {}
|
|
272
|
+
cls = self._object_class()
|
|
273
|
+
|
|
274
|
+
def convert(y):
|
|
275
|
+
return y if isinstance(y, cls) else self(y)
|
|
276
|
+
|
|
277
|
+
for k, v in x.items():
|
|
278
|
+
k = convert(k)
|
|
279
|
+
v = convert(v)
|
|
280
|
+
z[k] = v
|
|
281
|
+
A.append(f"{k.name()}=>{v.name()}")
|
|
282
|
+
r = self.new("{" + ",".join(A) + "}")
|
|
283
|
+
|
|
284
|
+
# this to avoid having the entries of the list be garbage collected
|
|
285
|
+
r.__sage_dict = z
|
|
286
|
+
return r
|
|
287
|
+
|
|
288
|
+
import sage.rings.abc
|
|
289
|
+
from sage.rings.integer import Integer
|
|
290
|
+
from sage.rings.rational import Rational
|
|
291
|
+
from sage.rings.real_double import RDF
|
|
292
|
+
|
|
293
|
+
def to_str(x):
|
|
294
|
+
if isinstance(x, list):
|
|
295
|
+
s = '['
|
|
296
|
+
for y in x:
|
|
297
|
+
s += to_str(y) + ', '
|
|
298
|
+
s += ']'
|
|
299
|
+
return s
|
|
300
|
+
if isinstance(x, (Integer, Rational, int)):
|
|
301
|
+
return '{}'.format(x)
|
|
302
|
+
parent = None
|
|
303
|
+
try:
|
|
304
|
+
parent = x.parent()
|
|
305
|
+
except AttributeError:
|
|
306
|
+
pass
|
|
307
|
+
|
|
308
|
+
if isinstance(parent, sage.rings.abc.NumberField_quadratic):
|
|
309
|
+
return x._polymake_init_()
|
|
310
|
+
try:
|
|
311
|
+
if x.parent().is_exact():
|
|
312
|
+
# No other exact rings are supported.
|
|
313
|
+
raise NotImplementedError
|
|
314
|
+
except AttributeError:
|
|
315
|
+
pass
|
|
316
|
+
|
|
317
|
+
try:
|
|
318
|
+
x = RDF(x)
|
|
319
|
+
return '{}'.format(x)
|
|
320
|
+
except (TypeError, ValueError):
|
|
321
|
+
pass
|
|
322
|
+
|
|
323
|
+
raise NotImplementedError
|
|
324
|
+
|
|
325
|
+
# Iteratively calling polymake for conversion takes a long time.
|
|
326
|
+
# However, it takes iterated arrays of integers, rationals and floats directly.
|
|
327
|
+
try:
|
|
328
|
+
return self.new(to_str(x))
|
|
329
|
+
except NotImplementedError:
|
|
330
|
+
pass
|
|
331
|
+
|
|
332
|
+
return super()._coerce_impl(x, use_special=use_special)
|
|
333
|
+
|
|
334
|
+
def console(self):
|
|
335
|
+
"""
|
|
336
|
+
Raise an error, pointing to :meth:`~sage.interfaces.interface.Interface.interact` and :func:`polymake_console`.
|
|
337
|
+
|
|
338
|
+
EXAMPLES::
|
|
339
|
+
|
|
340
|
+
sage: polymake.console()
|
|
341
|
+
Traceback (most recent call last):
|
|
342
|
+
...
|
|
343
|
+
NotImplementedError: Please use polymake_console() function or the .interact() method
|
|
344
|
+
"""
|
|
345
|
+
raise NotImplementedError("Please use polymake_console() function or the .interact() method")
|
|
346
|
+
|
|
347
|
+
# Methods concerning interface communication
|
|
348
|
+
|
|
349
|
+
def _install_hints(self):
|
|
350
|
+
"""
|
|
351
|
+
TESTS::
|
|
352
|
+
|
|
353
|
+
sage: print(polymake._install_hints())
|
|
354
|
+
Please install the optional polymake package for sage
|
|
355
|
+
or install polymake system-wide
|
|
356
|
+
(use the shell command 'sage --info polymake' for more information)
|
|
357
|
+
"""
|
|
358
|
+
return "Please install the optional polymake package for sage" + os.linesep + "or install polymake system-wide" + os.linesep + "(use the shell command 'sage --info polymake' for more information)"
|
|
359
|
+
|
|
360
|
+
def _start(self):
|
|
361
|
+
"""
|
|
362
|
+
Start the polymake interface in the application "polytope".
|
|
363
|
+
|
|
364
|
+
.. NOTE::
|
|
365
|
+
|
|
366
|
+
There should be no need to call this explicitly.
|
|
367
|
+
|
|
368
|
+
TESTS::
|
|
369
|
+
|
|
370
|
+
sage: polymake._start() # optional - jupymake
|
|
371
|
+
|
|
372
|
+
Since 'normal_fan' is not defined in the polymake application 'polytope',
|
|
373
|
+
we now get
|
|
374
|
+
::
|
|
375
|
+
|
|
376
|
+
sage: 'normal_fan' in dir(polymake) # optional - jupymake
|
|
377
|
+
False
|
|
378
|
+
"""
|
|
379
|
+
self.application("polytope")
|
|
380
|
+
self.eval('use Scalar::Util qw(reftype);')
|
|
381
|
+
self.eval('use Scalar::Util qw(blessed);')
|
|
382
|
+
|
|
383
|
+
def _assign_symbol(self):
|
|
384
|
+
"""
|
|
385
|
+
TESTS::
|
|
386
|
+
|
|
387
|
+
sage: polymake._assign_symbol()
|
|
388
|
+
'='
|
|
389
|
+
"""
|
|
390
|
+
return "="
|
|
391
|
+
|
|
392
|
+
def _equality_symbol(self):
|
|
393
|
+
"""
|
|
394
|
+
TESTS::
|
|
395
|
+
|
|
396
|
+
sage: polymake._equality_symbol()
|
|
397
|
+
'=='
|
|
398
|
+
"""
|
|
399
|
+
return "=="
|
|
400
|
+
|
|
401
|
+
def _read_in_file_command(self, filename):
|
|
402
|
+
r"""
|
|
403
|
+
TESTS::
|
|
404
|
+
|
|
405
|
+
sage: polymake._read_in_file_command('foobar')
|
|
406
|
+
'eval read_file "foobar";\n'
|
|
407
|
+
|
|
408
|
+
Force use of file::
|
|
409
|
+
|
|
410
|
+
sage: L = polymake([42] * 400) # optional - jupymake
|
|
411
|
+
sage: len(L) # optional - jupymake
|
|
412
|
+
400
|
|
413
|
+
|
|
414
|
+
Just below standard file cutoff of 1024::
|
|
415
|
+
|
|
416
|
+
sage: L = polymake([42] * 84) # optional - jupymake
|
|
417
|
+
sage: len(L) # optional - jupymake
|
|
418
|
+
84
|
|
419
|
+
"""
|
|
420
|
+
return 'eval read_file "{}";\n'.format(filename)
|
|
421
|
+
|
|
422
|
+
def _next_var_name(self):
|
|
423
|
+
r"""
|
|
424
|
+
Return the next unused variable name.
|
|
425
|
+
|
|
426
|
+
TESTS::
|
|
427
|
+
|
|
428
|
+
sage: print(polymake._next_var_name())
|
|
429
|
+
SAGE...
|
|
430
|
+
"""
|
|
431
|
+
if self._available_vars:
|
|
432
|
+
return self._available_vars.pop(0)
|
|
433
|
+
try:
|
|
434
|
+
self.__seq += 1
|
|
435
|
+
except AttributeError:
|
|
436
|
+
self.__seq = 0
|
|
437
|
+
return r'SAGE{}'.format(self.__seq)
|
|
438
|
+
|
|
439
|
+
def clear(self, var):
|
|
440
|
+
r"""
|
|
441
|
+
Clear the variable named ``var``.
|
|
442
|
+
|
|
443
|
+
.. NOTE::
|
|
444
|
+
|
|
445
|
+
This is implicitly done when deleting an element in the interface.
|
|
446
|
+
|
|
447
|
+
TESTS::
|
|
448
|
+
|
|
449
|
+
sage: # optional - jupymake
|
|
450
|
+
sage: c = polymake.cube(15)
|
|
451
|
+
sage: polymake._available_vars = []
|
|
452
|
+
sage: old = c._name
|
|
453
|
+
sage: del c
|
|
454
|
+
sage: len(polymake._available_vars)
|
|
455
|
+
1
|
|
456
|
+
sage: polymake._next_var_name() in old
|
|
457
|
+
True
|
|
458
|
+
"""
|
|
459
|
+
self._available_vars.append(_name_pattern.search(var).group())
|
|
460
|
+
|
|
461
|
+
def _create(self, value, name=None):
|
|
462
|
+
"""
|
|
463
|
+
Assign a value to a name in the polymake interface.
|
|
464
|
+
|
|
465
|
+
INPUT:
|
|
466
|
+
|
|
467
|
+
- ``value`` -- string; Polymake command (or value) whose result
|
|
468
|
+
is to be assigned to a variable
|
|
469
|
+
- ``name`` -- (optional) string; if given, the new variable has this
|
|
470
|
+
name; otherwise, the name is automatically generated
|
|
471
|
+
|
|
472
|
+
RETURN:
|
|
473
|
+
|
|
474
|
+
The command by which the assigned value can now be retrieved.
|
|
475
|
+
|
|
476
|
+
.. NOTE::
|
|
477
|
+
|
|
478
|
+
In order to overcome problems with the perl programming language,
|
|
479
|
+
we store *all* data as arrays. If the given value is an array
|
|
480
|
+
of length different from one, then the new variable contains that
|
|
481
|
+
array. Otherwise, the new variable is an array of length one whose
|
|
482
|
+
only entry is the given value, which has to be a scalar (which
|
|
483
|
+
also includes Perl references). In other words, perl hashes
|
|
484
|
+
are not suitable.
|
|
485
|
+
|
|
486
|
+
EXAMPLES::
|
|
487
|
+
|
|
488
|
+
sage: # optional - jupymake
|
|
489
|
+
sage: polymake._create("('foo', 'bar')", name='my_array')
|
|
490
|
+
'@my_array'
|
|
491
|
+
sage: print(polymake.eval('print join(", ", @my_array);'))
|
|
492
|
+
foo, bar
|
|
493
|
+
sage: polymake._create('"foobar"', name='my_string')
|
|
494
|
+
'$my_string[0]'
|
|
495
|
+
sage: print(polymake.eval('print $my_string[0];'))
|
|
496
|
+
foobar
|
|
497
|
+
"""
|
|
498
|
+
name = self._next_var_name() if name is None else name
|
|
499
|
+
self.set(name, value)
|
|
500
|
+
# If value is a list, then @name is now equal to that list.
|
|
501
|
+
# Otherwise, value is obtained by $name[0]. So, we modify
|
|
502
|
+
# the name returned by _create so that it can be used to
|
|
503
|
+
# access the wrapped value.
|
|
504
|
+
if self.eval('print scalar @{};'.format(name)).strip() == '1':
|
|
505
|
+
return '$'+name+'[0]'
|
|
506
|
+
return '@'+name
|
|
507
|
+
|
|
508
|
+
def set(self, var, value):
|
|
509
|
+
"""
|
|
510
|
+
Set the variable var to the given value.
|
|
511
|
+
|
|
512
|
+
Eventually, ``var`` is a reference to ``value``.
|
|
513
|
+
|
|
514
|
+
.. WARNING::
|
|
515
|
+
|
|
516
|
+
This method, although it doesn't start with an underscore, is
|
|
517
|
+
an internal method and not part of the interface. So, please do
|
|
518
|
+
not try to call it explicitly. Instead, use the polymake interface
|
|
519
|
+
as shown in the examples.
|
|
520
|
+
|
|
521
|
+
REMARK:
|
|
522
|
+
|
|
523
|
+
Polymake's user language is Perl. In Perl, if one wants to assign
|
|
524
|
+
the return value of a function to a variable, the syntax to do so
|
|
525
|
+
depends on the type of the return value. While this is fine in
|
|
526
|
+
compiled code, it seems quite awkward in user interaction.
|
|
527
|
+
|
|
528
|
+
To make this polymake pexpect interface a bit more user friendly,
|
|
529
|
+
we treat *all* variables as arrays. A scalar value (most typically
|
|
530
|
+
a reference) is thus interpreted as the only item in an array of
|
|
531
|
+
length one. It is, of course, possible to use the interface without
|
|
532
|
+
knowing these details.
|
|
533
|
+
|
|
534
|
+
EXAMPLES::
|
|
535
|
+
|
|
536
|
+
sage: c = polymake('cube(3)') # optional - jupymake # indirect doctest
|
|
537
|
+
sage: d = polymake.cube(3) # optional - jupymake
|
|
538
|
+
|
|
539
|
+
Equality is, for "big" objects such as polytopes, comparison by
|
|
540
|
+
identity::
|
|
541
|
+
|
|
542
|
+
sage: c == d # optional - jupymake
|
|
543
|
+
False
|
|
544
|
+
|
|
545
|
+
However, the list of vertices is equal::
|
|
546
|
+
|
|
547
|
+
sage: c.VERTICES == d.VERTICES # optional - jupymake
|
|
548
|
+
True
|
|
549
|
+
|
|
550
|
+
TESTS:
|
|
551
|
+
|
|
552
|
+
The following shows how polymake variables are wrapped in our interface.
|
|
553
|
+
It should, however, **never** be needed to do the following
|
|
554
|
+
*explicitly*::
|
|
555
|
+
|
|
556
|
+
sage: polymake.set('myvar', 'cube(3)') # optional - jupymake
|
|
557
|
+
sage: polymake.get('$myvar[0]') # optional - jupymake
|
|
558
|
+
'Polymake::polytope::Polytope__Rational=ARRAY(...)'
|
|
559
|
+
|
|
560
|
+
The following tests against :issue:`22658`::
|
|
561
|
+
|
|
562
|
+
sage: P = polymake.new_object("Polytope", FACETS=[[12, -2, -3, -5, -8, -13, -21, -34, -55], # optional - jupymake
|
|
563
|
+
....: [0, 1, 0, 0, 0, 0, 0, 0, 0],
|
|
564
|
+
....: [0, 0, 0, 0, 0, 0, 0, 0, 1],
|
|
565
|
+
....: [0, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
566
|
+
....: [0, 0, 0, 0, 0, 0, 1, 0, 0],
|
|
567
|
+
....: [0, 0, 0, 0, 0, 1, 0, 0, 0],
|
|
568
|
+
....: [0, 0, 0, 0, 1, 0, 0, 0, 0],
|
|
569
|
+
....: [0, 0, 0, 1, 0, 0, 0, 0, 0],
|
|
570
|
+
....: [0, 0, 1, 0, 0, 0, 0, 0, 0]])
|
|
571
|
+
sage: P.VERTICES # optional - jupymake
|
|
572
|
+
1 6 0 0 0 0 0 0 0
|
|
573
|
+
1 0 4 0 0 0 0 0 0
|
|
574
|
+
1 0 0 0 0 0 0 0 0
|
|
575
|
+
1 0 0 12/5 0 0 0 0 0
|
|
576
|
+
1 0 0 0 0 0 0 0 12/55
|
|
577
|
+
1 0 0 0 0 0 0 6/17 0
|
|
578
|
+
1 0 0 0 0 0 4/7 0 0
|
|
579
|
+
1 0 0 0 0 12/13 0 0 0
|
|
580
|
+
1 0 0 0 3/2 0 0 0 0
|
|
581
|
+
sage: P.F_VECTOR # optional - jupymake
|
|
582
|
+
9 36 84 126 126 84 36 9
|
|
583
|
+
"""
|
|
584
|
+
if isinstance(value, str):
|
|
585
|
+
value = value.strip().rstrip(';').strip()
|
|
586
|
+
cmd = "@{}{}({});".format(var, self._assign_symbol(), value)
|
|
587
|
+
self.eval(cmd)
|
|
588
|
+
|
|
589
|
+
def get(self, cmd):
|
|
590
|
+
"""
|
|
591
|
+
Return the string representation of an object in the polymake interface.
|
|
592
|
+
|
|
593
|
+
EXAMPLES::
|
|
594
|
+
|
|
595
|
+
sage: polymake.get('cube(3)') # optional - jupymake
|
|
596
|
+
'Polymake::polytope::Polytope__Rational=ARRAY(...)'
|
|
597
|
+
|
|
598
|
+
Note that the above string representation is what polymake provides.
|
|
599
|
+
In our interface, we use what polymake calls a "description"::
|
|
600
|
+
|
|
601
|
+
sage: polymake('cube(3)') # optional - jupymake
|
|
602
|
+
cube of dimension 3
|
|
603
|
+
"""
|
|
604
|
+
return self.eval("print {};".format(cmd)).strip()
|
|
605
|
+
|
|
606
|
+
def help(self, topic, pager=True):
|
|
607
|
+
"""
|
|
608
|
+
Displays polymake's help on a given topic, as a string.
|
|
609
|
+
|
|
610
|
+
INPUT:
|
|
611
|
+
|
|
612
|
+
- ``topic`` -- string
|
|
613
|
+
- ``pager`` -- boolean (default: ``True``); when ``True``, display
|
|
614
|
+
help, otherwise return as a string
|
|
615
|
+
|
|
616
|
+
EXAMPLES::
|
|
617
|
+
|
|
618
|
+
sage: print(polymake.help('Polytope', pager=False)) # optional - jupymake # random
|
|
619
|
+
objects/Polytope:
|
|
620
|
+
Not necessarily bounded or unbounded polyhedron.
|
|
621
|
+
Nonetheless, the name "Polytope" is used for two reasons:
|
|
622
|
+
Firstly, combinatorially we always deal with polytopes; see the description of VERTICES_IN_FACETS for details.
|
|
623
|
+
The second reason is historical.
|
|
624
|
+
We use homogeneous coordinates, which is why Polytope is derived from Cone.
|
|
625
|
+
Note that a pointed polyhedron is projectively equivalent to a polytope.
|
|
626
|
+
Scalar is the numeric data type used for the coordinates.
|
|
627
|
+
|
|
628
|
+
In some cases, polymake expects user interaction to choose from
|
|
629
|
+
different available help topics. In these cases, a warning is given,
|
|
630
|
+
and the available help topics are displayed resp. printed, without
|
|
631
|
+
user interaction::
|
|
632
|
+
|
|
633
|
+
sage: polymake.help('TRIANGULATION') # optional - jupymake # random
|
|
634
|
+
doctest:warning
|
|
635
|
+
...
|
|
636
|
+
UserWarning: Polymake expects user interaction. We abort and return the options that Polymake provides.
|
|
637
|
+
There are 5 help topics matching 'TRIANGULATION':
|
|
638
|
+
1: objects/Visualization/Visual::Polytope/methods/TRIANGULATION
|
|
639
|
+
2: objects/Visualization/Visual::PointConfiguration/methods/TRIANGULATION
|
|
640
|
+
3: objects/Cone/properties/Triangulation and volume/TRIANGULATION
|
|
641
|
+
4: objects/PointConfiguration/properties/Triangulation and volume/TRIANGULATION
|
|
642
|
+
5: objects/Polytope/properties/Triangulation and volume/TRIANGULATION
|
|
643
|
+
|
|
644
|
+
If an unknown help topic is requested, a :exc:`PolymakeError`
|
|
645
|
+
results::
|
|
646
|
+
|
|
647
|
+
sage: polymake.help('Triangulation') # optional - jupymake
|
|
648
|
+
Traceback (most recent call last):
|
|
649
|
+
...
|
|
650
|
+
PolymakeError: unknown help topic 'Triangulation'
|
|
651
|
+
"""
|
|
652
|
+
H = self.eval('help("{}");\n'.format(topic))
|
|
653
|
+
if not H:
|
|
654
|
+
raise PolymakeError("unknown help topic '{}'".format(topic))
|
|
655
|
+
if pager:
|
|
656
|
+
from IPython.core.page import page
|
|
657
|
+
page(H, start=0)
|
|
658
|
+
else:
|
|
659
|
+
return H
|
|
660
|
+
|
|
661
|
+
def _tab_completion(self):
|
|
662
|
+
r"""
|
|
663
|
+
Return a list of polymake function names.
|
|
664
|
+
|
|
665
|
+
..NOTE::
|
|
666
|
+
|
|
667
|
+
- The list of functions depends on the current application. The
|
|
668
|
+
result is cached, of course separately for each application.
|
|
669
|
+
- It is generally not the case that all the returned function
|
|
670
|
+
names can actually successfully be called.
|
|
671
|
+
|
|
672
|
+
TESTS::
|
|
673
|
+
|
|
674
|
+
sage: polymake.application('fan') # optional - jupymake
|
|
675
|
+
sage: 'normal_fan' in dir(polymake) # optional - jupymake # indirect doctest
|
|
676
|
+
True
|
|
677
|
+
sage: polymake.application('polytope') # optional - jupymake
|
|
678
|
+
|
|
679
|
+
Since ``'normal_fan'`` is not defined in the polymake application
|
|
680
|
+
``'polytope'``, we now get::
|
|
681
|
+
|
|
682
|
+
sage: 'normal_fan' in dir(polymake) # optional - jupymake
|
|
683
|
+
False
|
|
684
|
+
|
|
685
|
+
Global functions from ``'core'`` are available::
|
|
686
|
+
|
|
687
|
+
sage: 'show_credits' in dir(polymake) # optional - jupymake
|
|
688
|
+
True
|
|
689
|
+
|
|
690
|
+
Global functions from ``'common'`` are available::
|
|
691
|
+
|
|
692
|
+
sage: 'lex_ordered' in dir(polymake) # optional - jupymake
|
|
693
|
+
True
|
|
694
|
+
"""
|
|
695
|
+
if not self.is_running():
|
|
696
|
+
self._start()
|
|
697
|
+
try:
|
|
698
|
+
return self.__tab_completion[self._application]
|
|
699
|
+
except KeyError:
|
|
700
|
+
pass
|
|
701
|
+
s = self.eval("apropos '';").split('\n')
|
|
702
|
+
out = []
|
|
703
|
+
for name in s:
|
|
704
|
+
if (name.startswith("/common/functions/")
|
|
705
|
+
or name.startswith("/core/functions")
|
|
706
|
+
or name.startswith("/" + self._application + "/functions/")):
|
|
707
|
+
out.append(name.split("/")[-1])
|
|
708
|
+
self.__tab_completion[self._application] = sorted(out)
|
|
709
|
+
return self.__tab_completion[self._application]
|
|
710
|
+
|
|
711
|
+
# Polymake specific methods
|
|
712
|
+
|
|
713
|
+
def application(self, app):
|
|
714
|
+
"""
|
|
715
|
+
Change to a given polymake application.
|
|
716
|
+
|
|
717
|
+
INPUT:
|
|
718
|
+
|
|
719
|
+
- ``app`` -- string; one of ``'common'``, ``'fulton'``, ``'group'``,
|
|
720
|
+
``'matroid'``, ``'topaz'``, ``'fan'``, ``'graph'``, ``'ideal'``,
|
|
721
|
+
``'polytope'``, ``'tropical'``
|
|
722
|
+
|
|
723
|
+
EXAMPLES:
|
|
724
|
+
|
|
725
|
+
We expose a computation that uses both the 'polytope' and the 'fan'
|
|
726
|
+
application of polymake. Let us start by defining a polytope `q` in
|
|
727
|
+
terms of inequalities. Polymake knows to compute the f- and h-vector
|
|
728
|
+
and finds that the polytope is very ample::
|
|
729
|
+
|
|
730
|
+
sage: # optional - jupymake
|
|
731
|
+
sage: q = polymake.new_object("Polytope", INEQUALITIES=[[5,-4,0,1],[-3,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1],[1,0,-1,0],[3,-1,0,0]])
|
|
732
|
+
sage: q.H_VECTOR
|
|
733
|
+
1 5 5 1
|
|
734
|
+
sage: q.F_VECTOR
|
|
735
|
+
8 14 8
|
|
736
|
+
sage: q.VERY_AMPLE
|
|
737
|
+
true
|
|
738
|
+
|
|
739
|
+
In the application 'fan', polymake can now compute the normal fan
|
|
740
|
+
of `q` and its (primitive) rays::
|
|
741
|
+
|
|
742
|
+
sage: # optional - jupymake
|
|
743
|
+
sage: polymake.application('fan')
|
|
744
|
+
sage: g = q.normal_fan()
|
|
745
|
+
sage: g.RAYS
|
|
746
|
+
-1 0 1/4
|
|
747
|
+
0 -1 1/4
|
|
748
|
+
1 0 0
|
|
749
|
+
1 1 -1/4
|
|
750
|
+
0 1 0
|
|
751
|
+
0 0 -1
|
|
752
|
+
0 -1 0
|
|
753
|
+
-1 0 0
|
|
754
|
+
sage: g.RAYS.primitive()
|
|
755
|
+
-4 0 1
|
|
756
|
+
0 -4 1
|
|
757
|
+
1 0 0
|
|
758
|
+
4 4 -1
|
|
759
|
+
0 1 0
|
|
760
|
+
0 0 -1
|
|
761
|
+
0 -1 0
|
|
762
|
+
-1 0 0
|
|
763
|
+
|
|
764
|
+
Note that the list of functions available by tab completion depends
|
|
765
|
+
on the application.
|
|
766
|
+
|
|
767
|
+
TESTS:
|
|
768
|
+
|
|
769
|
+
Since 'trop_witness' is not defined in the polymake application 'polytope'
|
|
770
|
+
but only in 'tropical', the following shows the effect of changing
|
|
771
|
+
the application. ::
|
|
772
|
+
|
|
773
|
+
sage: # optional - jupymake
|
|
774
|
+
sage: polymake.application('polytope')
|
|
775
|
+
sage: 'trop_witness' in dir(polymake)
|
|
776
|
+
False
|
|
777
|
+
sage: polymake.application('tropical')
|
|
778
|
+
sage: 'trop_witness' in dir(polymake)
|
|
779
|
+
True
|
|
780
|
+
sage: polymake.application('polytope')
|
|
781
|
+
sage: 'trop_witness' in dir(polymake)
|
|
782
|
+
False
|
|
783
|
+
|
|
784
|
+
For completeness, we show what happens when asking for an application
|
|
785
|
+
that doesn't exist::
|
|
786
|
+
|
|
787
|
+
sage: polymake.application('killerapp') # optional - jupymake
|
|
788
|
+
Traceback (most recent call last):
|
|
789
|
+
...
|
|
790
|
+
ValueError: Unknown polymake application 'killerapp'
|
|
791
|
+
|
|
792
|
+
Of course, a different error results when we send an explicit
|
|
793
|
+
command in polymake to change to an unknown application::
|
|
794
|
+
|
|
795
|
+
sage: polymake.eval('application "killerapp";') # optional - jupymake
|
|
796
|
+
Traceback (most recent call last):
|
|
797
|
+
...
|
|
798
|
+
PolymakeError: Unknown application killerapp
|
|
799
|
+
"""
|
|
800
|
+
if app not in ["common", "fulton", "group", "matroid", "topaz", "fan", "graph", "ideal", "polytope", "tropical"]:
|
|
801
|
+
raise ValueError("Unknown polymake application '{}'".format(app))
|
|
802
|
+
self._application = app
|
|
803
|
+
self.eval('application "{}";'.format(app))
|
|
804
|
+
|
|
805
|
+
def new_object(self, name, *args, **kwds):
|
|
806
|
+
"""
|
|
807
|
+
Return a new instance of a given polymake type, with given positional or named arguments.
|
|
808
|
+
|
|
809
|
+
INPUT:
|
|
810
|
+
|
|
811
|
+
- ``name`` of a polymake class (potentially templated), as string.
|
|
812
|
+
- further positional or named arguments, to be passed to the constructor.
|
|
813
|
+
|
|
814
|
+
EXAMPLES::
|
|
815
|
+
|
|
816
|
+
sage: # optional - jupymake
|
|
817
|
+
sage: q = polymake.new_object("Polytope<Rational>", INEQUALITIES=[[4,-4,0,1],[-4,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1]])
|
|
818
|
+
sage: q.N_VERTICES
|
|
819
|
+
4
|
|
820
|
+
sage: q.BOUNDED
|
|
821
|
+
true
|
|
822
|
+
sage: q.VERTICES
|
|
823
|
+
1 2 0 4
|
|
824
|
+
1 3 0 8
|
|
825
|
+
1 2 1 8
|
|
826
|
+
1 3 1 8
|
|
827
|
+
sage: q.full_typename()
|
|
828
|
+
'Polytope<Rational>'
|
|
829
|
+
"""
|
|
830
|
+
try:
|
|
831
|
+
f = self.__new[name]
|
|
832
|
+
except AttributeError:
|
|
833
|
+
self.__new = {}
|
|
834
|
+
f = self.__new[name] = self._function_class()(self, "new {}".format(name))
|
|
835
|
+
except KeyError:
|
|
836
|
+
f = self.__new[name] = self._function_class()(self, "new {}".format(name))
|
|
837
|
+
return f(*args, **kwds)
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
# --------
|
|
841
|
+
# Elements
|
|
842
|
+
# --------
|
|
843
|
+
|
|
844
|
+
class PolymakeElement(ExtraTabCompletion, InterfaceElement):
|
|
845
|
+
"""
|
|
846
|
+
Elements in the polymake interface.
|
|
847
|
+
|
|
848
|
+
EXAMPLES:
|
|
849
|
+
|
|
850
|
+
We support all "big" polymake types, Perl arrays of length
|
|
851
|
+
different from one, and Perl scalars::
|
|
852
|
+
|
|
853
|
+
sage: p = polymake.rand_sphere(4, 20, seed=5) # optional - jupymake
|
|
854
|
+
sage: p.typename() # optional - jupymake
|
|
855
|
+
'Polytope'
|
|
856
|
+
sage: p # optional - jupymake
|
|
857
|
+
Random spherical polytope of dimension 4; seed=5...
|
|
858
|
+
|
|
859
|
+
Now, one can work with that element in Python syntax, for example::
|
|
860
|
+
|
|
861
|
+
sage: p.VERTICES[2][2] # optional - jupymake
|
|
862
|
+
1450479926727001/2251799813685248
|
|
863
|
+
"""
|
|
864
|
+
def _repr_(self):
|
|
865
|
+
"""
|
|
866
|
+
String representation of polymake elements.
|
|
867
|
+
|
|
868
|
+
EXAMPLES:
|
|
869
|
+
|
|
870
|
+
In the case of a "big" object, if polymake provides a description
|
|
871
|
+
of the object that is not longer than single line, it is used for
|
|
872
|
+
printing::
|
|
873
|
+
|
|
874
|
+
sage: # optional - jupymake
|
|
875
|
+
sage: p = polymake.rand_sphere(3, 12, seed=15)
|
|
876
|
+
sage: p
|
|
877
|
+
Random spherical polytope of dimension 3; seed=15...
|
|
878
|
+
sage: c = polymake.cube(4)
|
|
879
|
+
sage: c
|
|
880
|
+
cube of dimension 4
|
|
881
|
+
|
|
882
|
+
We use the print representation of scalars to display scalars::
|
|
883
|
+
|
|
884
|
+
sage: p.N_VERTICES # optional - jupymake
|
|
885
|
+
12
|
|
886
|
+
|
|
887
|
+
The items of a Perl arrays are shown separated by commas::
|
|
888
|
+
|
|
889
|
+
sage: p.get_member('list_properties') # optional - jupymake # random
|
|
890
|
+
POINTS, CONE_AMBIENT_DIM, BOUNDED, FEASIBLE, N_POINTS, POINTED,
|
|
891
|
+
CONE_DIM, FULL_DIM, LINEALITY_DIM, LINEALITY_SPACE,
|
|
892
|
+
COMBINATORIAL_DIM, AFFINE_HULL, VERTICES, N_VERTICES
|
|
893
|
+
|
|
894
|
+
We chose to print rule chains explicitly, so that the user doesn't
|
|
895
|
+
need to know how to list the rules using polymake commands::
|
|
896
|
+
|
|
897
|
+
sage: r = p.get_schedule('"H_VECTOR"') # optional - jupymake
|
|
898
|
+
sage: r # optional - jupymake # random
|
|
899
|
+
precondition : N_RAYS | N_INPUT_RAYS ( ppl.convex_hull.primal: FACETS, LINEAR_SPAN : RAYS | INPUT_RAYS )
|
|
900
|
+
sensitivity check for FacetPerm
|
|
901
|
+
ppl.convex_hull.primal: FACETS, LINEAR_SPAN : RAYS | INPUT_RAYS
|
|
902
|
+
RAYS_IN_FACETS : RAYS, FACETS
|
|
903
|
+
SIMPLICIAL : COMBINATORIAL_DIM, RAYS_IN_FACETS
|
|
904
|
+
N_FACETS : FACETS
|
|
905
|
+
precondition : COMBINATORIAL_DIM ( F_VECTOR : N_FACETS, N_RAYS, COMBINATORIAL_DIM )
|
|
906
|
+
F_VECTOR : N_FACETS, N_RAYS, COMBINATORIAL_DIM
|
|
907
|
+
precondition : SIMPLICIAL ( H_VECTOR : F_VECTOR )
|
|
908
|
+
H_VECTOR : F_VECTOR
|
|
909
|
+
sage: r.typeof() # optional - jupymake
|
|
910
|
+
('Polymake::Core::Scheduler::RuleChain', 'ARRAY')
|
|
911
|
+
|
|
912
|
+
Similarly, polymake matrices and vectors are explicitly listed::
|
|
913
|
+
|
|
914
|
+
sage: # optional - jupymake
|
|
915
|
+
sage: c.VERTICES.typename()
|
|
916
|
+
'Matrix'
|
|
917
|
+
sage: c.VERTICES[0].typename()
|
|
918
|
+
'Vector'
|
|
919
|
+
sage: c.VERTICES
|
|
920
|
+
1 -1 -1 -1 -1
|
|
921
|
+
1 1 -1 -1 -1
|
|
922
|
+
1 -1 1 -1 -1
|
|
923
|
+
1 1 1 -1 -1
|
|
924
|
+
1 -1 -1 1 -1
|
|
925
|
+
1 1 -1 1 -1
|
|
926
|
+
1 -1 1 1 -1
|
|
927
|
+
1 1 1 1 -1
|
|
928
|
+
1 -1 -1 -1 1
|
|
929
|
+
1 1 -1 -1 1
|
|
930
|
+
1 -1 1 -1 1
|
|
931
|
+
1 1 1 -1 1
|
|
932
|
+
1 -1 -1 1 1
|
|
933
|
+
1 1 -1 1 1
|
|
934
|
+
1 -1 1 1 1
|
|
935
|
+
1 1 1 1 1
|
|
936
|
+
sage: c.VERTICES[0]
|
|
937
|
+
1 -1 -1 -1 -1
|
|
938
|
+
|
|
939
|
+
For other types, we simply use the print representation offered
|
|
940
|
+
by polymake::
|
|
941
|
+
|
|
942
|
+
sage: p.TWO_FACE_SIZES.typename() # optional - jupymake
|
|
943
|
+
'Map'
|
|
944
|
+
sage: p.TWO_FACE_SIZES # optional - jupymake
|
|
945
|
+
{(3 20)}
|
|
946
|
+
"""
|
|
947
|
+
T1, T2 = self.typeof()
|
|
948
|
+
P = self._check_valid()
|
|
949
|
+
name = self._name
|
|
950
|
+
if T1:
|
|
951
|
+
Temp = self.typename()
|
|
952
|
+
if Temp:
|
|
953
|
+
T1 = Temp
|
|
954
|
+
if T1 in ['Matrix', 'Vector']:
|
|
955
|
+
out = P.get(name).strip()
|
|
956
|
+
elif 'RuleChain' in T1:
|
|
957
|
+
out = os.linesep.join(P.get('join("##",{}->list)'.format(name)).split('##'))
|
|
958
|
+
else:
|
|
959
|
+
try:
|
|
960
|
+
out = P.get('{}->description'.format(name)).strip()
|
|
961
|
+
except PolymakeError:
|
|
962
|
+
out = ''
|
|
963
|
+
if os.linesep in out:
|
|
964
|
+
out = ''
|
|
965
|
+
if not out:
|
|
966
|
+
if "Polytope" == T1:
|
|
967
|
+
out = "{}[{}]".format(P.get("{}->type->full_name".format(name)) or "PolymakeElement", _name_pattern.search(name).group())
|
|
968
|
+
elif T1 == '' and T2 == 'ARRAY':
|
|
969
|
+
out = P.eval('print join(", ", @{});'.format(name)).strip()
|
|
970
|
+
elif T1 == '' and T2 == 'HASH':
|
|
971
|
+
out = P.get('%{}'.format(name)).strip()
|
|
972
|
+
elif self._name[0] == '@':
|
|
973
|
+
out = P.eval('print join(", ", {});'.format(name)).strip()
|
|
974
|
+
else:
|
|
975
|
+
out = P.get(name).strip()
|
|
976
|
+
return out
|
|
977
|
+
|
|
978
|
+
def _richcmp_(self, other, op):
|
|
979
|
+
"""
|
|
980
|
+
Comparison of polymake elements.
|
|
981
|
+
|
|
982
|
+
EXAMPLES:
|
|
983
|
+
|
|
984
|
+
The default for comparing equality for polytopes is *identity*::
|
|
985
|
+
|
|
986
|
+
sage: p1 = polymake.rand_sphere(3, 12, seed=15) # optional - jupymake
|
|
987
|
+
sage: p2 = polymake.rand_sphere(3, 12, seed=15) # optional - jupymake
|
|
988
|
+
sage: p1 == p2 # optional - jupymake
|
|
989
|
+
False
|
|
990
|
+
|
|
991
|
+
However, other data types are compared by equality, not identity::
|
|
992
|
+
|
|
993
|
+
sage: p1.VERTICES == p2.VERTICES # optional - jupymake
|
|
994
|
+
True
|
|
995
|
+
|
|
996
|
+
A computation applied to a polytope can change the available
|
|
997
|
+
properties, and thus we have
|
|
998
|
+
::
|
|
999
|
+
|
|
1000
|
+
sage: p1.get_member('list_properties') == p2.get_member('list_properties') # optional - jupymake
|
|
1001
|
+
True
|
|
1002
|
+
sage: p1.F_VECTOR # optional - jupymake
|
|
1003
|
+
12 30 20
|
|
1004
|
+
sage: p1.get_member('list_properties') == p2.get_member('list_properties') # optional - jupymake
|
|
1005
|
+
False
|
|
1006
|
+
"""
|
|
1007
|
+
P = self._check_valid()
|
|
1008
|
+
if P.eval("print {} {} {};".format(self.name(), P._equality_symbol(), other.name())).strip() == P._true_symbol():
|
|
1009
|
+
return rich_to_bool(op, 0)
|
|
1010
|
+
if P.eval("print {} {} {};".format(self.name(), P._lessthan_symbol(), other.name())).strip() == P._true_symbol():
|
|
1011
|
+
return rich_to_bool(op, -1)
|
|
1012
|
+
if P.eval("print {} {} {};".format(self.name(), P._greaterthan_symbol(), other.name())).strip() == P._true_symbol():
|
|
1013
|
+
return rich_to_bool(op, 1)
|
|
1014
|
+
return NotImplemented
|
|
1015
|
+
|
|
1016
|
+
def __bool__(self):
|
|
1017
|
+
"""
|
|
1018
|
+
Return whether this polymake element is equal to ``True``.
|
|
1019
|
+
|
|
1020
|
+
EXAMPLES::
|
|
1021
|
+
|
|
1022
|
+
sage: from sage.interfaces.polymake import polymake
|
|
1023
|
+
sage: bool(polymake(0)) # optional - jupymake
|
|
1024
|
+
False
|
|
1025
|
+
sage: bool(polymake(1)) # optional - jupymake
|
|
1026
|
+
True
|
|
1027
|
+
"""
|
|
1028
|
+
P = self._check_valid()
|
|
1029
|
+
t = P._true_symbol()
|
|
1030
|
+
cmd = '{} {} {};'.format(self._name, P._equality_symbol(), t)
|
|
1031
|
+
return P.get(cmd) == t
|
|
1032
|
+
|
|
1033
|
+
def known_properties(self):
|
|
1034
|
+
"""
|
|
1035
|
+
List the names of properties that have been computed so far on this element.
|
|
1036
|
+
|
|
1037
|
+
.. NOTE::
|
|
1038
|
+
|
|
1039
|
+
This is in many cases equivalent to use polymake's
|
|
1040
|
+
``list_properties``, which returns a blank separated string
|
|
1041
|
+
representation of the list of properties. However, on some
|
|
1042
|
+
elements, ``list_properties`` would simply result in an error.
|
|
1043
|
+
|
|
1044
|
+
EXAMPLES::
|
|
1045
|
+
|
|
1046
|
+
sage: c = polymake.cube(4) # optional - jupymake
|
|
1047
|
+
sage: c.known_properties() # optional - jupymake
|
|
1048
|
+
['AFFINE_HULL',
|
|
1049
|
+
'BOUNDED',
|
|
1050
|
+
'CONE_AMBIENT_DIM',
|
|
1051
|
+
'CONE_DIM',
|
|
1052
|
+
...
|
|
1053
|
+
'VERTICES_IN_FACETS']
|
|
1054
|
+
sage: c.list_properties() # optional - jupymake
|
|
1055
|
+
CONE_AMBIENT_DIM, CONE_DIM, FACETS, AFFINE_HULL, VERTICES_IN_FACETS,
|
|
1056
|
+
BOUNDED...
|
|
1057
|
+
|
|
1058
|
+
A computation can change the list of known properties::
|
|
1059
|
+
|
|
1060
|
+
sage: c.F_VECTOR # optional - jupymake
|
|
1061
|
+
16 32 24 8
|
|
1062
|
+
sage: c.known_properties() # optional - jupymake
|
|
1063
|
+
['AFFINE_HULL',
|
|
1064
|
+
'BOUNDED',
|
|
1065
|
+
'COMBINATORIAL_DIM',
|
|
1066
|
+
'CONE_AMBIENT_DIM',
|
|
1067
|
+
'CONE_DIM',
|
|
1068
|
+
...
|
|
1069
|
+
'VERTICES_IN_FACETS']
|
|
1070
|
+
"""
|
|
1071
|
+
P = self._check_valid()
|
|
1072
|
+
try:
|
|
1073
|
+
return sorted(P.get('join(", ", {}->list_properties)'.format(self._name)).split(', '))
|
|
1074
|
+
except PolymakeError:
|
|
1075
|
+
return []
|
|
1076
|
+
|
|
1077
|
+
@cached_method
|
|
1078
|
+
def _member_list(self):
|
|
1079
|
+
"""
|
|
1080
|
+
The list of properties that polymake knows to compute for this element.
|
|
1081
|
+
|
|
1082
|
+
The resulting list is used for tab completion.
|
|
1083
|
+
|
|
1084
|
+
TESTS::
|
|
1085
|
+
|
|
1086
|
+
sage: c = polymake.cube(4) # optional - jupymake
|
|
1087
|
+
sage: c._member_list() # optional - jupymake
|
|
1088
|
+
['AFFINE_HULL',
|
|
1089
|
+
...
|
|
1090
|
+
'WEAKLY_CENTERED',
|
|
1091
|
+
...]
|
|
1092
|
+
"""
|
|
1093
|
+
# return the members of a "big" object.
|
|
1094
|
+
P = self._check_valid()
|
|
1095
|
+
try:
|
|
1096
|
+
cmd = '$SAGETMP = ' + self._name + ' -> type;'
|
|
1097
|
+
P.eval(cmd)
|
|
1098
|
+
except (TypeError, PolymakeError): # this happens for a perl type that isn't a Polymake type
|
|
1099
|
+
return []
|
|
1100
|
+
cmd = 'print join(", ", sorted_uniq(sort { $a cmp $b } map { keys %{$_->properties} }$SAGETMP, @{$SAGETMP->super}));'
|
|
1101
|
+
try:
|
|
1102
|
+
out = P.eval(cmd).split(', ')
|
|
1103
|
+
except PolymakeError:
|
|
1104
|
+
return []
|
|
1105
|
+
return sorted(out)
|
|
1106
|
+
|
|
1107
|
+
def typename(self):
|
|
1108
|
+
"""
|
|
1109
|
+
The name of the underlying base type of this element in polymake.
|
|
1110
|
+
|
|
1111
|
+
EXAMPLES::
|
|
1112
|
+
|
|
1113
|
+
sage: c = polymake.cube(4) # optional - jupymake
|
|
1114
|
+
sage: c.typename() # optional - jupymake
|
|
1115
|
+
'Polytope'
|
|
1116
|
+
sage: c.VERTICES.typename() # optional - jupymake
|
|
1117
|
+
'Matrix'
|
|
1118
|
+
"""
|
|
1119
|
+
P = self._check_valid()
|
|
1120
|
+
try:
|
|
1121
|
+
return P.eval('print {}->type->name;'.format(self._name))
|
|
1122
|
+
except PolymakeError:
|
|
1123
|
+
return ''
|
|
1124
|
+
|
|
1125
|
+
def full_typename(self):
|
|
1126
|
+
"""
|
|
1127
|
+
The name of the specialised type of this element.
|
|
1128
|
+
|
|
1129
|
+
EXAMPLES::
|
|
1130
|
+
|
|
1131
|
+
sage: c = polymake.cube(4) # optional - jupymake
|
|
1132
|
+
sage: c.full_typename() # optional - jupymake
|
|
1133
|
+
'Polytope<Rational>'
|
|
1134
|
+
sage: c.VERTICES.full_typename() # optional - jupymake
|
|
1135
|
+
'Matrix<Rational, NonSymmetric>'
|
|
1136
|
+
"""
|
|
1137
|
+
P = self._check_valid()
|
|
1138
|
+
try:
|
|
1139
|
+
return P.eval('print {}->type->full_name;'.format(self._name))
|
|
1140
|
+
except PolymakeError:
|
|
1141
|
+
return ''
|
|
1142
|
+
|
|
1143
|
+
def qualified_typename(self):
|
|
1144
|
+
"""
|
|
1145
|
+
The qualified name of the type of this element.
|
|
1146
|
+
|
|
1147
|
+
EXAMPLES::
|
|
1148
|
+
|
|
1149
|
+
sage: c = polymake.cube(4) # optional - jupymake
|
|
1150
|
+
sage: c.qualified_typename() # optional - jupymake
|
|
1151
|
+
'polytope::Polytope<Rational>'
|
|
1152
|
+
sage: c.VERTICES.qualified_typename() # optional - jupymake
|
|
1153
|
+
'common::Matrix<Rational, NonSymmetric>'
|
|
1154
|
+
"""
|
|
1155
|
+
P = self._check_valid()
|
|
1156
|
+
try:
|
|
1157
|
+
return P.eval('print {}->type->qualified_name;'.format(self._name))
|
|
1158
|
+
except PolymakeError:
|
|
1159
|
+
return ''
|
|
1160
|
+
|
|
1161
|
+
def _tab_completion(self):
|
|
1162
|
+
"""
|
|
1163
|
+
Return a list of available function and property names.
|
|
1164
|
+
|
|
1165
|
+
.. NOTE::
|
|
1166
|
+
|
|
1167
|
+
This currently returns the names of functions defined in the current
|
|
1168
|
+
application, regardless whether they can be applied to this element
|
|
1169
|
+
or not, together with the list of properties of this element that
|
|
1170
|
+
polymake knows how to compute. It does not contain the list of available
|
|
1171
|
+
member functions of this element. This may change in future versions
|
|
1172
|
+
of polymake.
|
|
1173
|
+
|
|
1174
|
+
EXAMPLES::
|
|
1175
|
+
|
|
1176
|
+
sage: c = polymake.cube(4) # optional - jupymake
|
|
1177
|
+
sage: c._tab_completion() # optional - jupymake
|
|
1178
|
+
['AFFINE_HULL',
|
|
1179
|
+
...
|
|
1180
|
+
'zero_vector',
|
|
1181
|
+
'zonotope',
|
|
1182
|
+
'zonotope_tiling_lattice',
|
|
1183
|
+
'zonotope_vertices_fukuda']
|
|
1184
|
+
"""
|
|
1185
|
+
return sorted(self._member_list()+self.parent()._tab_completion())
|
|
1186
|
+
|
|
1187
|
+
def __getattr__(self, attrname):
|
|
1188
|
+
"""
|
|
1189
|
+
Return a property of this element, or a polymake function with this
|
|
1190
|
+
element as first argument, or a member function of this element.
|
|
1191
|
+
|
|
1192
|
+
.. NOTE::
|
|
1193
|
+
|
|
1194
|
+
If the attribute name is known as the name of a property, it is
|
|
1195
|
+
interpreted as such. Otherwise, if it is known as a function in
|
|
1196
|
+
the current application, the function is returned with this
|
|
1197
|
+
element inserted as first argument, and potential further arguments,
|
|
1198
|
+
when called. Otherwise, it is assumed that it is a member function
|
|
1199
|
+
of this element, and treated as such. Note that member functions
|
|
1200
|
+
are currently invisible in tab completion, thus, the user has
|
|
1201
|
+
to know the name of the member function.
|
|
1202
|
+
|
|
1203
|
+
EXAMPLES:
|
|
1204
|
+
|
|
1205
|
+
A property::
|
|
1206
|
+
|
|
1207
|
+
sage: # optional - jupymake
|
|
1208
|
+
sage: c = polymake.cube(3)
|
|
1209
|
+
sage: c.H_VECTOR
|
|
1210
|
+
1 5 5 1
|
|
1211
|
+
sage: c.N_VERTICES
|
|
1212
|
+
8
|
|
1213
|
+
sage: d = polymake.cross(3)
|
|
1214
|
+
sage: d.N_VERTICES
|
|
1215
|
+
6
|
|
1216
|
+
|
|
1217
|
+
A function::
|
|
1218
|
+
|
|
1219
|
+
sage: # optional - jupymake
|
|
1220
|
+
sage: c.minkowski_sum_fukuda
|
|
1221
|
+
minkowski_sum_fukuda (bound to Polymake::polytope::Polytope__Rational object)
|
|
1222
|
+
sage: s = c.minkowski_sum_fukuda(d)
|
|
1223
|
+
sage: s.N_VERTICES
|
|
1224
|
+
24
|
|
1225
|
+
sage: s
|
|
1226
|
+
Polytope<Rational>[SAGE...]
|
|
1227
|
+
|
|
1228
|
+
A member function::
|
|
1229
|
+
|
|
1230
|
+
sage: # optional - jupymake
|
|
1231
|
+
sage: c = polymake.cube(2)
|
|
1232
|
+
sage: V = polymake.new_object('Vector', [1,0,0])
|
|
1233
|
+
sage: V
|
|
1234
|
+
1 0 0
|
|
1235
|
+
sage: c.contains
|
|
1236
|
+
Member function 'contains' of Polymake::polytope::Polytope__Rational object
|
|
1237
|
+
sage: c.contains(V)
|
|
1238
|
+
true
|
|
1239
|
+
"""
|
|
1240
|
+
P = self._check_valid()
|
|
1241
|
+
if attrname[:1] == "_":
|
|
1242
|
+
raise AttributeError
|
|
1243
|
+
if attrname not in P._tab_completion():
|
|
1244
|
+
# Does not appear in list of global functions.
|
|
1245
|
+
if attrname in self._member_list():
|
|
1246
|
+
try:
|
|
1247
|
+
return P('{}->{}'.format(self._name, attrname))
|
|
1248
|
+
except (TypeError, PolymakeError):
|
|
1249
|
+
raise AttributeError
|
|
1250
|
+
else:
|
|
1251
|
+
return P._function_element_class()(self, '{}->{}'.format(self._name, attrname), memberfunction=True)
|
|
1252
|
+
return P._function_element_class()(self, attrname, memberfunction=False)
|
|
1253
|
+
|
|
1254
|
+
def get_member_function(self, attrname):
|
|
1255
|
+
"""
|
|
1256
|
+
Request a member function of this element.
|
|
1257
|
+
|
|
1258
|
+
.. NOTE::
|
|
1259
|
+
|
|
1260
|
+
It is not checked whether a member function with the given name
|
|
1261
|
+
exists.
|
|
1262
|
+
|
|
1263
|
+
EXAMPLES::
|
|
1264
|
+
|
|
1265
|
+
sage: # optional - jupymake
|
|
1266
|
+
sage: c = polymake.cube(2)
|
|
1267
|
+
sage: c.contains
|
|
1268
|
+
Member function 'contains' of Polymake::polytope::Polytope__Rational object
|
|
1269
|
+
sage: V = polymake.new_object('Vector', [1,0,0])
|
|
1270
|
+
sage: V
|
|
1271
|
+
1 0 0
|
|
1272
|
+
sage: c.contains(V)
|
|
1273
|
+
true
|
|
1274
|
+
|
|
1275
|
+
Whether a member function of the given name actually exists for that
|
|
1276
|
+
object will only be clear when calling it::
|
|
1277
|
+
|
|
1278
|
+
sage: c.get_member_function("foo") # optional - jupymake
|
|
1279
|
+
Member function 'foo' of Polymake::polytope::Polytope__Rational object
|
|
1280
|
+
sage: c.get_member_function("foo")() # optional - jupymake
|
|
1281
|
+
Traceback (most recent call last):
|
|
1282
|
+
...
|
|
1283
|
+
TypeError: Can't locate object method "foo" via package "Polymake::polytope::Polytope__Rational"
|
|
1284
|
+
"""
|
|
1285
|
+
P = self._check_valid()
|
|
1286
|
+
return P._function_element_class()(self, '{}->{}'.format(self._name, attrname), memberfunction=True)
|
|
1287
|
+
|
|
1288
|
+
def get_member(self, attrname):
|
|
1289
|
+
"""
|
|
1290
|
+
Get a member/property of this element.
|
|
1291
|
+
|
|
1292
|
+
.. NOTE::
|
|
1293
|
+
|
|
1294
|
+
Normally, it should be possible to just access the property
|
|
1295
|
+
in the usual Python syntax for attribute access. However, if
|
|
1296
|
+
that fails, one can request the member explicitly.
|
|
1297
|
+
|
|
1298
|
+
EXAMPLES::
|
|
1299
|
+
|
|
1300
|
+
sage: p = polymake.rand_sphere(4, 20, seed=5) # optional - jupymake
|
|
1301
|
+
|
|
1302
|
+
Normally, a property would be accessed as follows::
|
|
1303
|
+
|
|
1304
|
+
sage: p.F_VECTOR # optional - jupymake
|
|
1305
|
+
20 94 148 74
|
|
1306
|
+
|
|
1307
|
+
However, explicit access is possible as well::
|
|
1308
|
+
|
|
1309
|
+
sage: p.get_member('F_VECTOR') # optional - jupymake
|
|
1310
|
+
20 94 148 74
|
|
1311
|
+
|
|
1312
|
+
In some cases, the explicit access works better::
|
|
1313
|
+
|
|
1314
|
+
sage: p.type # optional - jupymake
|
|
1315
|
+
Member function 'type' of Polymake::polytope::Polytope__Rational object
|
|
1316
|
+
sage: p.get_member('type') # optional - jupymake
|
|
1317
|
+
Polytope<Rational>[SAGE...]
|
|
1318
|
+
sage: p.get_member('type').get_member('name') # optional - jupymake
|
|
1319
|
+
Polytope
|
|
1320
|
+
|
|
1321
|
+
Note that in the last example calling the erroneously constructed
|
|
1322
|
+
member function ``type`` still works::
|
|
1323
|
+
|
|
1324
|
+
sage: p.type() # optional - jupymake
|
|
1325
|
+
Polytope<Rational>[SAGE...]
|
|
1326
|
+
"""
|
|
1327
|
+
P = self._check_valid()
|
|
1328
|
+
return P('{}->{}'.format(self.name(), attrname))
|
|
1329
|
+
|
|
1330
|
+
def __getitem__(self, key):
|
|
1331
|
+
"""
|
|
1332
|
+
Indexing and slicing.
|
|
1333
|
+
|
|
1334
|
+
Slicing returns a Python list.
|
|
1335
|
+
|
|
1336
|
+
EXAMPLES::
|
|
1337
|
+
|
|
1338
|
+
sage: p = polymake.rand_sphere(3, 12, seed=15) # optional - jupymake
|
|
1339
|
+
sage: p.VERTICES[3] # optional - jupymake
|
|
1340
|
+
1 7977905618560809/18014398509481984 -1671539598851959/144115188075855872 8075083879632623/9007199254740992
|
|
1341
|
+
sage: p.list_properties()[2] # optional - jupymake
|
|
1342
|
+
BOUNDED
|
|
1343
|
+
|
|
1344
|
+
Slicing::
|
|
1345
|
+
|
|
1346
|
+
sage: p.F_VECTOR[:] # optional - jupymake
|
|
1347
|
+
[12, 30, 20]
|
|
1348
|
+
sage: p.F_VECTOR[0:1] # optional - jupymake
|
|
1349
|
+
[12]
|
|
1350
|
+
sage: p.F_VECTOR[0:3:2] # optional - jupymake
|
|
1351
|
+
[12, 20]
|
|
1352
|
+
"""
|
|
1353
|
+
P = self._check_valid()
|
|
1354
|
+
if isinstance(key, slice):
|
|
1355
|
+
indices = key.indices(len(self))
|
|
1356
|
+
return [self[i] for i in range(*indices)]
|
|
1357
|
+
_, T = self.typeof()
|
|
1358
|
+
if self._name.startswith('@'):
|
|
1359
|
+
return P('${}[{}]'.format(self._name[1:], key))
|
|
1360
|
+
if T == 'ARRAY':
|
|
1361
|
+
return P('{}[{}]'.format(self._name, key))
|
|
1362
|
+
if T == 'HASH':
|
|
1363
|
+
try:
|
|
1364
|
+
if key.parent() is self.parent():
|
|
1365
|
+
key = key._name
|
|
1366
|
+
else:
|
|
1367
|
+
key = str(key)
|
|
1368
|
+
except AttributeError:
|
|
1369
|
+
key = str(key)
|
|
1370
|
+
return P(self._name + "{" + key + "}")
|
|
1371
|
+
raise NotImplementedError("Cannot get items from Perl type {}".format(T))
|
|
1372
|
+
|
|
1373
|
+
def __iter__(self):
|
|
1374
|
+
"""
|
|
1375
|
+
Return an iterator for ``self``.
|
|
1376
|
+
|
|
1377
|
+
OUTPUT: iterator
|
|
1378
|
+
|
|
1379
|
+
EXAMPLES::
|
|
1380
|
+
|
|
1381
|
+
sage: p = polymake.rand_sphere(3, 12, seed=15) # optional - jupymake
|
|
1382
|
+
sage: [ x for x in p.VERTICES[3] ] # optional - jupymake
|
|
1383
|
+
[1, 7977905618560809/18014398509481984, -1671539598851959/144115188075855872, 8075083879632623/9007199254740992]
|
|
1384
|
+
"""
|
|
1385
|
+
for i in range(len(self)):
|
|
1386
|
+
yield self[i]
|
|
1387
|
+
|
|
1388
|
+
def __len__(self):
|
|
1389
|
+
"""
|
|
1390
|
+
EXAMPLES::
|
|
1391
|
+
|
|
1392
|
+
sage: p = polymake.rand_sphere(3, 12, seed=15) # optional - jupymake
|
|
1393
|
+
sage: len(p.FACETS) # optional - jupymake
|
|
1394
|
+
20
|
|
1395
|
+
sage: len(p.list_properties()) >= 12 # optional - jupymake
|
|
1396
|
+
True
|
|
1397
|
+
"""
|
|
1398
|
+
P = self._check_valid()
|
|
1399
|
+
T1, T2 = self.typeof()
|
|
1400
|
+
name = self._name
|
|
1401
|
+
if T2 == 'ARRAY':
|
|
1402
|
+
return int(P.eval('print scalar @{+%s};' % name))
|
|
1403
|
+
if T2 == 'HASH':
|
|
1404
|
+
return int(P.eval('print scalar keys %' + ('{+%s};' % name)))
|
|
1405
|
+
if T1:
|
|
1406
|
+
raise TypeError("Don't know how to compute the length of {} object".format(T1))
|
|
1407
|
+
return int(P.eval('print scalar {};'.format(name)))
|
|
1408
|
+
|
|
1409
|
+
@cached_method
|
|
1410
|
+
def typeof(self):
|
|
1411
|
+
"""
|
|
1412
|
+
Return the type of a polymake "big" object, and its
|
|
1413
|
+
underlying Perl type.
|
|
1414
|
+
|
|
1415
|
+
.. NOTE::
|
|
1416
|
+
|
|
1417
|
+
This is mainly for internal use.
|
|
1418
|
+
|
|
1419
|
+
EXAMPLES::
|
|
1420
|
+
|
|
1421
|
+
sage: # optional - jupymake
|
|
1422
|
+
sage: p = polymake.rand_sphere(3, 13, seed=12)
|
|
1423
|
+
sage: p.typeof()
|
|
1424
|
+
('Polymake::polytope::Polytope__Rational', 'ARRAY')
|
|
1425
|
+
sage: p.VERTICES.typeof()
|
|
1426
|
+
('Polymake::common::Matrix_A_Rational_I_NonSymmetric_Z', 'ARRAY')
|
|
1427
|
+
sage: p.get_schedule('"F_VECTOR"').typeof()
|
|
1428
|
+
('Polymake::Core::Scheduler::RuleChain', 'ARRAY')
|
|
1429
|
+
|
|
1430
|
+
On "small" objects, it just returns empty strings::
|
|
1431
|
+
|
|
1432
|
+
sage: p.N_VERTICES.typeof() # optional - jupymake
|
|
1433
|
+
('', '')
|
|
1434
|
+
sage: p.list_properties().typeof() # optional - jupymake
|
|
1435
|
+
('', '')
|
|
1436
|
+
"""
|
|
1437
|
+
P = self._check_valid()
|
|
1438
|
+
name = self._name
|
|
1439
|
+
T1, T2 = P.eval('print ref({});'.format(name)), P.eval('print reftype({});'.format(name))
|
|
1440
|
+
if T1 == 'false': # Polymake 3.4 returns this
|
|
1441
|
+
T1 = ''
|
|
1442
|
+
return T1, T2
|
|
1443
|
+
|
|
1444
|
+
def _sage_(self):
|
|
1445
|
+
"""
|
|
1446
|
+
Convert ``self`` to a Sage object.
|
|
1447
|
+
|
|
1448
|
+
EXAMPLES::
|
|
1449
|
+
|
|
1450
|
+
sage: a = polymake(1/2); a # optional - jupymake
|
|
1451
|
+
1/2
|
|
1452
|
+
sage: a.sage() # optional - jupymake
|
|
1453
|
+
1/2
|
|
1454
|
+
sage: _.parent() # optional - jupymake
|
|
1455
|
+
Rational Field
|
|
1456
|
+
|
|
1457
|
+
Quadratic extensions::
|
|
1458
|
+
|
|
1459
|
+
sage: # needs sage.rings.number_field
|
|
1460
|
+
sage: K.<sqrt5> = QuadraticField(5)
|
|
1461
|
+
sage: polymake(K(0)).sage() # optional - jupymake
|
|
1462
|
+
0
|
|
1463
|
+
sage: _.parent() # optional - jupymake
|
|
1464
|
+
Rational Field
|
|
1465
|
+
sage: polymake(sqrt5).sage() # optional - jupymake
|
|
1466
|
+
a
|
|
1467
|
+
sage: polymake(-sqrt5).sage() # optional - jupymake
|
|
1468
|
+
-a
|
|
1469
|
+
sage: polymake(1/3-1/2*sqrt5).sage() # optional - jupymake
|
|
1470
|
+
-1/2*a + 1/3
|
|
1471
|
+
sage: polymake(-1+sqrt5).sage() # optional - jupymake
|
|
1472
|
+
a - 1
|
|
1473
|
+
|
|
1474
|
+
Vectors::
|
|
1475
|
+
|
|
1476
|
+
sage: PP = polymake.cube(3) # optional - jupymake
|
|
1477
|
+
sage: PP.F_VECTOR.sage() # optional - jupymake
|
|
1478
|
+
(8, 12, 6)
|
|
1479
|
+
sage: _.parent() # optional - jupymake
|
|
1480
|
+
Ambient free module of rank 3 over the principal ideal domain Integer Ring
|
|
1481
|
+
|
|
1482
|
+
Matrices::
|
|
1483
|
+
|
|
1484
|
+
sage: polymake.unit_matrix(2).sage() # optional - jupymake
|
|
1485
|
+
[1 0]
|
|
1486
|
+
[0 1]
|
|
1487
|
+
sage: _.parent() # optional - jupymake
|
|
1488
|
+
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
|
|
1489
|
+
|
|
1490
|
+
Polytopes::
|
|
1491
|
+
|
|
1492
|
+
sage: polymake.cube(3).sage() # optional - jupymake
|
|
1493
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices
|
|
1494
|
+
sage: polymake.icosahedron().sage() # optional - jupymake, needs sage.rings.number_field
|
|
1495
|
+
A 3-dimensional polyhedron in
|
|
1496
|
+
(Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?)^3
|
|
1497
|
+
defined as the convex hull of 12 vertices
|
|
1498
|
+
"""
|
|
1499
|
+
T1, T2 = self.typeof()
|
|
1500
|
+
self._check_valid()
|
|
1501
|
+
try:
|
|
1502
|
+
# Try to just read things from the string representation.
|
|
1503
|
+
if 'Sparse' in T1:
|
|
1504
|
+
raise NotImplementedError
|
|
1505
|
+
|
|
1506
|
+
r = self._repr_()
|
|
1507
|
+
if 'Float' in T1:
|
|
1508
|
+
from sage.rings.real_double import RDF
|
|
1509
|
+
base_ring = RDF
|
|
1510
|
+
str_to_base_ring = RDF
|
|
1511
|
+
elif 'QuadraticExtension' in T1 and 'r' in r:
|
|
1512
|
+
i = r.find('r')
|
|
1513
|
+
i1 = min((r[i:]+' ').find(' '), (r[i:]+'\n').find('\n'))
|
|
1514
|
+
d = int(r[i+1:i+i1])
|
|
1515
|
+
from sage.rings.number_field.number_field import QuadraticField
|
|
1516
|
+
base_ring = QuadraticField(d)
|
|
1517
|
+
|
|
1518
|
+
def str_to_base_ring(s):
|
|
1519
|
+
m = re.match(r'(-?[0-9/]+)[+]?((-?[0-9/]+)r([0-9/]+))?', s)
|
|
1520
|
+
a, b = m.group(1), m.group(3)
|
|
1521
|
+
return base_ring(a) + base_ring(b) * base_ring.gen()
|
|
1522
|
+
|
|
1523
|
+
elif 'Rational' in T1:
|
|
1524
|
+
from sage.rings.rational_field import QQ
|
|
1525
|
+
base_ring = QQ
|
|
1526
|
+
str_to_base_ring = QQ
|
|
1527
|
+
else:
|
|
1528
|
+
raise NotImplementedError
|
|
1529
|
+
|
|
1530
|
+
if 'Vector' in T1:
|
|
1531
|
+
from sage.modules.free_module_element import vector
|
|
1532
|
+
if r == '':
|
|
1533
|
+
return vector(base_ring)
|
|
1534
|
+
return vector(base_ring, [str_to_base_ring(s) for s in r.split(' ')])
|
|
1535
|
+
elif 'Matrix' in T1:
|
|
1536
|
+
from sage.matrix.constructor import matrix
|
|
1537
|
+
if r == '':
|
|
1538
|
+
return matrix(base_ring)
|
|
1539
|
+
return matrix(base_ring, [[str_to_base_ring(s) for s in t.split(' ')] for t in r.split('\n')])
|
|
1540
|
+
except Exception:
|
|
1541
|
+
pass
|
|
1542
|
+
|
|
1543
|
+
if T1:
|
|
1544
|
+
Temp = self.typename()
|
|
1545
|
+
if Temp:
|
|
1546
|
+
T1 = Temp
|
|
1547
|
+
if T1 == 'QuadraticExtension':
|
|
1548
|
+
# We can't seem to access a, b, r by method calls, so let's parse.
|
|
1549
|
+
m = re.match(r'(-?[0-9/]+)[+]?((-?[0-9/]+)r([0-9/]+))?', repr(self))
|
|
1550
|
+
if m is None:
|
|
1551
|
+
raise NotImplementedError("Cannot parse QuadraticExtension element: {}".format(self))
|
|
1552
|
+
a, b, r = m.group(1), m.group(3), m.group(4)
|
|
1553
|
+
from sage.rings.rational_field import QQ
|
|
1554
|
+
if r is None:
|
|
1555
|
+
# Prints like a rational, so we can't know the extension. Coerce to rational.
|
|
1556
|
+
return QQ(a)
|
|
1557
|
+
else:
|
|
1558
|
+
from sage.rings.number_field.number_field import QuadraticField
|
|
1559
|
+
K = QuadraticField(r)
|
|
1560
|
+
return QQ(a) + QQ(b) * K.gen()
|
|
1561
|
+
elif T1 == 'Vector' or T1 == 'SparseVector':
|
|
1562
|
+
from sage.modules.free_module_element import vector
|
|
1563
|
+
return vector([x.sage() for x in self])
|
|
1564
|
+
elif T1 == 'Matrix' or T1 == 'SparseMatrix':
|
|
1565
|
+
from sage.matrix.constructor import matrix
|
|
1566
|
+
return matrix([x.sage() for x in self])
|
|
1567
|
+
elif T1 == 'Polytope':
|
|
1568
|
+
from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake
|
|
1569
|
+
return Polyhedron_polymake._from_polymake_polytope(None, self)
|
|
1570
|
+
else:
|
|
1571
|
+
return super()._sage_()
|
|
1572
|
+
|
|
1573
|
+
def _sage_doc_(self):
|
|
1574
|
+
"""
|
|
1575
|
+
EXAMPLES::
|
|
1576
|
+
|
|
1577
|
+
sage: c = polymake.cube(3) # optional - jupymake
|
|
1578
|
+
sage: print(c._sage_doc_()) # optional - jupymake # random
|
|
1579
|
+
objects/Polytope:
|
|
1580
|
+
Not necessarily bounded or unbounded polyhedron.
|
|
1581
|
+
Nonetheless, the name "Polytope" is used for two reasons:
|
|
1582
|
+
Firstly, combinatorially we always deal with polytopes; see the description of VERTICES_IN_FACETS for details.
|
|
1583
|
+
The second reason is historical.
|
|
1584
|
+
We use homogeneous coordinates, which is why Polytope is derived from Cone.
|
|
1585
|
+
Note that a pointed polyhedron is projectively equivalent to a polytope.
|
|
1586
|
+
Scalar is the numeric data type used for the coordinates.
|
|
1587
|
+
<BLANKLINE>
|
|
1588
|
+
objects/Polytope/specializations/Polytope<Rational>:
|
|
1589
|
+
A rational polyhedron realized in Q^d
|
|
1590
|
+
sage: print(c.FACETS._sage_doc_()) # optional - jupymake # random
|
|
1591
|
+
property_types/Algebraic Types/SparseMatrix:
|
|
1592
|
+
A SparseMatrix is a two-dimensional associative array with row and column indices as keys; elements equal to the default value (ElementType(), which is 0 for most numerical types) are not stored, but implicitly encoded by the gaps in the key set. Each row and column is organized as an AVL-tree.
|
|
1593
|
+
<BLANKLINE>
|
|
1594
|
+
Use dense to convert this into its dense form.
|
|
1595
|
+
<BLANKLINE>
|
|
1596
|
+
You can create a new SparseMatrix by entering its entries row by row, as a list of SparseVectors e.g.:
|
|
1597
|
+
$A = new SparseMatrix<Int>(<< '.');
|
|
1598
|
+
(5) (1 1)
|
|
1599
|
+
(5) (4 2)
|
|
1600
|
+
(5)
|
|
1601
|
+
(5) (0 3) (1 -1)
|
|
1602
|
+
.
|
|
1603
|
+
"""
|
|
1604
|
+
P = self._check_valid()
|
|
1605
|
+
# according to Julian Pfeifle, the only case in which the fully qualified
|
|
1606
|
+
# typename would not provide the doc.
|
|
1607
|
+
Tname = self.typename()
|
|
1608
|
+
Tqname = self.qualified_typename()
|
|
1609
|
+
Tfname = self.full_typename()
|
|
1610
|
+
if Tname == 'Polytope':
|
|
1611
|
+
try:
|
|
1612
|
+
doc = P.eval('help "Polytope";')
|
|
1613
|
+
except PolymakeError:
|
|
1614
|
+
doc = ''
|
|
1615
|
+
else:
|
|
1616
|
+
try:
|
|
1617
|
+
doc = P.eval('help "{}";'.format(Tname))
|
|
1618
|
+
except PolymakeError:
|
|
1619
|
+
doc = ''
|
|
1620
|
+
try:
|
|
1621
|
+
doc2 = P.eval('help "{}";'.format(Tqname))
|
|
1622
|
+
except PolymakeError:
|
|
1623
|
+
doc2 = ''
|
|
1624
|
+
if doc:
|
|
1625
|
+
if doc2:
|
|
1626
|
+
doc = doc+os.linesep+doc2
|
|
1627
|
+
else:
|
|
1628
|
+
doc = doc2
|
|
1629
|
+
try:
|
|
1630
|
+
doc3 = P.eval('help "{}";'.format(Tfname))
|
|
1631
|
+
except PolymakeError:
|
|
1632
|
+
doc3 = ''
|
|
1633
|
+
if doc:
|
|
1634
|
+
if doc3:
|
|
1635
|
+
doc = doc+os.linesep+doc3
|
|
1636
|
+
else:
|
|
1637
|
+
doc = doc3
|
|
1638
|
+
if doc:
|
|
1639
|
+
return doc
|
|
1640
|
+
return "Undocumented polymake type '{}'".format(self.full_typename())
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
class PolymakeFunctionElement(InterfaceFunctionElement):
|
|
1644
|
+
"""
|
|
1645
|
+
A callable (function or member function) bound to a polymake element.
|
|
1646
|
+
|
|
1647
|
+
EXAMPLES::
|
|
1648
|
+
|
|
1649
|
+
sage: # optional - jupymake
|
|
1650
|
+
sage: c = polymake.cube(2)
|
|
1651
|
+
sage: V = polymake.new_object('Vector', [1,0,0])
|
|
1652
|
+
sage: V
|
|
1653
|
+
1 0 0
|
|
1654
|
+
sage: c.contains
|
|
1655
|
+
Member function 'contains' of Polymake::polytope::Polytope__Rational object
|
|
1656
|
+
sage: c.contains(V)
|
|
1657
|
+
true
|
|
1658
|
+
"""
|
|
1659
|
+
def __init__(self, obj, name, memberfunction=False):
|
|
1660
|
+
"""
|
|
1661
|
+
INPUT:
|
|
1662
|
+
|
|
1663
|
+
- ``obj`` -- Polymake object that this function is bound to
|
|
1664
|
+
- ``name`` -- string; it actually says how to call this function in
|
|
1665
|
+
polymake. So, if it is a member function, it will look like
|
|
1666
|
+
`"$SAGE123[0]->func_name"`.
|
|
1667
|
+
- ``memberfunction`` -- boolean (default: ``False``); whether this is a
|
|
1668
|
+
member function or a plain function applied with this element as
|
|
1669
|
+
first argument
|
|
1670
|
+
|
|
1671
|
+
EXAMPLES::
|
|
1672
|
+
|
|
1673
|
+
sage: p = polymake.rand_sphere(3, 13, seed=12) # optional - jupymake
|
|
1674
|
+
sage: p.minkowski_sum_fukuda # optional - jupymake
|
|
1675
|
+
minkowski_sum_fukuda (bound to Polymake::polytope::Polytope__Rational object)
|
|
1676
|
+
sage: p.get_schedule # optional - jupymake
|
|
1677
|
+
Member function 'get_schedule' of Polymake::polytope::Polytope__Rational object
|
|
1678
|
+
"""
|
|
1679
|
+
self._obj = obj
|
|
1680
|
+
self._name = name
|
|
1681
|
+
self._is_memberfunc = memberfunction
|
|
1682
|
+
|
|
1683
|
+
def _repr_(self):
|
|
1684
|
+
"""
|
|
1685
|
+
EXAMPLES::
|
|
1686
|
+
|
|
1687
|
+
sage: p = polymake.rand_sphere(3, 13, seed=12) # optional - jupymake
|
|
1688
|
+
sage: p.minkowski_sum_fukuda # optional - jupymake
|
|
1689
|
+
minkowski_sum_fukuda (bound to Polymake::polytope::Polytope__Rational object)
|
|
1690
|
+
sage: p.contains # optional - jupymake
|
|
1691
|
+
Member function 'contains' of Polymake::polytope::Polytope__Rational object
|
|
1692
|
+
"""
|
|
1693
|
+
if self._is_memberfunc:
|
|
1694
|
+
return "Member function '{}' of {} object".format(self._name.split("->")[-1], self._obj.typeof()[0])
|
|
1695
|
+
return "{} (bound to {} object)".format(self._name, self._obj.typeof()[0])
|
|
1696
|
+
|
|
1697
|
+
def __call__(self, *args, **kwds):
|
|
1698
|
+
"""
|
|
1699
|
+
EXAMPLES:
|
|
1700
|
+
|
|
1701
|
+
We consider both member functions of an element and global functions
|
|
1702
|
+
bound to an element::
|
|
1703
|
+
|
|
1704
|
+
sage: p = polymake.rand_sphere(3, 13, seed=12) # optional - jupymake
|
|
1705
|
+
sage: p.get_schedule('"VERTICES"') # optional - jupymake # random
|
|
1706
|
+
sensitivity check for VertexPerm
|
|
1707
|
+
cdd.convex_hull.canon: POINTED, RAYS, LINEALITY_SPACE : INPUT_RAYS
|
|
1708
|
+
sage: p.minkowski_sum_fukuda(p).F_VECTOR # optional - jupymake # not tested
|
|
1709
|
+
13 33 22
|
|
1710
|
+
"""
|
|
1711
|
+
if self._is_memberfunc:
|
|
1712
|
+
return self._obj._check_valid().function_call(self._name, list(args), kwds)
|
|
1713
|
+
return self._obj._check_valid().function_call(self._name, [self._obj] + list(args), kwds)
|
|
1714
|
+
|
|
1715
|
+
def _sage_doc_(self):
|
|
1716
|
+
"""
|
|
1717
|
+
Return documentation of this function.
|
|
1718
|
+
|
|
1719
|
+
.. NOTE::
|
|
1720
|
+
|
|
1721
|
+
For unclear reasons, accessing documentation with ``?`` sometimes
|
|
1722
|
+
does not include the return value of this method.
|
|
1723
|
+
|
|
1724
|
+
EXAMPLES::
|
|
1725
|
+
|
|
1726
|
+
sage: p = polymake.rand_sphere(3, 13, seed=12) # optional - jupymake
|
|
1727
|
+
sage: print(p.get_schedule._sage_doc_()) # optional - jupymake # random
|
|
1728
|
+
objects/Core::Object/methods/get_schedule:
|
|
1729
|
+
get_schedule(request; ... ) -> Core::RuleChain
|
|
1730
|
+
<BLANKLINE>
|
|
1731
|
+
Compose an optimal chain of production rules providing all requested properties.
|
|
1732
|
+
The returned RuleChain object can be applied to the original object as well as to any other object
|
|
1733
|
+
with the same initial set of properties. If no feasible rule chain exists, `undef' is returned.
|
|
1734
|
+
<BLANKLINE>
|
|
1735
|
+
To watch the rule scheduler at work, e.g. to see announcements about tried preconditions,
|
|
1736
|
+
you may temporarily increase the verbosity levels $Verbose::rules and $Verbose::scheduler.
|
|
1737
|
+
<BLANKLINE>
|
|
1738
|
+
Arguments:
|
|
1739
|
+
String request : name of a property with optional alternatives or a property path in dotted notation.
|
|
1740
|
+
Several requests may be listed.
|
|
1741
|
+
<BLANKLINE>
|
|
1742
|
+
Returns Core::RuleChain
|
|
1743
|
+
sage: print(p.minkowski_sum_fukuda._sage_doc_()) # optional - jupymake # random
|
|
1744
|
+
functions/Producing a polytope from polytopes/minkowski_sum_fukuda:
|
|
1745
|
+
minkowski_sum_fukuda(summands) -> Polytope<Scalar>
|
|
1746
|
+
<BLANKLINE>
|
|
1747
|
+
Computes the (VERTICES of the) Minkowski sum of a list of polytopes using the algorithm by Fukuda described in
|
|
1748
|
+
Komei Fukuda, From the zonotope construction to the Minkowski addition of convex polytopes, J. Symbolic Comput., 38(4):1261-1272, 2004.
|
|
1749
|
+
<BLANKLINE>
|
|
1750
|
+
Arguments:
|
|
1751
|
+
Array<Polytope<Scalar>> summands
|
|
1752
|
+
<BLANKLINE>
|
|
1753
|
+
Returns Polytope<Scalar>
|
|
1754
|
+
<BLANKLINE>
|
|
1755
|
+
Example:
|
|
1756
|
+
> $p = minkowski_sum_fukuda([cube(2),simplex(2),cross(2)]);
|
|
1757
|
+
> print $p->VERTICES;
|
|
1758
|
+
1 -2 -1
|
|
1759
|
+
1 -1 -2
|
|
1760
|
+
1 3 -1
|
|
1761
|
+
1 3 1
|
|
1762
|
+
1 2 -2
|
|
1763
|
+
1 -2 2
|
|
1764
|
+
1 -1 3
|
|
1765
|
+
1 1 3
|
|
1766
|
+
"""
|
|
1767
|
+
P = self._obj._check_valid()
|
|
1768
|
+
return P.help(self._name.split("->")[-1], pager=False)
|
|
1769
|
+
|
|
1770
|
+
|
|
1771
|
+
class PolymakeJuPyMake(PolymakeAbstract):
|
|
1772
|
+
r"""
|
|
1773
|
+
Interface to the polymake interpreter using JuPyMake.
|
|
1774
|
+
|
|
1775
|
+
In order to use this interface, you need to either install the
|
|
1776
|
+
optional polymake package for Sage, or install polymake system-wide
|
|
1777
|
+
on your computer; it is available from https://polymake.org.
|
|
1778
|
+
Also install the jupymake Python package.
|
|
1779
|
+
|
|
1780
|
+
Type ``polymake.[tab]`` for a list of most functions
|
|
1781
|
+
available from your polymake install. Type
|
|
1782
|
+
``polymake.Function?`` for polymake's help about a given ``Function``.
|
|
1783
|
+
Type ``polymake(...)`` to create a new polymake
|
|
1784
|
+
object, and ``polymake.eval(...)`` to run a string using
|
|
1785
|
+
polymake and get the result back as a string.
|
|
1786
|
+
|
|
1787
|
+
EXAMPLES::
|
|
1788
|
+
|
|
1789
|
+
sage: from sage.interfaces.polymake import polymake_jupymake as polymake
|
|
1790
|
+
sage: type(polymake)
|
|
1791
|
+
<...sage.interfaces.polymake.PolymakeJuPyMake...
|
|
1792
|
+
sage: p = polymake.rand_sphere(4, 20, seed=5) # optional - jupymake
|
|
1793
|
+
sage: p # optional - jupymake
|
|
1794
|
+
Random spherical polytope of dimension 4; seed=5...
|
|
1795
|
+
sage: set_verbose(3)
|
|
1796
|
+
sage: p.H_VECTOR; # optional - jupymake # random
|
|
1797
|
+
used package ppl
|
|
1798
|
+
The Parma Polyhedra Library ...
|
|
1799
|
+
sage: p.H_VECTOR # optional - jupymake
|
|
1800
|
+
1 16 40 16 1
|
|
1801
|
+
sage: set_verbose(0)
|
|
1802
|
+
sage: p.F_VECTOR # optional - jupymake
|
|
1803
|
+
20 94 148 74
|
|
1804
|
+
sage: print(p.F_VECTOR._sage_doc_()) # optional - jupymake # random
|
|
1805
|
+
property_types/Algebraic Types/Vector:
|
|
1806
|
+
A type for vectors with entries of type Element.
|
|
1807
|
+
|
|
1808
|
+
You can perform algebraic operations such as addition or scalar multiplication.
|
|
1809
|
+
|
|
1810
|
+
You can create a new Vector by entering its elements, e.g.:
|
|
1811
|
+
$v = new Vector<Int>(1,2,3);
|
|
1812
|
+
or
|
|
1813
|
+
$v = new Vector<Int>([1,2,3]);
|
|
1814
|
+
|
|
1815
|
+
Python strings are translated to polymake (Perl) identifiers.
|
|
1816
|
+
To obtain Perl strings, use strings containing double-quote characters.
|
|
1817
|
+
Python dicts are translated to Perl hashes.
|
|
1818
|
+
|
|
1819
|
+
::
|
|
1820
|
+
|
|
1821
|
+
sage: # long time, optional - internet jupymake perl_mongodb
|
|
1822
|
+
sage: L = polymake.db_query({'"_id"': '"F.4D.0047"'},
|
|
1823
|
+
....: db='"LatticePolytopes"',
|
|
1824
|
+
....: collection='"SmoothReflexive"'); L
|
|
1825
|
+
BigObjectArray
|
|
1826
|
+
sage: len(L)
|
|
1827
|
+
1
|
|
1828
|
+
sage: P = L[0]
|
|
1829
|
+
sage: sorted(P.list_properties(), key=str)
|
|
1830
|
+
[..., LATTICE_POINTS_GENERATORS, ..., POINTED, ...]
|
|
1831
|
+
sage: P.F_VECTOR
|
|
1832
|
+
20 40 29 9
|
|
1833
|
+
"""
|
|
1834
|
+
|
|
1835
|
+
def __init__(self, seed=None, verbose=False):
|
|
1836
|
+
"""
|
|
1837
|
+
Initialize ``self``.
|
|
1838
|
+
|
|
1839
|
+
INPUT:
|
|
1840
|
+
|
|
1841
|
+
- ``verbose`` -- boolean (default: ``False``); whether to print the
|
|
1842
|
+
commands passed to polymake
|
|
1843
|
+
|
|
1844
|
+
TESTS::
|
|
1845
|
+
|
|
1846
|
+
sage: from sage.interfaces.polymake import PolymakeJuPyMake
|
|
1847
|
+
sage: PolymakeJuPyMake()
|
|
1848
|
+
Polymake
|
|
1849
|
+
"""
|
|
1850
|
+
self._verbose = verbose
|
|
1851
|
+
PolymakeAbstract.__init__(self, seed=seed)
|
|
1852
|
+
|
|
1853
|
+
_is_running = False # class variable
|
|
1854
|
+
|
|
1855
|
+
def is_running(self):
|
|
1856
|
+
"""
|
|
1857
|
+
Return ``True`` if ``self`` is currently running.
|
|
1858
|
+
|
|
1859
|
+
TESTS::
|
|
1860
|
+
|
|
1861
|
+
sage: from sage.interfaces.polymake import PolymakeJuPyMake
|
|
1862
|
+
sage: pm = PolymakeJuPyMake()
|
|
1863
|
+
sage: pm(1) # optional - jupymake
|
|
1864
|
+
1
|
|
1865
|
+
sage: pm.is_running() # optional - jupymake
|
|
1866
|
+
True
|
|
1867
|
+
|
|
1868
|
+
Several PolymakeJuPyMake interfaces can be created, but they all
|
|
1869
|
+
talk to the same polymake interpreter::
|
|
1870
|
+
|
|
1871
|
+
sage: pm2 = PolymakeJuPyMake()
|
|
1872
|
+
sage: pm2.is_running() # optional - jupymake
|
|
1873
|
+
True
|
|
1874
|
+
"""
|
|
1875
|
+
return self._is_running
|
|
1876
|
+
|
|
1877
|
+
def _start(self):
|
|
1878
|
+
"""
|
|
1879
|
+
Initialize the interpreter.
|
|
1880
|
+
|
|
1881
|
+
TESTS::
|
|
1882
|
+
|
|
1883
|
+
sage: from sage.interfaces.polymake import PolymakeJuPyMake
|
|
1884
|
+
sage: pm = PolymakeJuPyMake()
|
|
1885
|
+
sage: pm._start() # optional - jupymake
|
|
1886
|
+
sage: pm.is_running() # optional - jupymake
|
|
1887
|
+
True
|
|
1888
|
+
"""
|
|
1889
|
+
from JuPyMake import InitializePolymake
|
|
1890
|
+
if not self.is_running():
|
|
1891
|
+
InitializePolymake() # Can only be called once
|
|
1892
|
+
PolymakeJuPyMake._is_running = True
|
|
1893
|
+
PolymakeAbstract._start(self)
|
|
1894
|
+
self.eval("sub Polymake::Core::Shell::Mock::fill_history {}")
|
|
1895
|
+
self._tab_completion() # Run it here already because it causes a segfault when invoked in actual tab completion situation?!
|
|
1896
|
+
|
|
1897
|
+
def eval(self, code, **kwds):
|
|
1898
|
+
r"""
|
|
1899
|
+
Evaluate a command.
|
|
1900
|
+
|
|
1901
|
+
INPUT:
|
|
1902
|
+
|
|
1903
|
+
- ``code`` -- a command (string) to be evaluated
|
|
1904
|
+
|
|
1905
|
+
Different reaction types of polymake, including warnings, comments,
|
|
1906
|
+
errors, request for user interaction, and yielding a continuation prompt,
|
|
1907
|
+
are taken into account.
|
|
1908
|
+
|
|
1909
|
+
EXAMPLES::
|
|
1910
|
+
|
|
1911
|
+
sage: from sage.interfaces.polymake import polymake_jupymake as polymake
|
|
1912
|
+
sage: p = polymake.cube(3) # optional - jupymake # indirect doctest
|
|
1913
|
+
|
|
1914
|
+
Here we see that remarks printed by polymake are displayed if
|
|
1915
|
+
the verbosity is positive::
|
|
1916
|
+
|
|
1917
|
+
sage: set_verbose(1)
|
|
1918
|
+
sage: p.N_LATTICE_POINTS # optional - jupymake # random
|
|
1919
|
+
used package latte
|
|
1920
|
+
LattE (Lattice point Enumeration) is a computer software dedicated to the
|
|
1921
|
+
problems of counting lattice points and integration inside convex polytopes.
|
|
1922
|
+
Copyright by Matthias Koeppe, Jesus A. De Loera and others.
|
|
1923
|
+
http://www.math.ucdavis.edu/~latte/
|
|
1924
|
+
27
|
|
1925
|
+
sage: set_verbose(0)
|
|
1926
|
+
|
|
1927
|
+
If polymake raises an error, the polymake *interface* raises
|
|
1928
|
+
a :exc:`PolymakeError`::
|
|
1929
|
+
|
|
1930
|
+
sage: polymake.eval('FOOBAR(3);') # optional - jupymake
|
|
1931
|
+
Traceback (most recent call last):
|
|
1932
|
+
...
|
|
1933
|
+
PolymakeError: Undefined subroutine &Polymake::User::FOOBAR called...
|
|
1934
|
+
|
|
1935
|
+
If a command is incomplete, then polymake returns a continuation
|
|
1936
|
+
prompt. In that case, we raise an error::
|
|
1937
|
+
|
|
1938
|
+
sage: polymake.eval('print 3') # optional - jupymake
|
|
1939
|
+
Traceback (most recent call last):
|
|
1940
|
+
...
|
|
1941
|
+
SyntaxError: Incomplete polymake command 'print 3'
|
|
1942
|
+
sage: polymake.eval('print 3;') # optional - jupymake
|
|
1943
|
+
'3'
|
|
1944
|
+
|
|
1945
|
+
However, if the command contains line breaks but eventually is complete,
|
|
1946
|
+
no error is raised::
|
|
1947
|
+
|
|
1948
|
+
sage: print(polymake.eval('$tmp="abc";\nprint $tmp;')) # optional - jupymake
|
|
1949
|
+
abc
|
|
1950
|
+
|
|
1951
|
+
When requesting help, polymake sometimes expects the user to choose
|
|
1952
|
+
from a list. In that situation, we abort with a warning, and show
|
|
1953
|
+
the list from which the user can choose; we could demonstrate this using
|
|
1954
|
+
the :meth:`~sage.interfaces.polymake.PolymakeAbstract.help` method,
|
|
1955
|
+
but here we use an explicit code evaluation::
|
|
1956
|
+
|
|
1957
|
+
sage: print(polymake.eval('help "TRIANGULATION";')) # optional - jupymake # random
|
|
1958
|
+
doctest:warning
|
|
1959
|
+
...
|
|
1960
|
+
UserWarning: Polymake expects user interaction. We abort and return
|
|
1961
|
+
the options that Polymake provides.
|
|
1962
|
+
There are 5 help topics matching 'TRIANGULATION':
|
|
1963
|
+
1: objects/Cone/properties/Triangulation and volume/TRIANGULATION
|
|
1964
|
+
2: objects/Polytope/properties/Triangulation and volume/TRIANGULATION
|
|
1965
|
+
3: objects/Visualization/Visual::PointConfiguration/methods/TRIANGULATION
|
|
1966
|
+
4: objects/Visualization/Visual::Polytope/methods/TRIANGULATION
|
|
1967
|
+
5: objects/PointConfiguration/properties/Triangulation and volume/TRIANGULATION
|
|
1968
|
+
|
|
1969
|
+
By default, we just wait until polymake returns a result. However,
|
|
1970
|
+
it is possible to explicitly set a timeout. The following usually does
|
|
1971
|
+
work in an interactive session and often in doc tests, too. However,
|
|
1972
|
+
sometimes it hangs, and therefore we remove it from the tests, for now::
|
|
1973
|
+
|
|
1974
|
+
sage: c = polymake.cube(15) # optional - jupymake
|
|
1975
|
+
sage: polymake.eval('print {}->F_VECTOR;'.format(c.name()), timeout=1) # not tested # optional - jupymake
|
|
1976
|
+
Traceback (most recent call last):
|
|
1977
|
+
...
|
|
1978
|
+
RuntimeError: Polymake fails to respond timely
|
|
1979
|
+
|
|
1980
|
+
We verify that after the timeout, polymake is still able
|
|
1981
|
+
to give answers::
|
|
1982
|
+
|
|
1983
|
+
sage: c # optional - jupymake
|
|
1984
|
+
cube of dimension 15
|
|
1985
|
+
sage: c.N_VERTICES # optional - jupymake
|
|
1986
|
+
32768
|
|
1987
|
+
|
|
1988
|
+
Note, however, that the recovery after a timeout is not perfect.
|
|
1989
|
+
It may happen that in some situation the interface collapses and
|
|
1990
|
+
thus polymake would automatically be restarted, thereby losing all
|
|
1991
|
+
data that have been computed before.
|
|
1992
|
+
"""
|
|
1993
|
+
if not self.is_running():
|
|
1994
|
+
self._start()
|
|
1995
|
+
from JuPyMake import ExecuteCommand
|
|
1996
|
+
if self._verbose:
|
|
1997
|
+
print("## eval: {}".format(code))
|
|
1998
|
+
parsed, stdout, stderr, error = ExecuteCommand(code)
|
|
1999
|
+
if get_verbose() > 0 or self._verbose:
|
|
2000
|
+
stderr = stderr.rstrip('\n\r')
|
|
2001
|
+
if stderr:
|
|
2002
|
+
print(stderr)
|
|
2003
|
+
if error:
|
|
2004
|
+
# "Error evaluating {} in {}: {}".format(code, self, error)
|
|
2005
|
+
raise PolymakeError(error)
|
|
2006
|
+
if not parsed:
|
|
2007
|
+
raise SyntaxError("Incomplete polymake command '{}'".format(code))
|
|
2008
|
+
return stdout
|
|
2009
|
+
|
|
2010
|
+
_eval_line = eval
|
|
2011
|
+
|
|
2012
|
+
|
|
2013
|
+
def reduce_load_Polymake():
|
|
2014
|
+
r"""
|
|
2015
|
+
Return the polymake interface object defined in :mod:`sage.interfaces.polymake`.
|
|
2016
|
+
|
|
2017
|
+
EXAMPLES::
|
|
2018
|
+
|
|
2019
|
+
sage: from sage.interfaces.polymake import reduce_load_Polymake
|
|
2020
|
+
sage: reduce_load_Polymake()
|
|
2021
|
+
Polymake
|
|
2022
|
+
"""
|
|
2023
|
+
return polymake
|
|
2024
|
+
|
|
2025
|
+
|
|
2026
|
+
Polymake = PolymakeJuPyMake
|
|
2027
|
+
|
|
2028
|
+
polymake = polymake_jupymake = PolymakeJuPyMake()
|