gamspy 1.17.0__tar.gz → 1.17.1__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.
- {gamspy-1.17.0 → gamspy-1.17.1}/PKG-INFO +3 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/pyproject.toml +7 -3
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/__init__.py +1 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_algebra/expression.py +12 -14
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_algebra/operation.py +3 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/install.py +4 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/show.py +4 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/uninstall.py +4 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_config.py +1 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_container.py +9 -7
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_convert.py +18 -17
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_database.py +1 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_miro.py +1 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_model.py +42 -13
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_model_instance.py +3 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_options.py +6 -6
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_serialization.py +8 -5
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/alias.py +4 -3
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/equation.py +3 -3
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/implicits/implicit_parameter.py +4 -3
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/implicits/implicit_set.py +3 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/implicits/implicit_symbol.py +7 -7
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/implicits/implicit_variable.py +4 -3
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/parameter.py +6 -5
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/set.py +4 -3
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/universe_alias.py +1 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/variable.py +6 -5
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_types.py +0 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_validation.py +5 -5
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/exceptions.py +1 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/maxpool2d.py +5 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/minpool2d.py +5 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/math/__init__.py +2 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/math/activation.py +63 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/math/matrix.py +2 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/math/misc.py +1 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/utils.py +59 -46
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy.egg-info/PKG-INFO +3 -2
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy.egg-info/requires.txt +2 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/tests/test_gamspy.py +1 -1
- {gamspy-1.17.0 → gamspy-1.17.1}/LICENSE +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/README.md +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/README_PYPI.md +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/setup.cfg +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/__main__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_algebra/__init__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_algebra/condition.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_algebra/domain.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_algebra/number.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_algebra/operable.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_backend/__init__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_backend/backend.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_backend/engine.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_backend/local.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_backend/neos.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/__init__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/cli.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/gdx.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/list.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/probe.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/retrieve.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/run.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_cli/util.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_extrinsic.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/__init__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/implicits/__init__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/implicits/implicit_equation.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_symbols/symbol.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/_workspace.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/__init__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/ml/__init__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/ml/decision_tree_struct.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/ml/gradient_boosting.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/ml/random_forest.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/ml/regression_tree.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/__init__.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/avgpool2d.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/conv1d.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/conv2d.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/linear.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/mpool2d.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/nn/torch_sequential.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/piecewise.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/shape.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/formulations/utils.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/math/log_power.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/math/probability.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/math/trigonometric.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/py.typed +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy/version.py +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy.egg-info/SOURCES.txt +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy.egg-info/dependency_links.txt +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy.egg-info/entry_points.txt +0 -0
- {gamspy-1.17.0 → gamspy-1.17.1}/src/gamspy.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gamspy
|
|
3
|
-
Version: 1.17.
|
|
3
|
+
Version: 1.17.1
|
|
4
4
|
Summary: Python-based algebraic modeling interface to GAMS
|
|
5
5
|
Author-email: GAMS Development Corporation <support@gams.com>
|
|
6
6
|
Project-URL: homepage, https://gams.com/sales/gamspy_facts/
|
|
@@ -31,8 +31,9 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
31
31
|
Requires-Python: >=3.10
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
33
33
|
License-File: LICENSE
|
|
34
|
-
Requires-Dist: gamsapi
|
|
34
|
+
Requires-Dist: gamsapi<52.0.0,>=51.1.0
|
|
35
35
|
Requires-Dist: gamspy_base<52.0.0,>=51.1.0
|
|
36
|
+
Requires-Dist: pandas<2.4,>=2.2.2
|
|
36
37
|
Requires-Dist: pydantic>=2.0
|
|
37
38
|
Requires-Dist: requests>=2.28.0
|
|
38
39
|
Requires-Dist: typer>=0.16.0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gamspy"
|
|
7
|
-
version = "1.17.
|
|
7
|
+
version = "1.17.1"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name = "GAMS Development Corporation", email = "support@gams.com" },
|
|
10
10
|
]
|
|
@@ -36,8 +36,9 @@ classifiers = [
|
|
|
36
36
|
"Operating System :: Microsoft :: Windows",
|
|
37
37
|
]
|
|
38
38
|
dependencies = [
|
|
39
|
-
"gamsapi
|
|
39
|
+
"gamsapi >= 51.1.0, < 52.0.0",
|
|
40
40
|
"gamspy_base >= 51.1.0, < 52.0.0",
|
|
41
|
+
"pandas >= 2.2.2, < 2.4",
|
|
41
42
|
"pydantic >= 2.0",
|
|
42
43
|
"requests >= 2.28.0",
|
|
43
44
|
"typer >= 0.16.0",
|
|
@@ -222,7 +223,8 @@ target-version = "py310"
|
|
|
222
223
|
|
|
223
224
|
[tool.ruff.lint]
|
|
224
225
|
select = [
|
|
225
|
-
"E", # pycodestyle
|
|
226
|
+
"E", # pycodestyle error
|
|
227
|
+
"W", # pycodestyle warning
|
|
226
228
|
"F", # Pyflakes
|
|
227
229
|
"UP", # pyupgrade
|
|
228
230
|
"B", # flake8-bugbear
|
|
@@ -231,6 +233,8 @@ select = [
|
|
|
231
233
|
"PIE", # flake8-pie
|
|
232
234
|
"PLR1714", # Consider merging multiple comparisons
|
|
233
235
|
"RUF", # Ruff-specific rules
|
|
236
|
+
"TC", # flake8-type-checking
|
|
237
|
+
"C4", # flake8-comprehensions
|
|
234
238
|
]
|
|
235
239
|
ignore = ["E203", "E501", "E701", "E741", "E743", "W605", "SIM105", "SIM115", "B028", "B006", "RUF005", "RUF022"]
|
|
236
240
|
|
|
@@ -20,8 +20,6 @@ from gamspy.exceptions import ValidationError
|
|
|
20
20
|
from gamspy.math.misc import MathOp
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
|
-
from numbers import Real
|
|
24
|
-
|
|
25
23
|
import pandas as pd
|
|
26
24
|
|
|
27
25
|
from gamspy import Alias, Set
|
|
@@ -150,7 +148,7 @@ def create_gams_expression(root_node: Expression) -> str:
|
|
|
150
148
|
s1.append(node.right)
|
|
151
149
|
|
|
152
150
|
# 2. Build the GAMS expression
|
|
153
|
-
eval_stack: list[tuple[str,
|
|
151
|
+
eval_stack: list[tuple[str, float]] = []
|
|
154
152
|
for node in reversed(post_order_nodes):
|
|
155
153
|
if not isinstance(node, Expression):
|
|
156
154
|
eval_stack.append((get_operand_gams_repr(node), LEAF_PRECEDENCE))
|
|
@@ -237,7 +235,7 @@ def create_latex_expression(root_node: Expression) -> str:
|
|
|
237
235
|
s1.append(node.right)
|
|
238
236
|
|
|
239
237
|
# 2. Build the GAMS expression
|
|
240
|
-
eval_stack: list[tuple[str,
|
|
238
|
+
eval_stack: list[tuple[str, float]] = []
|
|
241
239
|
for node in reversed(post_order_nodes):
|
|
242
240
|
if not isinstance(node, Expression):
|
|
243
241
|
eval_stack.append((get_operand_latex_repr(node), LEAF_PRECEDENCE))
|
|
@@ -406,8 +404,8 @@ class Expression(operable.Operable):
|
|
|
406
404
|
|
|
407
405
|
def __getitem__(self, indices):
|
|
408
406
|
indices = validation.validate_domain(self, indices)
|
|
409
|
-
left_domain =
|
|
410
|
-
right_domain =
|
|
407
|
+
left_domain = list(self._left_domain)
|
|
408
|
+
right_domain = list(self._right_domain)
|
|
411
409
|
for i, s in enumerate(indices):
|
|
412
410
|
for lr, pos in self._shadow_domain[i].indices:
|
|
413
411
|
if lr == "l":
|
|
@@ -638,16 +636,16 @@ class Expression(operable.Operable):
|
|
|
638
636
|
symbols.append(node.alias_with.name)
|
|
639
637
|
|
|
640
638
|
symbols.append(node.name)
|
|
641
|
-
stack
|
|
639
|
+
stack.extend(node.domain)
|
|
642
640
|
node = None
|
|
643
641
|
elif isinstance(node, ImplicitSymbol):
|
|
644
642
|
if node.parent.name not in symbols:
|
|
645
643
|
symbols.append(node.parent.name)
|
|
646
|
-
stack
|
|
647
|
-
stack
|
|
644
|
+
stack.extend(node.domain)
|
|
645
|
+
stack.extend(node.container[node.parent.name].domain)
|
|
648
646
|
node = None
|
|
649
647
|
elif isinstance(node, operation.Operation):
|
|
650
|
-
stack
|
|
648
|
+
stack.extend(node.op_domain)
|
|
651
649
|
node = node.rhs
|
|
652
650
|
elif isinstance(node, condition.Condition):
|
|
653
651
|
stack.append(node.conditioning_on)
|
|
@@ -664,10 +662,10 @@ class Expression(operable.Operable):
|
|
|
664
662
|
if isinstance(node.elements[0], Expression):
|
|
665
663
|
node = node.elements[0]
|
|
666
664
|
else:
|
|
667
|
-
stack
|
|
665
|
+
stack.extend(node.elements)
|
|
668
666
|
node = None
|
|
669
667
|
elif isinstance(node, ExtrinsicFunction):
|
|
670
|
-
stack
|
|
668
|
+
stack.extend(list(node.args))
|
|
671
669
|
node = None
|
|
672
670
|
else:
|
|
673
671
|
node = getattr(node, "right", None)
|
|
@@ -692,12 +690,12 @@ class Expression(operable.Operable):
|
|
|
692
690
|
given_condition = node.condition
|
|
693
691
|
|
|
694
692
|
if isinstance(given_condition, Expression):
|
|
695
|
-
symbols
|
|
693
|
+
symbols.extend(given_condition._find_all_symbols())
|
|
696
694
|
elif isinstance(given_condition, ImplicitSymbol):
|
|
697
695
|
symbols.append(given_condition.parent.name)
|
|
698
696
|
|
|
699
697
|
if isinstance(node, operation.Operation):
|
|
700
|
-
stack
|
|
698
|
+
stack.extend(node.op_domain)
|
|
701
699
|
node = node.rhs
|
|
702
700
|
else:
|
|
703
701
|
node = getattr(node, "right", None)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from collections.abc import Sequence
|
|
4
3
|
from typing import TYPE_CHECKING
|
|
5
4
|
|
|
6
5
|
import gamspy._algebra.condition as condition
|
|
@@ -14,6 +13,8 @@ import gamspy.utils as utils
|
|
|
14
13
|
from gamspy.exceptions import ValidationError
|
|
15
14
|
|
|
16
15
|
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Sequence
|
|
17
|
+
|
|
17
18
|
import pandas as pd
|
|
18
19
|
|
|
19
20
|
from gamspy._algebra import Domain
|
|
@@ -70,7 +71,7 @@ class Operation(operable.Operable):
|
|
|
70
71
|
self.domain.append(x)
|
|
71
72
|
|
|
72
73
|
self.dimension: int = validation.get_dimension(self.domain)
|
|
73
|
-
controlled_domain =
|
|
74
|
+
controlled_domain = list(self._bare_op_domain)
|
|
74
75
|
controlled_domain.extend(getattr(rhs, "controlled_domain", []))
|
|
75
76
|
self.controlled_domain = list(set(controlled_domain))
|
|
76
77
|
|
|
@@ -5,8 +5,7 @@ import os
|
|
|
5
5
|
import shutil
|
|
6
6
|
import subprocess
|
|
7
7
|
import sys
|
|
8
|
-
from
|
|
9
|
-
from typing import Annotated
|
|
8
|
+
from typing import TYPE_CHECKING, Annotated
|
|
10
9
|
|
|
11
10
|
import requests
|
|
12
11
|
import typer
|
|
@@ -16,6 +15,9 @@ from gamspy.exceptions import GamspyException, ValidationError
|
|
|
16
15
|
|
|
17
16
|
from .util import add_solver_entry
|
|
18
17
|
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Iterable
|
|
20
|
+
|
|
19
21
|
app = typer.Typer(
|
|
20
22
|
rich_markup_mode="rich",
|
|
21
23
|
short_help="To install licenses and solvers.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from collections.abc import Callable
|
|
4
3
|
from datetime import datetime, timedelta
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
import rich
|
|
7
7
|
import rich.table
|
|
@@ -10,6 +10,9 @@ import typer
|
|
|
10
10
|
import gamspy.utils as utils
|
|
11
11
|
from gamspy.exceptions import ValidationError
|
|
12
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from collections.abc import Callable
|
|
15
|
+
|
|
13
16
|
app = typer.Typer(
|
|
14
17
|
rich_markup_mode="rich",
|
|
15
18
|
short_help="To show your license and gamspy_base directory.",
|
|
@@ -3,8 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import os
|
|
4
4
|
import subprocess
|
|
5
5
|
import sys
|
|
6
|
-
from
|
|
7
|
-
from typing import Annotated
|
|
6
|
+
from typing import TYPE_CHECKING, Annotated
|
|
8
7
|
|
|
9
8
|
import typer
|
|
10
9
|
|
|
@@ -13,6 +12,9 @@ from gamspy.exceptions import GamspyException, ValidationError
|
|
|
13
12
|
|
|
14
13
|
from .util import remove_solver_entry
|
|
15
14
|
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Iterable
|
|
17
|
+
|
|
16
18
|
app = typer.Typer(
|
|
17
19
|
rich_markup_mode="rich",
|
|
18
20
|
short_help="To uninstall licenses and solvers.",
|
|
@@ -11,7 +11,6 @@ import threading
|
|
|
11
11
|
import time
|
|
12
12
|
import traceback
|
|
13
13
|
import weakref
|
|
14
|
-
from collections.abc import Iterable, Sequence
|
|
15
14
|
from typing import TYPE_CHECKING
|
|
16
15
|
|
|
17
16
|
import gams.transfer as gt
|
|
@@ -25,12 +24,12 @@ from gamspy._config import get_option
|
|
|
25
24
|
from gamspy._extrinsic import ExtrinsicLibrary
|
|
26
25
|
from gamspy._miro import MiroJSONEncoder
|
|
27
26
|
from gamspy._model import Problem, Sense
|
|
28
|
-
from gamspy._options import Options
|
|
29
27
|
from gamspy._workspace import Workspace
|
|
30
28
|
from gamspy.exceptions import FatalError, GamspyException, ValidationError
|
|
31
29
|
|
|
32
30
|
if TYPE_CHECKING:
|
|
33
31
|
import io
|
|
32
|
+
from collections.abc import Iterable, Sequence
|
|
34
33
|
from typing import Any, Literal, TypeAlias
|
|
35
34
|
|
|
36
35
|
from pandas import DataFrame
|
|
@@ -46,6 +45,8 @@ if TYPE_CHECKING:
|
|
|
46
45
|
)
|
|
47
46
|
from gamspy._algebra.expression import Expression
|
|
48
47
|
from gamspy._algebra.operation import Operation
|
|
48
|
+
from gamspy._options import Options
|
|
49
|
+
from gamspy._symbols.implicits import ImplicitVariable
|
|
49
50
|
from gamspy.math.matrix import Dim
|
|
50
51
|
|
|
51
52
|
SymbolType: TypeAlias = Set | Alias | Parameter | Variable | Equation
|
|
@@ -267,7 +268,7 @@ class Container(gt.Container):
|
|
|
267
268
|
):
|
|
268
269
|
self.output = output
|
|
269
270
|
self._gams_string = ""
|
|
270
|
-
self.models: dict[str, Model] =
|
|
271
|
+
self.models: dict[str, Model] = {}
|
|
271
272
|
if IS_MIRO_INIT:
|
|
272
273
|
atexit.register(self._write_miro_files)
|
|
273
274
|
|
|
@@ -339,7 +340,7 @@ class Container(gt.Container):
|
|
|
339
340
|
{"restart": load_from, "gdxSymbols": "all"}
|
|
340
341
|
)
|
|
341
342
|
self._synch_with_gams(gams_to_gamspy=True)
|
|
342
|
-
self._options._set_debug_options(
|
|
343
|
+
self._options._set_debug_options({})
|
|
343
344
|
self._clean_modified_symbols()
|
|
344
345
|
self._unsaved_statements = []
|
|
345
346
|
self._is_restarted = True
|
|
@@ -679,7 +680,8 @@ class Container(gt.Container):
|
|
|
679
680
|
strings.append("$offDotL")
|
|
680
681
|
elif assume_suffix == 2:
|
|
681
682
|
strings.append("$offDotScale")
|
|
682
|
-
|
|
683
|
+
|
|
684
|
+
strings.extend(["$offUNDF", "$offMulti"])
|
|
683
685
|
|
|
684
686
|
if not IS_MIRO_INIT and MIRO_GDX_OUT:
|
|
685
687
|
if len(self._miro_output_symbols) == 0:
|
|
@@ -1347,7 +1349,7 @@ class Container(gt.Container):
|
|
|
1347
1349
|
Variable | Sequence[Variable],
|
|
1348
1350
|
]
|
|
1349
1351
|
| None = None,
|
|
1350
|
-
limited_variables: Sequence[
|
|
1352
|
+
limited_variables: Sequence[ImplicitVariable] | None = None,
|
|
1351
1353
|
external_module: str | None = None,
|
|
1352
1354
|
) -> Model:
|
|
1353
1355
|
"""
|
|
@@ -1370,7 +1372,7 @@ class Container(gt.Container):
|
|
|
1370
1372
|
Objective variable to minimize or maximize or objective itself.
|
|
1371
1373
|
matches : dict[Equation | Sequence[Equation], Variable | Sequence[Variable]], optional
|
|
1372
1374
|
Equation - Variable matches for MCP models.
|
|
1373
|
-
limited_variables : Sequence, optional
|
|
1375
|
+
limited_variables : Sequence[ImplicitVariable], optional
|
|
1374
1376
|
Allows limiting the domain of variables used in a model.
|
|
1375
1377
|
external_module: str, optional
|
|
1376
1378
|
The name of the external module in which the external equations are implemented
|
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
import subprocess
|
|
6
6
|
from collections.abc import Sequence
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
8
|
|
|
9
9
|
import gamspy._symbols as syms
|
|
10
10
|
import gamspy.utils as utils
|
|
@@ -12,6 +12,7 @@ from gamspy._options import EXECUTION_OPTIONS, MODEL_ATTR_OPTION_MAP, Options
|
|
|
12
12
|
from gamspy.exceptions import LatexException, ValidationError
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
|
+
from pathlib import Path
|
|
15
16
|
from typing import TypeAlias
|
|
16
17
|
|
|
17
18
|
from gamspy import (
|
|
@@ -80,11 +81,11 @@ option js<js2; jd(js) = yes;
|
|
|
80
81
|
jc(j) = yes;
|
|
81
82
|
jc(jd) = no;
|
|
82
83
|
|
|
83
|
-
xb.lo(jb) =xc.lo(jb); xb.up(jb) =xc.up(jb); xb.prior(jb) =xc.scale(jb);
|
|
84
|
-
xi.lo(ji) =xc.lo(ji); xi.up(ji) =xc.up(ji); xi.prior(ji) =xc.scale(ji);
|
|
85
|
-
xsc.lo(jsc) =xc.lo(jsc); xsc.up(jsc) =xc.up(jsc); xsc.prior(jsc) =xc.scale(jsc);
|
|
86
|
-
xsi.lo(jsi) =xc.lo(jsi); xsi.up(jsi) =xc.up(jsi); xsi.prior(jsi) =xc.scale(jsi);
|
|
87
|
-
xs1.lo(js1(s,j))=xc.lo(j); xs1.up(js1(s,j))=xc.up(j); xs1.prior(js1(s,j))=xc.scale(j);
|
|
84
|
+
xb.lo(jb) =xc.lo(jb); xb.up(jb) =xc.up(jb); xb.prior(jb) =xc.scale(jb);
|
|
85
|
+
xi.lo(ji) =xc.lo(ji); xi.up(ji) =xc.up(ji); xi.prior(ji) =xc.scale(ji);
|
|
86
|
+
xsc.lo(jsc) =xc.lo(jsc); xsc.up(jsc) =xc.up(jsc); xsc.prior(jsc) =xc.scale(jsc);
|
|
87
|
+
xsi.lo(jsi) =xc.lo(jsi); xsi.up(jsi) =xc.up(jsi); xsi.prior(jsi) =xc.scale(jsi);
|
|
88
|
+
xs1.lo(js1(s,j))=xc.lo(j); xs1.up(js1(s,j))=xc.up(j); xs1.prior(js1(s,j))=xc.scale(j);
|
|
88
89
|
xs2.lo(js2(s,j))=xc.lo(j); xs2.up(js2(s,j))=xc.up(j); xs2.prior(js2(s,j))=xc.scale(j);
|
|
89
90
|
|
|
90
91
|
option ij<A;
|
|
@@ -300,7 +301,7 @@ jac.solve(output=sys.stdout, options=options)
|
|
|
300
301
|
|
|
301
302
|
|
|
302
303
|
def get_convert_solver_options(
|
|
303
|
-
path:
|
|
304
|
+
path: Path,
|
|
304
305
|
file_format: FileFormat | Sequence[FileFormat],
|
|
305
306
|
options: ConvertOptions | None,
|
|
306
307
|
) -> dict[str, str]:
|
|
@@ -319,7 +320,7 @@ def get_convert_solver_options(
|
|
|
319
320
|
if any(not isinstance(format, FileFormat) for format in file_format):
|
|
320
321
|
raise ValidationError("`file_format` must be a FileFormat enum.")
|
|
321
322
|
|
|
322
|
-
solver_options = {}
|
|
323
|
+
solver_options: dict[str, Any] = {}
|
|
323
324
|
for format in file_format:
|
|
324
325
|
name, value = format.name, format.value
|
|
325
326
|
if name in FORMAT_RENAME_MAP:
|
|
@@ -335,13 +336,13 @@ def get_convert_solver_options(
|
|
|
335
336
|
"$if not set jacfile $abort Please set --jacfile=<filename>.gdx"
|
|
336
337
|
)
|
|
337
338
|
|
|
338
|
-
with open(
|
|
339
|
+
with open(path / value, "w") as file:
|
|
339
340
|
file.write(jacobian_gms)
|
|
340
341
|
elif format == FileFormat.GAMSPyJacobian:
|
|
341
|
-
with open(
|
|
342
|
+
with open(path / value, "w") as file:
|
|
342
343
|
file.write(GAMSPY_JACOBIAN)
|
|
343
344
|
else:
|
|
344
|
-
solver_options[name] =
|
|
345
|
+
solver_options[name] = str((path / value).resolve())
|
|
345
346
|
|
|
346
347
|
if options is not None:
|
|
347
348
|
extra_options = options.model_dump(exclude_none=True)
|
|
@@ -375,7 +376,7 @@ class GamsConverter:
|
|
|
375
376
|
def __init__(
|
|
376
377
|
self,
|
|
377
378
|
model: Model,
|
|
378
|
-
path:
|
|
379
|
+
path: Path,
|
|
379
380
|
options: Options | None,
|
|
380
381
|
dump_gams_state: bool,
|
|
381
382
|
) -> None:
|
|
@@ -385,9 +386,9 @@ class GamsConverter:
|
|
|
385
386
|
self.path = path
|
|
386
387
|
self.options = options
|
|
387
388
|
self.dump_gams_state = dump_gams_state
|
|
388
|
-
self.gdx_path =
|
|
389
|
-
self.gms_path =
|
|
390
|
-
self.g00_path =
|
|
389
|
+
self.gdx_path = str((path / f"{model.name}_data.gdx").resolve())
|
|
390
|
+
self.gms_path = str((path / f"{model.name}.gms").resolve())
|
|
391
|
+
self.g00_path = str((path / f"{model.name}.g00").resolve())
|
|
391
392
|
|
|
392
393
|
def get_definitions(self) -> list[str]:
|
|
393
394
|
definitions = []
|
|
@@ -441,7 +442,7 @@ class GamsConverter:
|
|
|
441
442
|
)
|
|
442
443
|
|
|
443
444
|
# 2. Load the data from gdx
|
|
444
|
-
load_str = f
|
|
445
|
+
load_str = f'$onMultiR\n$gdxLoadAll "{self.gdx_path}"\n$offMulti'
|
|
445
446
|
|
|
446
447
|
# 3. Definitions
|
|
447
448
|
definitions = self.get_definitions()
|
|
@@ -493,7 +494,7 @@ TABLE_FOOTER = "\\hline\n\\end{tabularx}"
|
|
|
493
494
|
|
|
494
495
|
|
|
495
496
|
class LatexConverter:
|
|
496
|
-
def __init__(self, model: Model, path:
|
|
497
|
+
def __init__(self, model: Model, path: Path) -> None:
|
|
497
498
|
os.makedirs(path, exist_ok=True)
|
|
498
499
|
self.model = model
|
|
499
500
|
self.container = model.container
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
-
import io
|
|
5
4
|
import logging
|
|
6
5
|
import os
|
|
7
6
|
import threading
|
|
8
7
|
import warnings
|
|
9
8
|
from collections.abc import Sequence
|
|
10
9
|
from enum import Enum
|
|
10
|
+
from pathlib import Path
|
|
11
11
|
from typing import TYPE_CHECKING, Any, ClassVar
|
|
12
12
|
|
|
13
13
|
from gams.core.gdx import GMS_UEL_IDENT_SIZE
|
|
@@ -37,6 +37,7 @@ from gamspy._options import (
|
|
|
37
37
|
from gamspy.exceptions import GamspyException, ValidationError
|
|
38
38
|
|
|
39
39
|
if TYPE_CHECKING:
|
|
40
|
+
import io
|
|
40
41
|
from typing import Literal
|
|
41
42
|
|
|
42
43
|
import pandas as pd
|
|
@@ -141,18 +142,43 @@ class SolveStatus(Enum):
|
|
|
141
142
|
"""An enumeration for solve status types"""
|
|
142
143
|
|
|
143
144
|
NormalCompletion = 1
|
|
145
|
+
"""The solver terminated in a normal way."""
|
|
146
|
+
|
|
144
147
|
IterationInterrupt = 2
|
|
148
|
+
"""The solver was interrupted because it used too many iterations. The option `iteration_limit` may be used to increase the iteration limit if everything seems normal."""
|
|
149
|
+
|
|
145
150
|
ResourceInterrupt = 3
|
|
151
|
+
"""The solver was interrupted because it used too much time. The option `time_limit` may be used to increase the time limit if everything seems normal."""
|
|
152
|
+
|
|
146
153
|
TerminatedBySolver = 4
|
|
154
|
+
"""The solver encountered some difficulty and was unable to continue."""
|
|
155
|
+
|
|
147
156
|
EvaluationInterrupt = 5
|
|
157
|
+
"""Too many evaluations of nonlinear terms at undefined values. We recommend to use variable bounds to prevent forbidden operations, such as division by zero. The rows in which the errors occur are listed just before the solution."""
|
|
158
|
+
|
|
148
159
|
CapabilityError = 6
|
|
160
|
+
"""The solver does not have the capability required by the model. For example, some solvers do not support certain types of discrete variables or support a more limited set of functions than other solvers."""
|
|
161
|
+
|
|
149
162
|
LicenseError = 7
|
|
163
|
+
"""The solver cannot find the appropriate license key needed to use a specific subsolver."""
|
|
164
|
+
|
|
150
165
|
UserInterrupt = 8
|
|
166
|
+
"""The user has sent a signal to interrupt the solver."""
|
|
167
|
+
|
|
151
168
|
SetupError = 9
|
|
169
|
+
"""The solver encountered a fatal failure during problem set-up time."""
|
|
170
|
+
|
|
152
171
|
SolverError = 10
|
|
172
|
+
"""The solver encountered a fatal error."""
|
|
173
|
+
|
|
153
174
|
InternalError = 11
|
|
175
|
+
"""The solver encountered an internal fatal error."""
|
|
176
|
+
|
|
154
177
|
Skipped = 12
|
|
178
|
+
"""The entire solve step has been skipped."""
|
|
179
|
+
|
|
155
180
|
SystemError = 13
|
|
181
|
+
"""This indicates a completely unknown or unexpected error condition."""
|
|
156
182
|
|
|
157
183
|
|
|
158
184
|
class FileFormat(Enum):
|
|
@@ -394,7 +420,7 @@ class Model:
|
|
|
394
420
|
|
|
395
421
|
# matches
|
|
396
422
|
if self._matches is not None:
|
|
397
|
-
matches: dict =
|
|
423
|
+
matches: dict = {}
|
|
398
424
|
for key, value in self._matches.items():
|
|
399
425
|
if isinstance(key, gp.Equation):
|
|
400
426
|
if isinstance(value, gp.Variable):
|
|
@@ -924,19 +950,19 @@ class Model:
|
|
|
924
950
|
return assignment
|
|
925
951
|
|
|
926
952
|
def _generate_solve_string(self) -> str:
|
|
927
|
-
|
|
953
|
+
solve_statement = [f"solve {self.name} using {self.problem}"]
|
|
928
954
|
|
|
929
955
|
if self.sense == gp.Sense.FEASIBILITY:
|
|
930
956
|
# Set sense as min or max for feasibility
|
|
931
957
|
self.sense = gp.Sense("MIN")
|
|
932
958
|
|
|
933
959
|
if self.problem not in (Problem.MCP, Problem.CNS, Problem.EMP):
|
|
934
|
-
|
|
960
|
+
solve_statement.append(str(self.sense))
|
|
935
961
|
|
|
936
962
|
if self._objective_variable is not None:
|
|
937
|
-
|
|
963
|
+
solve_statement.append(self._objective_variable.gamsRepr())
|
|
938
964
|
|
|
939
|
-
return
|
|
965
|
+
return " ".join(solve_statement)
|
|
940
966
|
|
|
941
967
|
def _add_runtime_options(self, options: Options, backend: str = "local") -> None:
|
|
942
968
|
for key, value in options.model_dump(exclude_none=True).items():
|
|
@@ -1058,7 +1084,7 @@ class Model:
|
|
|
1058
1084
|
|
|
1059
1085
|
def convert(
|
|
1060
1086
|
self,
|
|
1061
|
-
path: str,
|
|
1087
|
+
path: str | Path,
|
|
1062
1088
|
file_format: FileFormat | Sequence[FileFormat],
|
|
1063
1089
|
options: ConvertOptions | None = None,
|
|
1064
1090
|
) -> None:
|
|
@@ -1067,7 +1093,7 @@ class Model:
|
|
|
1067
1093
|
|
|
1068
1094
|
Parameters
|
|
1069
1095
|
----------
|
|
1070
|
-
path : str
|
|
1096
|
+
path : str | Path
|
|
1071
1097
|
Path to the directory where the converted model files will be saved.
|
|
1072
1098
|
file_format : FileFormat | Sequence[FileFormat]
|
|
1073
1099
|
File format(s) to convert the model to. Can be a single FileFormat or a list of FileFormats.
|
|
@@ -1090,6 +1116,7 @@ class Model:
|
|
|
1090
1116
|
>>> my_model.convert("output_directory", [gp.FileFormat.GAMS, gp.FileFormat.AMPL])
|
|
1091
1117
|
|
|
1092
1118
|
"""
|
|
1119
|
+
path = Path(path)
|
|
1093
1120
|
os.makedirs(path, exist_ok=True)
|
|
1094
1121
|
solver_options = get_convert_solver_options(path, file_format, options)
|
|
1095
1122
|
self.solve(solver="convert", solver_options=solver_options)
|
|
@@ -1358,7 +1385,7 @@ class Model:
|
|
|
1358
1385
|
if isinstance(key, gp.Equation):
|
|
1359
1386
|
equations_in_matches.append(key)
|
|
1360
1387
|
else:
|
|
1361
|
-
equations_in_matches +=
|
|
1388
|
+
equations_in_matches += list(key)
|
|
1362
1389
|
|
|
1363
1390
|
equations = []
|
|
1364
1391
|
for equation in self.equations:
|
|
@@ -1413,7 +1440,7 @@ class Model:
|
|
|
1413
1440
|
|
|
1414
1441
|
def toGams(
|
|
1415
1442
|
self,
|
|
1416
|
-
path: str,
|
|
1443
|
+
path: str | Path,
|
|
1417
1444
|
options: Options | None = None,
|
|
1418
1445
|
*,
|
|
1419
1446
|
dump_gams_state: bool = False,
|
|
@@ -1423,7 +1450,7 @@ class Model:
|
|
|
1423
1450
|
|
|
1424
1451
|
Parameters
|
|
1425
1452
|
----------
|
|
1426
|
-
path : str
|
|
1453
|
+
path : str | Path
|
|
1427
1454
|
Path to the directory which will contain the GAMS model.
|
|
1428
1455
|
options : Options | None, optional
|
|
1429
1456
|
GAMSPy options, by default None
|
|
@@ -1440,18 +1467,20 @@ class Model:
|
|
|
1440
1467
|
f"`options` must be of type gp.Options of found {type(options)}"
|
|
1441
1468
|
)
|
|
1442
1469
|
|
|
1470
|
+
path = Path(path)
|
|
1443
1471
|
converter = GamsConverter(self, path, options, dump_gams_state)
|
|
1444
1472
|
converter.convert()
|
|
1445
1473
|
|
|
1446
|
-
def toLatex(self, path: str, generate_pdf: bool = False) -> None:
|
|
1474
|
+
def toLatex(self, path: str | Path, generate_pdf: bool = False) -> None:
|
|
1447
1475
|
"""
|
|
1448
1476
|
Generates a latex file that contains the model definition under path/<model_name>.tex
|
|
1449
1477
|
|
|
1450
1478
|
Parameters
|
|
1451
1479
|
----------
|
|
1452
|
-
path : str
|
|
1480
|
+
path : str | Path
|
|
1453
1481
|
Path to the directory which will contain the .tex file.
|
|
1454
1482
|
"""
|
|
1483
|
+
path = Path(path)
|
|
1455
1484
|
converter = LatexConverter(self, path)
|
|
1456
1485
|
converter.convert()
|
|
1457
1486
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import io
|
|
4
3
|
import logging
|
|
5
4
|
import os
|
|
6
5
|
import sys
|
|
@@ -66,7 +65,6 @@ from gamspy._database import (
|
|
|
66
65
|
GamsParameter,
|
|
67
66
|
GamsVariable,
|
|
68
67
|
)
|
|
69
|
-
from gamspy._options import FreezeOptions, Options
|
|
70
68
|
from gamspy.exceptions import (
|
|
71
69
|
GamspyException,
|
|
72
70
|
ValidationError,
|
|
@@ -74,7 +72,10 @@ from gamspy.exceptions import (
|
|
|
74
72
|
)
|
|
75
73
|
|
|
76
74
|
if TYPE_CHECKING:
|
|
75
|
+
import io
|
|
76
|
+
|
|
77
77
|
from gamspy import Container, Model, Parameter
|
|
78
|
+
from gamspy._options import FreezeOptions, Options
|
|
78
79
|
from gamspy._symbols.implicits import ImplicitParameter
|
|
79
80
|
|
|
80
81
|
logger = logging.getLogger("FROZEN MODEL")
|