gamspy 1.18.3__py3-none-any.whl → 1.18.4__py3-none-any.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.
- gamspy/__init__.py +2 -14
- gamspy/_algebra/condition.py +59 -0
- gamspy/_algebra/domain.py +10 -0
- gamspy/_algebra/expression.py +29 -8
- gamspy/_algebra/number.py +9 -0
- gamspy/_cli/install.py +18 -13
- gamspy/_cli/show.py +0 -9
- gamspy/_container.py +246 -62
- gamspy/_model.py +84 -17
- gamspy/_options.py +91 -13
- gamspy/_serialization.py +13 -1
- gamspy/_symbols/alias.py +8 -2
- gamspy/_symbols/equation.py +157 -48
- gamspy/_symbols/parameter.py +72 -33
- gamspy/_symbols/set.py +121 -59
- gamspy/_symbols/variable.py +121 -37
- gamspy/utils.py +19 -0
- {gamspy-1.18.3.dist-info → gamspy-1.18.4.dist-info}/METADATA +1 -1
- {gamspy-1.18.3.dist-info → gamspy-1.18.4.dist-info}/RECORD +23 -23
- {gamspy-1.18.3.dist-info → gamspy-1.18.4.dist-info}/WHEEL +0 -0
- {gamspy-1.18.3.dist-info → gamspy-1.18.4.dist-info}/entry_points.txt +0 -0
- {gamspy-1.18.3.dist-info → gamspy-1.18.4.dist-info}/licenses/LICENSE +0 -0
- {gamspy-1.18.3.dist-info → gamspy-1.18.4.dist-info}/top_level.txt +0 -0
gamspy/__init__.py
CHANGED
|
@@ -22,20 +22,8 @@ from gamspy._backend.engine import EngineClient
|
|
|
22
22
|
from gamspy._backend.neos import NeosClient
|
|
23
23
|
from gamspy._config import _set_default_options, get_option, set_options
|
|
24
24
|
from gamspy._container import Container
|
|
25
|
-
from gamspy._model import
|
|
26
|
-
|
|
27
|
-
Model,
|
|
28
|
-
ModelStatus,
|
|
29
|
-
Problem,
|
|
30
|
-
Sense,
|
|
31
|
-
SolveStatus,
|
|
32
|
-
)
|
|
33
|
-
from gamspy._options import (
|
|
34
|
-
ConvertOptions,
|
|
35
|
-
FreezeOptions,
|
|
36
|
-
ModelInstanceOptions,
|
|
37
|
-
Options,
|
|
38
|
-
)
|
|
25
|
+
from gamspy._model import FileFormat, Model, ModelStatus, Problem, Sense, SolveStatus
|
|
26
|
+
from gamspy._options import ConvertOptions, FreezeOptions, Options
|
|
39
27
|
from gamspy._serialization import deserialize, serialize
|
|
40
28
|
from gamspy._symbols import (
|
|
41
29
|
Alias,
|
gamspy/_algebra/condition.py
CHANGED
|
@@ -34,6 +34,18 @@ class Condition(operable.Operable):
|
|
|
34
34
|
----------
|
|
35
35
|
symbol: ImplicitSymbol | Expression
|
|
36
36
|
Reference to the symbol to be conditioned.
|
|
37
|
+
|
|
38
|
+
Examples
|
|
39
|
+
--------
|
|
40
|
+
>>> import gamspy as gp
|
|
41
|
+
>>> m = gp.Container()
|
|
42
|
+
>>> i = gp.Set(m, "i", records=["i1", "i2", "i3"])
|
|
43
|
+
>>> a = gp.Parameter(m, "a", domain=i, records=[("i1", 10), ("i2", 20), ("i3", 30)])
|
|
44
|
+
>>> # Conditional assignment: Set values to 1 where they exceed 15
|
|
45
|
+
>>> a[i].where[a[i] > 15] = 1
|
|
46
|
+
>>> a.records.values.tolist()
|
|
47
|
+
[['i1', 10.0], ['i2', 1.0], ['i3', 1.0]]
|
|
48
|
+
|
|
37
49
|
"""
|
|
38
50
|
|
|
39
51
|
def __init__(
|
|
@@ -124,6 +136,24 @@ class Condition(operable.Operable):
|
|
|
124
136
|
|
|
125
137
|
@property
|
|
126
138
|
def records(self) -> pd.DataFrame | None:
|
|
139
|
+
"""
|
|
140
|
+
The records of the condition.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
pd.DataFrame | None
|
|
145
|
+
|
|
146
|
+
Examples
|
|
147
|
+
--------
|
|
148
|
+
>>> import gamspy as gp
|
|
149
|
+
>>> m = gp.Container()
|
|
150
|
+
>>> i = gp.Set(m, "i", records=["i1", "i2", "i3"])
|
|
151
|
+
>>> a = gp.Parameter(m, "a", domain=i, records=[("i1", 10), ("i2", 20), ("i3", 5)])
|
|
152
|
+
>>> condition = a[i].where[a[i] > 9]
|
|
153
|
+
>>> condition.records.values.tolist()
|
|
154
|
+
[['i1', 10.0], ['i2', 20.0]]
|
|
155
|
+
|
|
156
|
+
"""
|
|
127
157
|
assert self.container is not None
|
|
128
158
|
assert self.domain is not None
|
|
129
159
|
if isinstance(
|
|
@@ -160,6 +190,24 @@ class Condition(operable.Operable):
|
|
|
160
190
|
return temp_sym.records
|
|
161
191
|
|
|
162
192
|
def gamsRepr(self) -> str:
|
|
193
|
+
"""
|
|
194
|
+
Representation of this condition in GAMS.
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
str
|
|
199
|
+
|
|
200
|
+
Examples
|
|
201
|
+
--------
|
|
202
|
+
>>> import gamspy as gp
|
|
203
|
+
>>> m = gp.Container()
|
|
204
|
+
>>> i = gp.Set(m, "i", records=["i1", "i2"])
|
|
205
|
+
>>> a = gp.Parameter(m, "a", domain=i)
|
|
206
|
+
>>> condition = a[i].where[a[i] > 5]
|
|
207
|
+
>>> condition.gamsRepr()
|
|
208
|
+
'a(i) $ (a(i) > 5)'
|
|
209
|
+
|
|
210
|
+
"""
|
|
163
211
|
condition_str = (
|
|
164
212
|
self.condition.gamsRepr() # type: ignore
|
|
165
213
|
if hasattr(self.condition, "gamsRepr")
|
|
@@ -185,6 +233,17 @@ class Condition(operable.Operable):
|
|
|
185
233
|
Returns
|
|
186
234
|
-------
|
|
187
235
|
str
|
|
236
|
+
|
|
237
|
+
Examples
|
|
238
|
+
--------
|
|
239
|
+
>>> import gamspy as gp
|
|
240
|
+
>>> m = gp.Container()
|
|
241
|
+
>>> i = gp.Set(m, "i", records=["i1", "i2"])
|
|
242
|
+
>>> a = gp.Parameter(m, "a", domain=i)
|
|
243
|
+
>>> condition = a[i].where[a[i] > 2]
|
|
244
|
+
>>> condition.latexRepr()
|
|
245
|
+
'a_{i} ~ | ~ a_{i} > 2'
|
|
246
|
+
|
|
188
247
|
"""
|
|
189
248
|
condition_str = (
|
|
190
249
|
self.condition.latexRepr() # type: ignore
|
gamspy/_algebra/domain.py
CHANGED
|
@@ -89,5 +89,15 @@ class Domain:
|
|
|
89
89
|
Returns
|
|
90
90
|
-------
|
|
91
91
|
str
|
|
92
|
+
|
|
93
|
+
Examples
|
|
94
|
+
--------
|
|
95
|
+
>>> from gamspy import Container, Domain, Set
|
|
96
|
+
>>> m = Container()
|
|
97
|
+
>>> X = Set(m, name="x", records=[f"I{i}" for i in range(1, 22)])
|
|
98
|
+
>>> Y = Set(m, name="y", records=[f"J{j}" for j in range(1, 22)])
|
|
99
|
+
>>> print(Domain(X, Y).latexRepr())
|
|
100
|
+
x,y
|
|
101
|
+
|
|
92
102
|
"""
|
|
93
103
|
return utils._get_domain_str(self.sets, latex=True)[1:-1]
|
gamspy/_algebra/expression.py
CHANGED
|
@@ -293,16 +293,19 @@ def create_latex_expression(root_node: Expression) -> str:
|
|
|
293
293
|
|
|
294
294
|
class Expression(operable.Operable):
|
|
295
295
|
"""
|
|
296
|
-
|
|
296
|
+
Represents an expression involving two operands and an operator.
|
|
297
|
+
|
|
298
|
+
This class constructs a binary expression tree that can be evaluated or
|
|
299
|
+
translated into GAMS syntax.
|
|
297
300
|
|
|
298
301
|
Parameters
|
|
299
302
|
----------
|
|
300
|
-
left:
|
|
301
|
-
Left operand
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
right:
|
|
305
|
-
Right operand
|
|
303
|
+
left : OperableType | ImplicitEquation | None
|
|
304
|
+
Left operand.
|
|
305
|
+
operator : str
|
|
306
|
+
The operator symbol (e.g., '+', '-', '*', '=', 'eq').
|
|
307
|
+
right : OperableType | str | None
|
|
308
|
+
Right operand.
|
|
306
309
|
|
|
307
310
|
Examples
|
|
308
311
|
--------
|
|
@@ -529,11 +532,22 @@ class Expression(operable.Operable):
|
|
|
529
532
|
|
|
530
533
|
def latexRepr(self) -> str:
|
|
531
534
|
"""
|
|
532
|
-
|
|
535
|
+
Returns the LaTeX representation of this Expression.
|
|
533
536
|
|
|
534
537
|
Returns
|
|
535
538
|
-------
|
|
536
539
|
str
|
|
540
|
+
The LaTeX string.
|
|
541
|
+
|
|
542
|
+
Examples
|
|
543
|
+
--------
|
|
544
|
+
>>> import gamspy as gp
|
|
545
|
+
>>> m = gp.Container()
|
|
546
|
+
>>> a = gp.Parameter(m, name="a")
|
|
547
|
+
>>> b = gp.Parameter(m, name="b")
|
|
548
|
+
>>> (a + b).latexRepr()
|
|
549
|
+
'a + b'
|
|
550
|
+
|
|
537
551
|
"""
|
|
538
552
|
return create_latex_expression(self)
|
|
539
553
|
|
|
@@ -745,6 +759,13 @@ class Expression(operable.Operable):
|
|
|
745
759
|
|
|
746
760
|
|
|
747
761
|
class SetExpression(Expression):
|
|
762
|
+
"""
|
|
763
|
+
Represents an expression involving set operations.
|
|
764
|
+
|
|
765
|
+
This class handles operations specifically for Sets and Aliases, such as
|
|
766
|
+
union, intersection, difference, and complement.
|
|
767
|
+
"""
|
|
768
|
+
|
|
748
769
|
def __init__(
|
|
749
770
|
self,
|
|
750
771
|
left: OperableType,
|
gamspy/_algebra/number.py
CHANGED
gamspy/_cli/install.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import importlib
|
|
4
|
+
import json
|
|
4
5
|
import os
|
|
5
6
|
import shutil
|
|
6
7
|
import subprocess
|
|
7
8
|
import sys
|
|
9
|
+
from importlib.metadata import distribution
|
|
8
10
|
from typing import TYPE_CHECKING, Annotated
|
|
9
11
|
|
|
10
12
|
import certifi
|
|
@@ -193,8 +195,20 @@ def license(
|
|
|
193
195
|
shutil.copy(license, license_path)
|
|
194
196
|
|
|
195
197
|
|
|
198
|
+
def is_editable(package_name: str) -> bool:
|
|
199
|
+
dist = distribution(package_name)
|
|
200
|
+
text = dist.read_text("direct_url.json")
|
|
201
|
+
if not text:
|
|
202
|
+
return False
|
|
203
|
+
data = json.loads(text)
|
|
204
|
+
return data.get("dir_info", {}).get("editable", False)
|
|
205
|
+
|
|
206
|
+
|
|
196
207
|
def append_dist_info(files, gamspy_base_dir: str):
|
|
197
208
|
"""Updates dist-info/RECORD in site-packages for pip uninstall"""
|
|
209
|
+
if is_editable("gamspy"):
|
|
210
|
+
return
|
|
211
|
+
|
|
198
212
|
import gamspy as gp
|
|
199
213
|
|
|
200
214
|
gamspy_path: str = gp.__path__[0]
|
|
@@ -277,29 +291,20 @@ def solver(
|
|
|
277
291
|
if not skip_pip_install:
|
|
278
292
|
solver_version = gamspy_base.__version__
|
|
279
293
|
# install specified solver
|
|
280
|
-
if use_uv
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
"pip",
|
|
284
|
-
"install",
|
|
285
|
-
f"gamspy-{solver_name}=={solver_version}",
|
|
286
|
-
"--force-reinstall",
|
|
287
|
-
]
|
|
288
|
-
else:
|
|
289
|
-
command = [
|
|
290
|
-
sys.executable,
|
|
291
|
-
"-m",
|
|
294
|
+
command = ["uv"] if use_uv else [sys.executable, "-m"]
|
|
295
|
+
command.extend(
|
|
296
|
+
[
|
|
292
297
|
"pip",
|
|
293
298
|
"install",
|
|
294
299
|
f"gamspy-{solver_name}=={solver_version}",
|
|
295
300
|
"--force-reinstall",
|
|
296
301
|
]
|
|
302
|
+
)
|
|
297
303
|
try:
|
|
298
304
|
_ = subprocess.run(
|
|
299
305
|
command,
|
|
300
306
|
check=True,
|
|
301
307
|
encoding="utf-8",
|
|
302
|
-
stderr=subprocess.PIPE,
|
|
303
308
|
env=environment_variables,
|
|
304
309
|
)
|
|
305
310
|
except subprocess.CalledProcessError as e:
|
gamspy/_cli/show.py
CHANGED
|
@@ -36,12 +36,10 @@ SOLVER_PAGE_MAP = {
|
|
|
36
36
|
"CONVERT": "https://www.gams.com/latest/docs/S_CONVERT.html",
|
|
37
37
|
"COPT": "https://www.gams.com/latest/docs/S_COPT.html",
|
|
38
38
|
"CPLEX": "https://www.gams.com/latest/docs/S_CPLEX.html",
|
|
39
|
-
"DE": "https://www.gams.com/latest/docs/S_DE.html",
|
|
40
39
|
"DECISC": "https://www.gams.com/latest/docs/S_DECIS.html",
|
|
41
40
|
"DECISM": "https://www.gams.com/latest/docs/S_DECIS.html",
|
|
42
41
|
"DICOPT": "https://www.gams.com/latest/docs/S_DICOPT.html",
|
|
43
42
|
"EXAMINER": "https://www.gams.com/latest/docs/S_EXAMINER.html",
|
|
44
|
-
"GAMSCHK": "https://www.gams.com/latest/docs/S_GAMSCHK.html",
|
|
45
43
|
"GUROBI": "https://www.gams.com/latest/docs/S_GUROBI.html",
|
|
46
44
|
"HIGHS": "https://www.gams.com/latest/docs/S_HIGHS.html",
|
|
47
45
|
"IPOPT": "https://www.gams.com/latest/docs/S_IPOPT.html",
|
|
@@ -51,13 +49,11 @@ SOLVER_PAGE_MAP = {
|
|
|
51
49
|
"KNITRO": "https://www.gams.com/latest/docs/S_KNITRO.html",
|
|
52
50
|
"LINDO": "https://www.gams.com/latest/docs/S_LINDO.html",
|
|
53
51
|
"LINDOGLOBAL": "https://www.gams.com/latest/docs/S_LINDO.html",
|
|
54
|
-
"LOGMIP": "https://www.gams.com/latest/docs/S_JAMS.html",
|
|
55
52
|
"MILES": "https://www.gams.com/latest/docs/S_MILES.html",
|
|
56
53
|
"MINOS": "https://www.gams.com/latest/docs/S_MINOS.html",
|
|
57
54
|
"MOSEK": "https://www.gams.com/latest/docs/S_MOSEK.html",
|
|
58
55
|
"MPSGE": "https://www.gams.com/50/docs/UG_MPSGE_Intro.html",
|
|
59
56
|
"NLPEC": "https://www.gams.com/latest/docs/S_NLPEC.html",
|
|
60
|
-
"ODHCPLEX": "https://www.gams.com/latest/docs/S_ODHCPLEX.html",
|
|
61
57
|
"PATH": "https://www.gams.com/latest/docs/S_PATH.html",
|
|
62
58
|
"QUADMINOS": "https://www.gams.com/latest/docs/S_MINOS.html",
|
|
63
59
|
"RESHOP": "https://www.gams.com/latest/docs/S_RESHOP.html",
|
|
@@ -80,28 +76,23 @@ EVALUATIONS: dict[str, Callable[[dict[str, bool], bool], bool]] = {
|
|
|
80
76
|
"CONVERT": lambda cm, ia: True,
|
|
81
77
|
"COPT": lambda cm, ia: cm["CT"] or cm["CK"],
|
|
82
78
|
"CPLEX": lambda cm, ia: cm["CP"] or cm["CL"],
|
|
83
|
-
"DE": lambda cm, ia: True,
|
|
84
79
|
"DECISC": lambda cm, ia: cm["DE"] and (cm["CP"] or cm["CL"]),
|
|
85
80
|
"DECISM": lambda cm, ia: cm["DE"] and cm["M5"],
|
|
86
81
|
"DICOPT": lambda cm, ia: cm["DI"],
|
|
87
82
|
"EXAMINER": lambda cm, ia: True,
|
|
88
|
-
"GAMSCHK": lambda cm, ia: True,
|
|
89
83
|
"GUROBI": lambda cm, ia: cm["GU"] or cm["GL"],
|
|
90
84
|
"HIGHS": lambda cm, ia: cm["HI"] or ia,
|
|
91
85
|
"IPOPT": lambda cm, ia: True,
|
|
92
86
|
"IPOPTH": lambda cm, ia: cm["IP"] or ia,
|
|
93
|
-
"JAMS": lambda cm, ia: True,
|
|
94
87
|
"KESTREL": lambda cm, ia: True,
|
|
95
88
|
"KNITRO": lambda cm, ia: cm["KN"],
|
|
96
89
|
"LINDO": lambda cm, ia: cm["LD"],
|
|
97
90
|
"LINDOGLOBAL": lambda cm, ia: cm["LD"] or cm["LI"],
|
|
98
|
-
"LOGMIP": lambda cm, ia: True,
|
|
99
91
|
"MILES": lambda cm, ia: True,
|
|
100
92
|
"MINOS": lambda cm, ia: cm["M5"],
|
|
101
93
|
"MOSEK": lambda cm, ia: cm["MB"] or cm["ML"],
|
|
102
94
|
"MPSGE": lambda cm, ia: cm["GE"],
|
|
103
95
|
"NLPEC": lambda cm, ia: True,
|
|
104
|
-
"ODHCPLEX": lambda cm, ia: (ia or cm["OD"]) and (cm["CP"] or cm["CL"]),
|
|
105
96
|
"PATH": lambda cm, ia: cm["PT"],
|
|
106
97
|
"QUADMINOS": lambda cm, ia: cm["M5"],
|
|
107
98
|
"RESHOP": lambda cm, ia: True,
|