certlin 1.2__tar.gz → 1.3__tar.gz
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.
- {certlin-1.2 → certlin-1.3}/PKG-INFO +5 -3
- {certlin-1.2 → certlin-1.3}/README.md +4 -2
- {certlin-1.2 → certlin-1.3}/certlin/__init__.py +1 -1
- {certlin-1.2 → certlin-1.3}/certlin/intervals.py +28 -27
- {certlin-1.2 → certlin-1.3}/certlin/linear_inequality_systems.py +31 -31
- {certlin-1.2 → certlin-1.3}/certlin/utility.py +4 -4
- {certlin-1.2 → certlin-1.3}/certlin.egg-info/PKG-INFO +5 -3
- {certlin-1.2 → certlin-1.3}/setup.py +1 -1
- {certlin-1.2 → certlin-1.3}/LICENSE +0 -0
- {certlin-1.2 → certlin-1.3}/certlin.egg-info/SOURCES.txt +0 -0
- {certlin-1.2 → certlin-1.3}/certlin.egg-info/dependency_links.txt +0 -0
- {certlin-1.2 → certlin-1.3}/certlin.egg-info/requires.txt +0 -0
- {certlin-1.2 → certlin-1.3}/certlin.egg-info/top_level.txt +0 -0
- {certlin-1.2 → certlin-1.3}/pyproject.toml +0 -0
- {certlin-1.2 → certlin-1.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: certlin
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3
|
|
4
4
|
Summary: SageMath package for linear inequality systems and certifying (un)solvability
|
|
5
5
|
Home-page: https://github.com/MarcusAichmayr/certlin
|
|
6
6
|
Author: Marcus S. Aichmayr
|
|
@@ -33,7 +33,7 @@ Dynamic: provides-extra
|
|
|
33
33
|
Dynamic: requires-dist
|
|
34
34
|
Dynamic: summary
|
|
35
35
|
|
|
36
|
-
#
|
|
36
|
+
# CertLin
|
|
37
37
|
|
|
38
38
|
## Description
|
|
39
39
|
|
|
@@ -50,6 +50,8 @@ LICENSE file), either version 3 or (at your option) any later version
|
|
|
50
50
|
|
|
51
51
|
Sage 10.0 or later is recommended.
|
|
52
52
|
|
|
53
|
+
The package [elementary_vectors](https://github.com/MarcusAichmayr/elementary_vectors) is required.
|
|
54
|
+
|
|
53
55
|
## Installation
|
|
54
56
|
|
|
55
57
|
### Install from GitHub (recommended)
|
|
@@ -91,7 +93,7 @@ Change to the root directory of the repository and run:
|
|
|
91
93
|
|
|
92
94
|
The documentation of this package is available on GitHub:
|
|
93
95
|
|
|
94
|
-
https://marcusaichmayr.github.io/certlin/
|
|
96
|
+
https://marcusaichmayr.github.io/certlin/
|
|
95
97
|
|
|
96
98
|
To generate it, run
|
|
97
99
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CertLin
|
|
2
2
|
|
|
3
3
|
## Description
|
|
4
4
|
|
|
@@ -15,6 +15,8 @@ LICENSE file), either version 3 or (at your option) any later version
|
|
|
15
15
|
|
|
16
16
|
Sage 10.0 or later is recommended.
|
|
17
17
|
|
|
18
|
+
The package [elementary_vectors](https://github.com/MarcusAichmayr/elementary_vectors) is required.
|
|
19
|
+
|
|
18
20
|
## Installation
|
|
19
21
|
|
|
20
22
|
### Install from GitHub (recommended)
|
|
@@ -56,7 +58,7 @@ Change to the root directory of the repository and run:
|
|
|
56
58
|
|
|
57
59
|
The documentation of this package is available on GitHub:
|
|
58
60
|
|
|
59
|
-
https://marcusaichmayr.github.io/certlin/
|
|
61
|
+
https://marcusaichmayr.github.io/certlin/
|
|
60
62
|
|
|
61
63
|
To generate it, run
|
|
62
64
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
r"""Certifying linear inequality systems"""
|
|
2
2
|
|
|
3
3
|
#############################################################################
|
|
4
|
-
# Copyright (C)
|
|
4
|
+
# Copyright (C) 2026 #
|
|
5
5
|
# Marcus S. Aichmayr (aichmayr@mathematik.uni-kassel.de) #
|
|
6
6
|
# #
|
|
7
7
|
# Distributed under the terms of the GNU General Public License (GPL) #
|
|
@@ -4,7 +4,7 @@ Intervals
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
#############################################################################
|
|
7
|
-
# Copyright (C)
|
|
7
|
+
# Copyright (C) 2026 #
|
|
8
8
|
# Marcus S. Aichmayr (aichmayr@mathematik.uni-kassel.de) #
|
|
9
9
|
# #
|
|
10
10
|
# Distributed under the terms of the GNU General Public License (GPL) #
|
|
@@ -108,7 +108,7 @@ class Interval(SageObject):
|
|
|
108
108
|
return "{}"
|
|
109
109
|
if self.is_pointed():
|
|
110
110
|
return f"{{{self.lower}}}"
|
|
111
|
-
return f"{'[' if self.lower_closed else '('}{'-oo' if self.
|
|
111
|
+
return f"{'[' if self.lower_closed else '('}{'-oo' if self._is_lower_infinite() else self.lower}, {'+oo' if self._is_upper_infinite() else self.upper}{']' if self.upper_closed else ')'}"
|
|
112
112
|
|
|
113
113
|
def _latex_(self) -> str:
|
|
114
114
|
r"""
|
|
@@ -135,9 +135,9 @@ class Interval(SageObject):
|
|
|
135
135
|
return r"\{" + f"{self.lower}" + r"\}"
|
|
136
136
|
return (
|
|
137
137
|
("[" if self.lower_closed else "(")
|
|
138
|
-
+ (r"-\infty" if self.
|
|
138
|
+
+ (r"-\infty" if self._is_lower_infinite() else f"{self.lower}")
|
|
139
139
|
+ ", "
|
|
140
|
-
+ (r"\infty" if self.
|
|
140
|
+
+ (r"\infty" if self._is_upper_infinite() else f"{self.upper}")
|
|
141
141
|
+ ("]" if self.upper_closed else ")")
|
|
142
142
|
)
|
|
143
143
|
|
|
@@ -158,7 +158,13 @@ class Interval(SageObject):
|
|
|
158
158
|
|
|
159
159
|
def is_unbounded(self) -> bool:
|
|
160
160
|
r"""Return whether the interval is unbounded."""
|
|
161
|
-
return self.
|
|
161
|
+
return self._is_lower_infinite() or self._is_upper_infinite()
|
|
162
|
+
|
|
163
|
+
def _is_lower_infinite(self) -> bool:
|
|
164
|
+
return self.lower == minus_infinity
|
|
165
|
+
|
|
166
|
+
def _is_upper_infinite(self) -> bool:
|
|
167
|
+
return self.upper == Infinity
|
|
162
168
|
|
|
163
169
|
def is_bounded(self) -> bool:
|
|
164
170
|
r"""Return whether the interval is bounded."""
|
|
@@ -251,8 +257,8 @@ class Interval(SageObject):
|
|
|
251
257
|
return self.upper
|
|
252
258
|
if self.is_bounded():
|
|
253
259
|
return (self.lower + self.upper) / 2
|
|
254
|
-
if self.
|
|
255
|
-
if self.
|
|
260
|
+
if self._is_lower_infinite():
|
|
261
|
+
if self._is_upper_infinite():
|
|
256
262
|
return 0
|
|
257
263
|
return self.upper - 1
|
|
258
264
|
return self.lower + 1
|
|
@@ -297,10 +303,10 @@ class Interval(SageObject):
|
|
|
297
303
|
if 0 in self:
|
|
298
304
|
return 0
|
|
299
305
|
if self.upper - self.lower > 1 or floor(self.lower) + 1 in self or ceil(self.upper) - 1 in self:
|
|
300
|
-
if self.
|
|
306
|
+
if self._is_lower_infinite():
|
|
301
307
|
floor_upper = floor(self.upper)
|
|
302
308
|
return floor_upper if floor_upper in self else floor_upper - 1
|
|
303
|
-
if self.
|
|
309
|
+
if self._is_upper_infinite():
|
|
304
310
|
ceil_lower = ceil(self.lower)
|
|
305
311
|
return ceil_lower if ceil_lower in self else ceil_lower + 1
|
|
306
312
|
if self.lower == 0:
|
|
@@ -537,7 +543,7 @@ class Intervals(SageObject):
|
|
|
537
543
|
return cls([Interval.random(ring) for _ in range(length)])
|
|
538
544
|
|
|
539
545
|
@classmethod
|
|
540
|
-
def from_bounds(cls,
|
|
546
|
+
def from_bounds(cls, lower: list, upper: list, lower_closed: bool = True, upper_closed: bool = True) -> Intervals:
|
|
541
547
|
r"""
|
|
542
548
|
Return intervals that are determined by bounds.
|
|
543
549
|
|
|
@@ -553,20 +559,15 @@ class Intervals(SageObject):
|
|
|
553
559
|
sage: Intervals.from_bounds([0, -5, 0], [1, 2, +oo], [True, False, True], [True, True, False])
|
|
554
560
|
[0, 1] x (-5, 2] x [0, +oo)
|
|
555
561
|
"""
|
|
556
|
-
length = len(
|
|
557
|
-
if
|
|
558
|
-
|
|
559
|
-
elif
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
if
|
|
563
|
-
|
|
564
|
-
elif
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
return cls([
|
|
568
|
-
Interval(*bounds)
|
|
569
|
-
for bounds in zip(
|
|
570
|
-
lower_bounds, upper_bounds, lower_bounds_closed, upper_bounds_closed
|
|
571
|
-
)
|
|
572
|
-
])
|
|
562
|
+
length = len(lower)
|
|
563
|
+
if lower_closed is True:
|
|
564
|
+
lower_closed = [True] * length
|
|
565
|
+
elif lower_closed is False:
|
|
566
|
+
lower_closed = [False] * length
|
|
567
|
+
|
|
568
|
+
if upper_closed is True:
|
|
569
|
+
upper_closed = [True] * length
|
|
570
|
+
elif upper_closed is False:
|
|
571
|
+
upper_closed = [False] * length
|
|
572
|
+
|
|
573
|
+
return cls([Interval(*bounds) for bounds in zip(lower, upper, lower_closed, upper_closed)])
|
|
@@ -7,7 +7,7 @@ with methods to find solutions or to certify their nonexistence.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
#############################################################################
|
|
10
|
-
# Copyright (C)
|
|
10
|
+
# Copyright (C) 2026 #
|
|
11
11
|
# Marcus S. Aichmayr (aichmayr@mathematik.uni-kassel.de) #
|
|
12
12
|
# #
|
|
13
13
|
# Distributed under the terms of the GNU General Public License (GPL) #
|
|
@@ -28,7 +28,7 @@ from sage.modules.free_module_element import vector, zero_vector
|
|
|
28
28
|
from sage.rings.infinity import Infinity
|
|
29
29
|
from sage.structure.sage_object import SageObject
|
|
30
30
|
|
|
31
|
-
from elementary_vectors import
|
|
31
|
+
from elementary_vectors import CircuitEnumerator
|
|
32
32
|
from . import Intervals, Interval
|
|
33
33
|
from .utility import CombinationsIncluding, solve_without_division
|
|
34
34
|
|
|
@@ -56,10 +56,10 @@ class LinearInequalitySystem(SageObject):
|
|
|
56
56
|
[2, 5) x [5, +oo) x (0, 8) x (-oo, 5]
|
|
57
57
|
sage: S = LinearInequalitySystem(M, I)
|
|
58
58
|
sage: S
|
|
59
|
-
[1 0] x in
|
|
60
|
-
[0 1] x in
|
|
61
|
-
[1 1] x in
|
|
62
|
-
[0 1] x in
|
|
59
|
+
[1 0] x in [2, 5)
|
|
60
|
+
[0 1] x in [5, +oo)
|
|
61
|
+
[1 1] x in (0, 8)
|
|
62
|
+
[0 1] x in (-oo, 5]
|
|
63
63
|
|
|
64
64
|
We check for solvability::
|
|
65
65
|
|
|
@@ -69,14 +69,14 @@ class LinearInequalitySystem(SageObject):
|
|
|
69
69
|
(5/2, 5)
|
|
70
70
|
sage: S.find_solution_random() # random
|
|
71
71
|
(5/2, 5)
|
|
72
|
-
sage: S.
|
|
72
|
+
sage: S.certify_unsolvability()
|
|
73
73
|
Traceback (most recent call last):
|
|
74
74
|
...
|
|
75
|
-
ValueError: A solution exists
|
|
76
|
-
sage: S.
|
|
75
|
+
ValueError: A solution exists.
|
|
76
|
+
sage: S.certify_unsolvability_random()
|
|
77
77
|
Traceback (most recent call last):
|
|
78
78
|
...
|
|
79
|
-
MaxIterationsReachedError:
|
|
79
|
+
MaxIterationsReachedError: Maximum number of iterations reached. A solution might exist.
|
|
80
80
|
|
|
81
81
|
We rewrite the system as a homogeneous and an inhomogeneous system::
|
|
82
82
|
|
|
@@ -113,14 +113,14 @@ class LinearInequalitySystem(SageObject):
|
|
|
113
113
|
"""
|
|
114
114
|
def __init__(self, matrix: Matrix, intervals: Intervals = None) -> None:
|
|
115
115
|
if intervals is not None and matrix.nrows() != len(intervals):
|
|
116
|
-
raise ValueError("Matrix row count and number of intervals must agree
|
|
116
|
+
raise ValueError("Matrix row count and number of intervals must agree.")
|
|
117
117
|
self._matrix = matrix
|
|
118
118
|
self._intervals = intervals
|
|
119
|
-
self._evs =
|
|
119
|
+
self._evs = CircuitEnumerator(self.matrix.T)
|
|
120
120
|
|
|
121
121
|
def _repr_(self) -> str:
|
|
122
122
|
return "\n".join(
|
|
123
|
-
f"{row_str} x in
|
|
123
|
+
f"{row_str} x in {interval}"
|
|
124
124
|
for row_str, interval in zip(str(self.matrix).splitlines(), self.intervals)
|
|
125
125
|
)
|
|
126
126
|
|
|
@@ -272,7 +272,7 @@ class LinearInequalitySystem(SageObject):
|
|
|
272
272
|
return False
|
|
273
273
|
return True
|
|
274
274
|
|
|
275
|
-
def
|
|
275
|
+
def certify_unsolvability(self, iteration_limit: int = -1) -> vector:
|
|
276
276
|
r"""
|
|
277
277
|
Certify nonexistence of a solution if no solution exists.
|
|
278
278
|
|
|
@@ -291,11 +291,11 @@ class LinearInequalitySystem(SageObject):
|
|
|
291
291
|
.. SEEALSO::
|
|
292
292
|
|
|
293
293
|
* :meth:`certify`
|
|
294
|
-
* :meth:`
|
|
294
|
+
* :meth:`certify_unsolvability_random`
|
|
295
295
|
"""
|
|
296
|
-
return self.
|
|
296
|
+
return self._certify_unsolvability(random=False, reverse=True, iteration_limit=iteration_limit, stop_event=None)
|
|
297
297
|
|
|
298
|
-
def
|
|
298
|
+
def certify_unsolvability_random(self, iteration_limit: int = 10000) -> vector:
|
|
299
299
|
r"""
|
|
300
300
|
Certify nonexistence of a solution using random elementary vectors.
|
|
301
301
|
|
|
@@ -315,11 +315,11 @@ class LinearInequalitySystem(SageObject):
|
|
|
315
315
|
.. SEEALSO::
|
|
316
316
|
|
|
317
317
|
* :meth:`certify`
|
|
318
|
-
* :meth:`
|
|
318
|
+
* :meth:`certify_unsolvability`
|
|
319
319
|
"""
|
|
320
|
-
return self.
|
|
320
|
+
return self._certify_unsolvability(random=True, reverse=False, iteration_limit=iteration_limit, stop_event=None)
|
|
321
321
|
|
|
322
|
-
def
|
|
322
|
+
def _certify_unsolvability(self, random: bool, reverse: bool, iteration_limit: int, stop_event) -> vector:
|
|
323
323
|
r"""
|
|
324
324
|
Certify nonexistence of a solution.
|
|
325
325
|
|
|
@@ -333,12 +333,12 @@ class LinearInequalitySystem(SageObject):
|
|
|
333
333
|
if stop_event is not None and stop_event.is_set():
|
|
334
334
|
raise ProcessStoppedError("Process was stopped because another process found a solution.")
|
|
335
335
|
if iteration_limit != -1 and i >= iteration_limit:
|
|
336
|
-
raise MaxIterationsReachedError("
|
|
336
|
+
raise MaxIterationsReachedError("Maximum number of iterations reached. A solution might exist.")
|
|
337
337
|
if v is None:
|
|
338
338
|
continue
|
|
339
339
|
if not self._exists_orthogonal_vector(v):
|
|
340
340
|
return v
|
|
341
|
-
raise ValueError("A solution exists
|
|
341
|
+
raise ValueError("A solution exists.")
|
|
342
342
|
|
|
343
343
|
def find_solution(self, iteration_limit: int = -1) -> vector:
|
|
344
344
|
r"""
|
|
@@ -408,8 +408,8 @@ class LinearInequalitySystem(SageObject):
|
|
|
408
408
|
|
|
409
409
|
.. SEEALSO::
|
|
410
410
|
|
|
411
|
-
* :meth:`
|
|
412
|
-
* :meth:`
|
|
411
|
+
* :meth:`certify_unsolvability`
|
|
412
|
+
* :meth:`certify_unsolvability_random`
|
|
413
413
|
* :meth:`find_solution`
|
|
414
414
|
* :meth:`find_solution_random`
|
|
415
415
|
"""
|
|
@@ -420,7 +420,7 @@ class LinearInequalitySystem(SageObject):
|
|
|
420
420
|
stop_event = Manager().Event()
|
|
421
421
|
with ProcessPoolExecutor(max_workers=2) as executor:
|
|
422
422
|
futures = {
|
|
423
|
-
executor.submit(self.
|
|
423
|
+
executor.submit(self._certify_unsolvability, random=random, reverse=True, iteration_limit=iteration_limit, stop_event=stop_event): False,
|
|
424
424
|
executor.submit(self._find_solution, random=random, reverse=False, iteration_limit=iteration_limit, stop_event=stop_event): True,
|
|
425
425
|
}
|
|
426
426
|
for future in as_completed(futures):
|
|
@@ -555,7 +555,7 @@ class HomogeneousSystem(LinearInequalitySystem):
|
|
|
555
555
|
if stop_event is not None and stop_event.is_set():
|
|
556
556
|
raise ProcessStoppedError("Process was stopped because another process found a certificate for nonexistence.")
|
|
557
557
|
if iteration_limit != -1 and i >= iteration_limit:
|
|
558
|
-
raise MaxIterationsReachedError("
|
|
558
|
+
raise MaxIterationsReachedError("Maximum number of iterations reached. A solution may not exist.")
|
|
559
559
|
if v is None:
|
|
560
560
|
continue
|
|
561
561
|
for w in [v, -v]:
|
|
@@ -568,7 +568,7 @@ class HomogeneousSystem(LinearInequalitySystem):
|
|
|
568
568
|
return certificate
|
|
569
569
|
break
|
|
570
570
|
|
|
571
|
-
raise ValueError("No solution exists
|
|
571
|
+
raise ValueError("No solution exists.")
|
|
572
572
|
|
|
573
573
|
|
|
574
574
|
class InhomogeneousSystem(LinearInequalitySystem):
|
|
@@ -600,9 +600,9 @@ class InhomogeneousSystem(LinearInequalitySystem):
|
|
|
600
600
|
(False, (1, 0, 1))
|
|
601
601
|
sage: S.certify(random=True)
|
|
602
602
|
(False, (1, 0, 1))
|
|
603
|
-
sage: S.
|
|
603
|
+
sage: S.certify_unsolvability()
|
|
604
604
|
(1, 0, 1)
|
|
605
|
-
sage: S.
|
|
605
|
+
sage: S.certify_unsolvability_random() # random
|
|
606
606
|
(1, 0, 1)
|
|
607
607
|
|
|
608
608
|
Therefore, we cannot find a solution::
|
|
@@ -610,11 +610,11 @@ class InhomogeneousSystem(LinearInequalitySystem):
|
|
|
610
610
|
sage: S.find_solution()
|
|
611
611
|
Traceback (most recent call last):
|
|
612
612
|
...
|
|
613
|
-
ValueError: No solution exists
|
|
613
|
+
ValueError: No solution exists.
|
|
614
614
|
sage: S.find_solution_random()
|
|
615
615
|
Traceback (most recent call last):
|
|
616
616
|
...
|
|
617
|
-
MaxIterationsReachedError:
|
|
617
|
+
MaxIterationsReachedError: Maximum number of iterations reached. A solution may not exist.
|
|
618
618
|
|
|
619
619
|
We compute the dual system and write it in homogeneous form::
|
|
620
620
|
|
|
@@ -4,7 +4,7 @@ Utility functions
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
#############################################################################
|
|
7
|
-
# Copyright (C)
|
|
7
|
+
# Copyright (C) 2026 #
|
|
8
8
|
# Marcus S. Aichmayr (aichmayr@mathematik.uni-kassel.de) #
|
|
9
9
|
# #
|
|
10
10
|
# Distributed under the terms of the GNU General Public License (GPL) #
|
|
@@ -21,7 +21,7 @@ from sage.matrix.constructor import Matrix
|
|
|
21
21
|
from sage.modules.free_module_element import vector
|
|
22
22
|
from sage.structure.sage_object import SageObject
|
|
23
23
|
|
|
24
|
-
from elementary_vectors.
|
|
24
|
+
from elementary_vectors.elements import circuit_generator
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
def solve_without_division(matrix: Matrix, rhs: vector) -> vector:
|
|
@@ -68,12 +68,12 @@ def solve_without_division(matrix: Matrix, rhs: vector) -> vector:
|
|
|
68
68
|
sage: solve_without_division(M, rhs)
|
|
69
69
|
Traceback (most recent call last):
|
|
70
70
|
...
|
|
71
|
-
ValueError: No circuit with nonzero last component found.
|
|
71
|
+
ValueError: No circuit with nonzero last component found. A solution might exist.
|
|
72
72
|
"""
|
|
73
73
|
for circuit in circuit_generator(Matrix.block([[matrix, Matrix.column(rhs)]]), reverse=True):
|
|
74
74
|
if circuit[-1] != 0:
|
|
75
75
|
return -sign(circuit[-1]) * circuit[:-1]
|
|
76
|
-
raise ValueError("No circuit with nonzero last component found.
|
|
76
|
+
raise ValueError("No circuit with nonzero last component found. A solution might exist.")
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
class CombinationsIncluding(SageObject):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: certlin
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3
|
|
4
4
|
Summary: SageMath package for linear inequality systems and certifying (un)solvability
|
|
5
5
|
Home-page: https://github.com/MarcusAichmayr/certlin
|
|
6
6
|
Author: Marcus S. Aichmayr
|
|
@@ -33,7 +33,7 @@ Dynamic: provides-extra
|
|
|
33
33
|
Dynamic: requires-dist
|
|
34
34
|
Dynamic: summary
|
|
35
35
|
|
|
36
|
-
#
|
|
36
|
+
# CertLin
|
|
37
37
|
|
|
38
38
|
## Description
|
|
39
39
|
|
|
@@ -50,6 +50,8 @@ LICENSE file), either version 3 or (at your option) any later version
|
|
|
50
50
|
|
|
51
51
|
Sage 10.0 or later is recommended.
|
|
52
52
|
|
|
53
|
+
The package [elementary_vectors](https://github.com/MarcusAichmayr/elementary_vectors) is required.
|
|
54
|
+
|
|
53
55
|
## Installation
|
|
54
56
|
|
|
55
57
|
### Install from GitHub (recommended)
|
|
@@ -91,7 +93,7 @@ Change to the root directory of the repository and run:
|
|
|
91
93
|
|
|
92
94
|
The documentation of this package is available on GitHub:
|
|
93
95
|
|
|
94
|
-
https://marcusaichmayr.github.io/certlin/
|
|
96
|
+
https://marcusaichmayr.github.io/certlin/
|
|
95
97
|
|
|
96
98
|
To generate it, run
|
|
97
99
|
|
|
@@ -9,7 +9,7 @@ def readfile(filename):
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name="certlin",
|
|
12
|
-
version="1.
|
|
12
|
+
version="1.3",
|
|
13
13
|
description="SageMath package for linear inequality systems and certifying (un)solvability",
|
|
14
14
|
long_description=readfile("README.md"),
|
|
15
15
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|