passagemath-polyhedra 10.6.31rc3__cp314-cp314-musllinux_1_2_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 +208 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_polyhedra.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-8949ffbe.so.1.0.0 +0 -0
- passagemath_polyhedra.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
- sage/all__sagemath_polyhedra.py +50 -0
- sage/game_theory/all.py +8 -0
- sage/game_theory/catalog.py +6 -0
- sage/game_theory/catalog_normal_form_games.py +923 -0
- sage/game_theory/cooperative_game.py +844 -0
- sage/game_theory/matching_game.py +1181 -0
- sage/game_theory/normal_form_game.py +2697 -0
- sage/game_theory/parser.py +275 -0
- sage/geometry/all__sagemath_polyhedra.py +22 -0
- sage/geometry/cone.py +6940 -0
- sage/geometry/cone_catalog.py +847 -0
- sage/geometry/cone_critical_angles.py +1027 -0
- sage/geometry/convex_set.py +1119 -0
- sage/geometry/fan.py +3743 -0
- sage/geometry/fan_isomorphism.py +389 -0
- sage/geometry/fan_morphism.py +1884 -0
- sage/geometry/hasse_diagram.py +202 -0
- sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
- sage/geometry/hyperplane_arrangement/all.py +1 -0
- sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
- sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
- sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
- sage/geometry/hyperplane_arrangement/library.py +825 -0
- sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
- sage/geometry/hyperplane_arrangement/plot.py +520 -0
- sage/geometry/integral_points.py +35 -0
- sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/integral_points_generic_dense.pyx +7 -0
- sage/geometry/lattice_polytope.py +5894 -0
- sage/geometry/linear_expression.py +773 -0
- sage/geometry/newton_polygon.py +767 -0
- sage/geometry/point_collection.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/point_collection.pyx +1008 -0
- sage/geometry/polyhedral_complex.py +2616 -0
- sage/geometry/polyhedron/all.py +8 -0
- sage/geometry/polyhedron/backend_cdd.py +460 -0
- sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
- sage/geometry/polyhedron/backend_field.py +347 -0
- sage/geometry/polyhedron/backend_normaliz.py +2503 -0
- sage/geometry/polyhedron/backend_number_field.py +168 -0
- sage/geometry/polyhedron/backend_polymake.py +765 -0
- sage/geometry/polyhedron/backend_ppl.py +582 -0
- sage/geometry/polyhedron/base.py +1206 -0
- sage/geometry/polyhedron/base0.py +1444 -0
- sage/geometry/polyhedron/base1.py +886 -0
- sage/geometry/polyhedron/base2.py +812 -0
- sage/geometry/polyhedron/base3.py +1845 -0
- sage/geometry/polyhedron/base4.py +1262 -0
- sage/geometry/polyhedron/base5.py +2700 -0
- sage/geometry/polyhedron/base6.py +1741 -0
- sage/geometry/polyhedron/base7.py +997 -0
- sage/geometry/polyhedron/base_QQ.py +1258 -0
- sage/geometry/polyhedron/base_RDF.py +98 -0
- sage/geometry/polyhedron/base_ZZ.py +934 -0
- sage/geometry/polyhedron/base_mutable.py +215 -0
- sage/geometry/polyhedron/base_number_field.py +122 -0
- sage/geometry/polyhedron/cdd_file_format.py +155 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
- sage/geometry/polyhedron/constructor.py +773 -0
- sage/geometry/polyhedron/double_description.py +753 -0
- sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
- sage/geometry/polyhedron/face.py +1060 -0
- sage/geometry/polyhedron/generating_function.py +1810 -0
- sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
- sage/geometry/polyhedron/library.py +3502 -0
- sage/geometry/polyhedron/misc.py +121 -0
- sage/geometry/polyhedron/modules/all.py +1 -0
- sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
- sage/geometry/polyhedron/palp_database.py +447 -0
- sage/geometry/polyhedron/parent.py +1279 -0
- sage/geometry/polyhedron/plot.py +1986 -0
- sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
- sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
- sage/geometry/polyhedron/representation.py +1723 -0
- sage/geometry/pseudolines.py +515 -0
- sage/geometry/relative_interior.py +445 -0
- sage/geometry/toric_plotter.py +1103 -0
- sage/geometry/triangulation/all.py +2 -0
- sage/geometry/triangulation/base.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/triangulation/base.pyx +963 -0
- sage/geometry/triangulation/data.h +147 -0
- sage/geometry/triangulation/data.pxd +4 -0
- sage/geometry/triangulation/element.py +914 -0
- sage/geometry/triangulation/functions.h +10 -0
- sage/geometry/triangulation/functions.pxd +4 -0
- sage/geometry/triangulation/point_configuration.py +2256 -0
- sage/geometry/triangulation/triangulations.h +49 -0
- sage/geometry/triangulation/triangulations.pxd +7 -0
- sage/geometry/voronoi_diagram.py +319 -0
- sage/interfaces/all__sagemath_polyhedra.py +1 -0
- sage/interfaces/polymake.py +2028 -0
- sage/numerical/all.py +13 -0
- sage/numerical/all__sagemath_polyhedra.py +11 -0
- sage/numerical/backends/all.py +1 -0
- sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
- sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxopt_backend.pyx +1006 -0
- sage/numerical/backends/cvxopt_backend_test.py +19 -0
- sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxpy_backend.pxd +41 -0
- sage/numerical/backends/cvxpy_backend.pyx +934 -0
- sage/numerical/backends/cvxpy_backend_test.py +13 -0
- sage/numerical/backends/generic_backend_test.py +24 -0
- sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/interactivelp_backend.pxd +36 -0
- sage/numerical/backends/interactivelp_backend.pyx +1231 -0
- sage/numerical/backends/interactivelp_backend_test.py +12 -0
- sage/numerical/backends/logging_backend.py +391 -0
- sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
- sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
- sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/ppl_backend.pyx +1126 -0
- sage/numerical/backends/ppl_backend_test.py +13 -0
- sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/scip_backend.pxd +22 -0
- sage/numerical/backends/scip_backend.pyx +1289 -0
- sage/numerical/backends/scip_backend_test.py +13 -0
- sage/numerical/interactive_simplex_method.py +5338 -0
- sage/numerical/knapsack.py +665 -0
- sage/numerical/linear_functions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/linear_functions.pxd +31 -0
- sage/numerical/linear_functions.pyx +1648 -0
- sage/numerical/linear_tensor.py +470 -0
- sage/numerical/linear_tensor_constraints.py +448 -0
- sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/sdp.pxd +39 -0
- sage/numerical/sdp.pyx +1433 -0
- sage/rings/all__sagemath_polyhedra.py +3 -0
- sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
- sage/rings/polynomial/omega.py +982 -0
- sage/schemes/all__sagemath_polyhedra.py +2 -0
- sage/schemes/toric/all.py +10 -0
- sage/schemes/toric/chow_group.py +1248 -0
- sage/schemes/toric/divisor.py +2082 -0
- sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-musl.so +0 -0
- sage/schemes/toric/divisor_class.pyx +322 -0
- sage/schemes/toric/fano_variety.py +1606 -0
- sage/schemes/toric/homset.py +650 -0
- sage/schemes/toric/ideal.py +451 -0
- sage/schemes/toric/library.py +1322 -0
- sage/schemes/toric/morphism.py +1958 -0
- sage/schemes/toric/points.py +1032 -0
- sage/schemes/toric/sheaf/all.py +1 -0
- sage/schemes/toric/sheaf/constructor.py +302 -0
- sage/schemes/toric/sheaf/klyachko.py +921 -0
- sage/schemes/toric/toric_subscheme.py +905 -0
- sage/schemes/toric/variety.py +3460 -0
- sage/schemes/toric/weierstrass.py +1078 -0
- sage/schemes/toric/weierstrass_covering.py +457 -0
- sage/schemes/toric/weierstrass_higher.py +288 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
import pytest
|
|
3
|
+
from sage.numerical.backends.generic_backend_test import GenericBackendTests
|
|
4
|
+
from sage.numerical.backends.generic_backend import GenericBackend
|
|
5
|
+
from sage.numerical.mip import MixedIntegerLinearProgram
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestInteractiveLPBackend(GenericBackendTests):
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def backend(self) -> GenericBackend:
|
|
12
|
+
return MixedIntegerLinearProgram(solver='InteractiveLP').get_backend()
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
r"""
|
|
3
|
+
Logging Backend
|
|
4
|
+
|
|
5
|
+
It records, for debugging and unit testing purposes, all calls to
|
|
6
|
+
backend methods in one of three ways.
|
|
7
|
+
|
|
8
|
+
See :class:`LoggingBackendFactory` for more information.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# ****************************************************************************
|
|
12
|
+
# Copyright (C) 2016 Matthias Koeppe <mkoeppe@math.ucdavis.edu>
|
|
13
|
+
#
|
|
14
|
+
# This program is free software: you can redistribute it and/or modify
|
|
15
|
+
# it under the terms of the GNU General Public License as published by
|
|
16
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
17
|
+
# (at your option) any later version.
|
|
18
|
+
# https://www.gnu.org/licenses/
|
|
19
|
+
# ****************************************************************************
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
from sage.numerical.backends.generic_backend import GenericBackend
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _format_function_call(fn_name, *v, **k):
|
|
26
|
+
"""
|
|
27
|
+
Return a Python function call as a string.
|
|
28
|
+
|
|
29
|
+
EXAMPLES::
|
|
30
|
+
|
|
31
|
+
sage: from sage.numerical.backends.logging_backend import _format_function_call
|
|
32
|
+
sage: _format_function_call('foo', 17, hellooooo='goodbyeeee')
|
|
33
|
+
"foo(17, hellooooo='goodbyeeee')"
|
|
34
|
+
"""
|
|
35
|
+
args = [repr(a) for a in v] + ["%s=%r" % (arg, val) for arg, val in k.items()]
|
|
36
|
+
return "{}({})".format(fn_name, ", ".join(args))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _make_wrapper(backend, attr):
|
|
40
|
+
"""
|
|
41
|
+
Return a wrapper for the backend method named by ``attr`` that does the logging.
|
|
42
|
+
|
|
43
|
+
Documentation and other metadata is copied from the `backend` method named ``attr``.
|
|
44
|
+
|
|
45
|
+
EXAMPLES::
|
|
46
|
+
|
|
47
|
+
sage: from sage.numerical.backends.generic_backend import get_solver
|
|
48
|
+
sage: from sage.numerical.backends.logging_backend import _make_wrapper, LoggingBackend
|
|
49
|
+
sage: backend = get_solver(solver='GLPK')
|
|
50
|
+
sage: w = _make_wrapper(backend, 'ncols')
|
|
51
|
+
sage: logging_backend = LoggingBackend(backend)
|
|
52
|
+
sage: w(logging_backend)
|
|
53
|
+
# p.ncols()
|
|
54
|
+
# result: 0
|
|
55
|
+
0
|
|
56
|
+
"""
|
|
57
|
+
def m(self, *args, **kwdargs):
|
|
58
|
+
funcall = _format_function_call("p." + attr, *args, **kwdargs)
|
|
59
|
+
a = getattr(self._backend, attr)
|
|
60
|
+
if self._printing:
|
|
61
|
+
print("# {}".format(funcall))
|
|
62
|
+
if self._doctest:
|
|
63
|
+
self._doctest.write(" sage: {}\n".format(funcall))
|
|
64
|
+
try:
|
|
65
|
+
result = a(*args, **kwdargs)
|
|
66
|
+
except Exception as e:
|
|
67
|
+
if self._printing:
|
|
68
|
+
print("# exception: {}".format(e))
|
|
69
|
+
if self._doctest:
|
|
70
|
+
self._doctest.write(" Traceback (most recent call last):\n"
|
|
71
|
+
" ...\n"
|
|
72
|
+
" MIPSolverException: {}\n".format(e))
|
|
73
|
+
if self._test_method:
|
|
74
|
+
self._test_method.write((" with tester.assertRaises({}) as cm:\n" +
|
|
75
|
+
" {}\n").format(type(e).__name__, funcall))
|
|
76
|
+
raise
|
|
77
|
+
else:
|
|
78
|
+
if self._printing:
|
|
79
|
+
print("# result: {}".format(result))
|
|
80
|
+
if self._doctest:
|
|
81
|
+
self._doctest.write(" {}\n".format(result))
|
|
82
|
+
if self._test_method:
|
|
83
|
+
if result is None:
|
|
84
|
+
self._test_method.write(" tester.assertIsNone({})\n".format(funcall))
|
|
85
|
+
elif type(result) is float:
|
|
86
|
+
# TODO: by default assertAlmostEqual does 7 decimal places (not significant digits)
|
|
87
|
+
# better perhaps to compute an appropriate 'places' or 'delta' parameter from result.
|
|
88
|
+
self._test_method.write(" tester.assertAlmostEqual({}, {})\n".format(funcall, result))
|
|
89
|
+
else:
|
|
90
|
+
self._test_method.write(" tester.assertEqual({}, {})\n".format(funcall, result))
|
|
91
|
+
return result
|
|
92
|
+
from functools import update_wrapper
|
|
93
|
+
update_wrapper(m, getattr(backend, attr))
|
|
94
|
+
return m
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class LoggingBackend(GenericBackend):
|
|
98
|
+
"""
|
|
99
|
+
See :class:`LoggingBackendFactory` for documentation.
|
|
100
|
+
|
|
101
|
+
EXAMPLES::
|
|
102
|
+
|
|
103
|
+
sage: import sage.numerical.backends.logging_backend
|
|
104
|
+
sage: from sage.numerical.backends.logging_backend import LoggingBackend
|
|
105
|
+
sage: from sage.numerical.backends.generic_backend import get_solver
|
|
106
|
+
sage: b = get_solver(solver = "GLPK")
|
|
107
|
+
sage: lb = LoggingBackend(backend=b)
|
|
108
|
+
sage: lb.add_variable(obj=42, name='Helloooooo')
|
|
109
|
+
# p.add_variable(obj=42, name='Helloooooo')
|
|
110
|
+
# result: 0
|
|
111
|
+
0
|
|
112
|
+
sage: lb.add_variable(obj=1789)
|
|
113
|
+
# p.add_variable(obj=1789)
|
|
114
|
+
# result: 1
|
|
115
|
+
1
|
|
116
|
+
|
|
117
|
+
.. :no-undoc-members:
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
def __init__(self, backend, printing=True, doctest=None, test_method=None,
|
|
121
|
+
base_ring=None):
|
|
122
|
+
"""
|
|
123
|
+
See :class:`LoggingBackendFactory` for documentation.
|
|
124
|
+
|
|
125
|
+
EXAMPLES::
|
|
126
|
+
|
|
127
|
+
sage: import sage.numerical.backends.logging_backend
|
|
128
|
+
sage: from sage.numerical.backends.logging_backend import LoggingBackend
|
|
129
|
+
sage: from sage.numerical.backends.generic_backend import get_solver
|
|
130
|
+
sage: b = get_solver(solver = "GLPK")
|
|
131
|
+
sage: lb = LoggingBackend(backend=b)
|
|
132
|
+
"""
|
|
133
|
+
self._backend = backend
|
|
134
|
+
self._printing = printing
|
|
135
|
+
self._doctest = doctest
|
|
136
|
+
self._test_method = test_method
|
|
137
|
+
self._base_ring = base_ring
|
|
138
|
+
|
|
139
|
+
def __getattr__(self, attr):
|
|
140
|
+
"""
|
|
141
|
+
Look up an attribute in the instance.
|
|
142
|
+
|
|
143
|
+
It is provided to dynamically create delegating methods for all methods of
|
|
144
|
+
the backend that are not part of the :class:`GenericBackend` interface,
|
|
145
|
+
from which :class:`LoggingBackend` inherits.
|
|
146
|
+
|
|
147
|
+
EXAMPLES::
|
|
148
|
+
|
|
149
|
+
sage: import sage.numerical.backends.logging_backend
|
|
150
|
+
sage: from sage.numerical.backends.logging_backend import LoggingBackend
|
|
151
|
+
sage: from sage.numerical.backends.generic_backend import get_solver
|
|
152
|
+
sage: b = get_solver(solver = "GLPK")
|
|
153
|
+
sage: lb = LoggingBackend(backend=b)
|
|
154
|
+
sage: lb.print_ranges
|
|
155
|
+
<bound method ...>
|
|
156
|
+
"""
|
|
157
|
+
_a = getattr(self._backend, attr)
|
|
158
|
+
if callable(_a):
|
|
159
|
+
# make a bound method
|
|
160
|
+
import types
|
|
161
|
+
_mm = types.MethodType(_make_wrapper(self._backend, attr), self)
|
|
162
|
+
# cache it
|
|
163
|
+
setattr(self, attr, _mm)
|
|
164
|
+
return _mm
|
|
165
|
+
else:
|
|
166
|
+
return _a
|
|
167
|
+
|
|
168
|
+
def base_ring(self):
|
|
169
|
+
"""
|
|
170
|
+
Return the base ring.
|
|
171
|
+
|
|
172
|
+
The backend's base ring can be overridden. It is best to run
|
|
173
|
+
the tests with GLPK and override the base ring to ``QQ``. Then
|
|
174
|
+
default input to backend methods, prepared by
|
|
175
|
+
:class:`MixedIntegerLinearProgram`, depends on the base ring.
|
|
176
|
+
This way input will be rational and so suitable for both exact
|
|
177
|
+
and inexact methods; whereas output will be float and will thus
|
|
178
|
+
trigger :func:`assertAlmostEqual` tests.
|
|
179
|
+
|
|
180
|
+
EXAMPLES::
|
|
181
|
+
|
|
182
|
+
sage: import sage.numerical.backends.logging_backend
|
|
183
|
+
sage: from sage.numerical.backends.logging_backend import LoggingBackend
|
|
184
|
+
sage: from sage.numerical.backends.generic_backend import get_solver
|
|
185
|
+
sage: b = get_solver(solver = "GLPK")
|
|
186
|
+
sage: lb = LoggingBackend(backend=b)
|
|
187
|
+
sage: lb.base_ring()
|
|
188
|
+
Real Double Field
|
|
189
|
+
sage: from sage.rings.rational_field import QQ
|
|
190
|
+
sage: lb = LoggingBackend(backend=b, base_ring=QQ)
|
|
191
|
+
sage: lb.base_ring()
|
|
192
|
+
Rational Field
|
|
193
|
+
"""
|
|
194
|
+
if self._base_ring is not None:
|
|
195
|
+
return self._base_ring
|
|
196
|
+
else:
|
|
197
|
+
return self._backend.base_ring()
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# Override all methods that we inherited from GenericBackend
|
|
201
|
+
# by delegating methods
|
|
202
|
+
def _override_attr(attr):
|
|
203
|
+
"""
|
|
204
|
+
Override a method by a delegating method.
|
|
205
|
+
"""
|
|
206
|
+
a = getattr(LoggingBackend, attr)
|
|
207
|
+
if callable(a):
|
|
208
|
+
m = _make_wrapper(GenericBackend(), attr)
|
|
209
|
+
setattr(LoggingBackend, attr, m)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
for attr in dir(LoggingBackend):
|
|
213
|
+
if not attr.startswith("_") and attr not in ("zero", "base_ring"):
|
|
214
|
+
_override_attr(attr)
|
|
215
|
+
|
|
216
|
+
test_method_template = \
|
|
217
|
+
r'''
|
|
218
|
+
@classmethod
|
|
219
|
+
def _test_{name}(cls, tester=None, **options):
|
|
220
|
+
"""
|
|
221
|
+
Run tests on ...
|
|
222
|
+
|
|
223
|
+
TESTS::
|
|
224
|
+
|
|
225
|
+
SAGE: from sage.numerical.backends.generic_backend import GenericBackend
|
|
226
|
+
SAGE: p = GenericBackend()
|
|
227
|
+
SAGE: p._test_{name}()
|
|
228
|
+
Traceback (most recent call last):
|
|
229
|
+
...
|
|
230
|
+
NotImplementedError
|
|
231
|
+
"""
|
|
232
|
+
p = cls() # fresh instance of the backend
|
|
233
|
+
if tester is None:
|
|
234
|
+
tester = p._tester(**options)
|
|
235
|
+
'''.replace("SAGE:", "sage:") # so that the above test does not get picked up by the doctester
|
|
236
|
+
|
|
237
|
+
from sage.rings.rational_field import QQ
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def LoggingBackendFactory(solver=None, printing=True, doctest_file=None, test_method_file=None,
|
|
241
|
+
test_method=None, base_ring=QQ):
|
|
242
|
+
"""
|
|
243
|
+
Factory that constructs a :class:`LoggingBackend` for debugging and testing.
|
|
244
|
+
|
|
245
|
+
An instance of it can be passed as the solver argument of
|
|
246
|
+
:func:`sage.numerical.backends.generic_backend.get_solver` and
|
|
247
|
+
:class:`MixedIntegerLinearProgram`.
|
|
248
|
+
|
|
249
|
+
EXAMPLES:
|
|
250
|
+
|
|
251
|
+
Assume that we have the following function that does some
|
|
252
|
+
computation using :class:`MixedIntegerLinearProgram` (or MIP
|
|
253
|
+
backend methods), and suppose we have observed that it works with
|
|
254
|
+
the GLPK backend, but not with the COIN backend::
|
|
255
|
+
|
|
256
|
+
sage: def compute_something(solver='GLPK'):
|
|
257
|
+
....: from sage.numerical.mip import MIPSolverException
|
|
258
|
+
....: mip = MixedIntegerLinearProgram(solver=solver)
|
|
259
|
+
....: lb = mip.get_backend()
|
|
260
|
+
....: lb.add_variable(obj=42, name='Helloooooo')
|
|
261
|
+
....: lb.add_variable(obj=1789)
|
|
262
|
+
....: try:
|
|
263
|
+
....: lb.solve()
|
|
264
|
+
....: except MIPSolverException:
|
|
265
|
+
....: return 4711
|
|
266
|
+
....: else:
|
|
267
|
+
....: return 91
|
|
268
|
+
|
|
269
|
+
We can investigate what the backend methods are doing by running a
|
|
270
|
+
:class:`LoggingBackend` in its in-terminal logging mode::
|
|
271
|
+
|
|
272
|
+
sage: import sage.numerical.backends.logging_backend
|
|
273
|
+
sage: from sage.numerical.backends.logging_backend import LoggingBackendFactory
|
|
274
|
+
sage: compute_something(solver = LoggingBackendFactory(solver='GLPK'))
|
|
275
|
+
# p = get_solver(solver='GLPK')
|
|
276
|
+
# p.add_variable(obj=42, name='Helloooooo')
|
|
277
|
+
# result: 0
|
|
278
|
+
# p.add_variable(obj=1789)
|
|
279
|
+
# result: 1
|
|
280
|
+
# p.solve()
|
|
281
|
+
# exception: GLPK: The LP (relaxation) problem has no dual feasible solution
|
|
282
|
+
4711
|
|
283
|
+
|
|
284
|
+
By replacing 'GLPK' by 'COIN' above, we can then compare the two
|
|
285
|
+
logs and see where they differ.
|
|
286
|
+
|
|
287
|
+
Imagine that we have now fixed the bug in the COIN backend, and we
|
|
288
|
+
want to add a doctest that documents this fact. We do not want to
|
|
289
|
+
call ``compute_something`` in the doctest, but rather just have a
|
|
290
|
+
sequence of calls to backend methods.
|
|
291
|
+
|
|
292
|
+
We can have the doctest autogenerated by running a
|
|
293
|
+
:class:`LoggingBackend` in its doctest-writing mode::
|
|
294
|
+
|
|
295
|
+
sage: fname = tmp_filename()
|
|
296
|
+
sage: compute_something(solver = LoggingBackendFactory(solver='GLPK', printing=False,
|
|
297
|
+
....: doctest_file=fname))
|
|
298
|
+
4711
|
|
299
|
+
sage: with open(fname) as f:
|
|
300
|
+
....: for line in f.readlines(): _ = sys.stdout.write('|{}'.format(line))
|
|
301
|
+
| sage: p = get_solver(solver='GLPK')
|
|
302
|
+
| sage: p.add_variable(obj=42, name='Helloooooo')
|
|
303
|
+
| 0
|
|
304
|
+
| sage: p.add_variable(obj=1789)
|
|
305
|
+
| 1
|
|
306
|
+
| sage: p.solve()
|
|
307
|
+
| Traceback (most recent call last):
|
|
308
|
+
| ...
|
|
309
|
+
| MIPSolverException: GLPK: The LP (relaxation) problem has no dual feasible solution
|
|
310
|
+
|
|
311
|
+
We then copy from the generated file and paste into the source
|
|
312
|
+
code of the COIN backend.
|
|
313
|
+
|
|
314
|
+
If this test seems valuable enough that all backends should be
|
|
315
|
+
tested against it, we should create a test method instead of a
|
|
316
|
+
docstring.
|
|
317
|
+
|
|
318
|
+
We can have the test method autogenerated by running a
|
|
319
|
+
:class:`LoggingBackend` in its test-method-writing mode::
|
|
320
|
+
|
|
321
|
+
sage: fname = tmp_filename()
|
|
322
|
+
sage: compute_something(solver= LoggingBackendFactory(solver='GLPK', printing=False,
|
|
323
|
+
....: test_method_file=fname,
|
|
324
|
+
....: test_method='something'))
|
|
325
|
+
4711
|
|
326
|
+
sage: with open(fname) as f:
|
|
327
|
+
....: for line in f.readlines(): _ = sys.stdout.write('|{}'.format(line))
|
|
328
|
+
|
|
|
329
|
+
| @classmethod
|
|
330
|
+
| def _test_something(cls, tester=None, **options):
|
|
331
|
+
| ...
|
|
332
|
+
| Run tests on ...
|
|
333
|
+
|
|
|
334
|
+
| TESTS::
|
|
335
|
+
|
|
|
336
|
+
| sage: from sage.numerical.backends.generic_backend import GenericBackend
|
|
337
|
+
| sage: p = GenericBackend()
|
|
338
|
+
| sage: p._test_something()
|
|
339
|
+
| Traceback (most recent call last):
|
|
340
|
+
| ...
|
|
341
|
+
| NotImplementedError
|
|
342
|
+
| ...
|
|
343
|
+
| p = cls() # fresh instance of the backend
|
|
344
|
+
| if tester is None:
|
|
345
|
+
| tester = p._tester(**options)
|
|
346
|
+
| tester.assertEqual(p.add_variable(obj=42, name='Helloooooo'), 0)
|
|
347
|
+
| tester.assertEqual(p.add_variable(obj=1789), 1)
|
|
348
|
+
| with tester.assertRaises(MIPSolverException) as cm:
|
|
349
|
+
| p.solve()
|
|
350
|
+
|
|
351
|
+
We then copy from the generated file and paste into the source
|
|
352
|
+
code of the generic backend, where all test methods are defined.
|
|
353
|
+
|
|
354
|
+
If ``test_method_file`` is not provided, a default output file name
|
|
355
|
+
will be computed from ``test_method``.
|
|
356
|
+
"""
|
|
357
|
+
|
|
358
|
+
if test_method is not None:
|
|
359
|
+
if test_method_file is None:
|
|
360
|
+
# Construct output file name from method name.
|
|
361
|
+
test_method_file = "test_{}.py".format(test_method)
|
|
362
|
+
else:
|
|
363
|
+
test_method = 'CHANGE'
|
|
364
|
+
# Will have to be edited by user in generated file.
|
|
365
|
+
|
|
366
|
+
if doctest_file is not None:
|
|
367
|
+
doctest = open(doctest_file, "w", 1) # line-buffered
|
|
368
|
+
else:
|
|
369
|
+
doctest = None
|
|
370
|
+
if test_method_file is not None:
|
|
371
|
+
test_method_output = open(test_method_file, "w", 1) # line-buffered
|
|
372
|
+
else:
|
|
373
|
+
test_method_output = None
|
|
374
|
+
|
|
375
|
+
def logging_solver(**kwds):
|
|
376
|
+
"""
|
|
377
|
+
Create an instance of :class:`LoggingBackend`.
|
|
378
|
+
"""
|
|
379
|
+
construct = "p = {}".format(_format_function_call('get_solver', solver=solver, **kwds))
|
|
380
|
+
if printing:
|
|
381
|
+
print("# {}".format(construct))
|
|
382
|
+
if doctest is not None:
|
|
383
|
+
doctest.write(" sage: {}\n".format(construct))
|
|
384
|
+
if test_method_output is not None:
|
|
385
|
+
test_method_output.write(test_method_template.format(name=test_method))
|
|
386
|
+
from sage.numerical.backends.generic_backend import get_solver
|
|
387
|
+
return LoggingBackend(backend=get_solver(solver=solver, **kwds),
|
|
388
|
+
printing=printing, doctest=doctest, test_method=test_method_output,
|
|
389
|
+
base_ring=base_ring)
|
|
390
|
+
|
|
391
|
+
return logging_solver
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
from sage.numerical.backends.generic_sdp_backend cimport GenericSDPBackend
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
cdef class MatrixSDPBackend(GenericSDPBackend):
|
|
6
|
+
|
|
7
|
+
cdef list objective_function
|
|
8
|
+
cdef list coeffs_matrix
|
|
9
|
+
cdef bint is_maximize
|
|
10
|
+
|
|
11
|
+
cdef list row_name_var
|
|
12
|
+
cdef list col_name_var
|
|
13
|
+
cdef str name
|
|
14
|
+
|
|
15
|
+
cdef object _base_ring
|