gamspy 1.15.0.post1__tar.gz → 1.15.1.post1__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.15.0.post1 → gamspy-1.15.1.post1}/PKG-INFO +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/pyproject.toml +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_algebra/expression.py +3 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/install.py +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/retrieve.py +13 -6
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_config.py +5 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_container.py +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_convert.py +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_miro.py +5 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/alias.py +2 -2
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/equation.py +40 -8
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/implicit_equation.py +18 -4
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/implicit_parameter.py +47 -51
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/implicit_set.py +16 -5
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/implicit_variable.py +17 -4
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/parameter.py +9 -9
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/set.py +8 -8
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/symbol.py +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/variable.py +8 -8
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_validation.py +44 -8
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/__init__.py +8 -1
- gamspy-1.15.1.post1/src/gamspy/formulations/ml/__init__.py +11 -0
- gamspy-1.15.1.post1/src/gamspy/formulations/ml/gradient_boosting.py +186 -0
- gamspy-1.15.1.post1/src/gamspy/formulations/ml/random_forest.py +168 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/ml/regression_tree.py +223 -122
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/avgpool2d.py +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/conv1d.py +17 -4
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/conv2d.py +18 -4
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/linear.py +17 -4
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/mpool2d.py +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/piecewise.py +4 -6
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/shape.py +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/math/activation.py +14 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy.egg-info/PKG-INFO +1 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy.egg-info/SOURCES.txt +3 -1
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/tests/test_gamspy.py +1 -1
- gamspy-1.15.0.post1/src/gamspy/formulations/ml/__init__.py +0 -4
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/LICENSE +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/README.md +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/README_PYPI.md +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/setup.cfg +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/__init__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/__main__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_algebra/__init__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_algebra/condition.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_algebra/domain.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_algebra/number.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_algebra/operable.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_algebra/operation.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_backend/__init__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_backend/backend.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_backend/engine.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_backend/local.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_backend/neos.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/__init__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/cli.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/gdx.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/list.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/probe.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/run.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/show.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/uninstall.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_cli/util.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_database.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_extrinsic.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_model.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_model_instance.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_options.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_serialization.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/__init__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/__init__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/implicit_symbol.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/universe_alias.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_types.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_workspace.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/exceptions.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/ml/decision_tree_struct.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/__init__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/maxpool2d.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/minpool2d.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/formulations/nn/torch_sequential.py +0 -0
- {gamspy-1.15.0.post1/src/gamspy/formulations/nn → gamspy-1.15.1.post1/src/gamspy/formulations}/utils.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/math/__init__.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/math/log_power.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/math/matrix.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/math/misc.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/math/probability.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/math/trigonometric.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/py.typed +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/utils.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/version.py +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy.egg-info/dependency_links.txt +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy.egg-info/entry_points.txt +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy.egg-info/requires.txt +0 -0
- {gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/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.15.
|
|
3
|
+
Version: 1.15.1.post1
|
|
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/
|
|
@@ -650,6 +650,9 @@ class Expression(operable.Operable):
|
|
|
650
650
|
|
|
651
651
|
if isinstance(node, Symbol):
|
|
652
652
|
if node.name not in symbols:
|
|
653
|
+
if type(node) is gp_syms.Alias:
|
|
654
|
+
symbols.append(node.alias_with.name)
|
|
655
|
+
|
|
653
656
|
symbols.append(node.name)
|
|
654
657
|
stack += node.domain
|
|
655
658
|
node = None
|
|
@@ -261,7 +261,7 @@ def solver(
|
|
|
261
261
|
_ = subprocess.run(command, check=True, encoding="utf-8", stderr=subprocess.PIPE)
|
|
262
262
|
except subprocess.CalledProcessError as e:
|
|
263
263
|
raise GamspyException(
|
|
264
|
-
f"Could not install gamspy-{solver_name}. Please check your internet connection. If it's not related to your internet connection, PyPI servers might be down. Please retry it later. Here is the error message of pip:\n\n{e.stderr
|
|
264
|
+
f"Could not install gamspy-{solver_name}. Please check your internet connection. If it's not related to your internet connection, PyPI servers might be down. Please retry it later. Here is the error message of pip:\n\n{e.stderr}"
|
|
265
265
|
) from e
|
|
266
266
|
else:
|
|
267
267
|
try:
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import subprocess
|
|
5
|
+
from typing import Optional
|
|
5
6
|
|
|
6
7
|
import typer
|
|
7
8
|
|
|
@@ -37,6 +38,7 @@ def license(
|
|
|
37
38
|
"-o",
|
|
38
39
|
help="Output path for the license file."
|
|
39
40
|
),
|
|
41
|
+
checkout_duration: Optional[int] = typer.Option(None, "--checkout-duration", "-c", help="Specifies a duration in hours to checkout a session."),
|
|
40
42
|
) -> None:
|
|
41
43
|
if input is None or not os.path.isfile(input):
|
|
42
44
|
raise ValidationError(
|
|
@@ -49,13 +51,18 @@ def license(
|
|
|
49
51
|
)
|
|
50
52
|
|
|
51
53
|
gamspy_base_dir = utils._get_gamspy_base_directory()
|
|
54
|
+
command = [
|
|
55
|
+
os.path.join(gamspy_base_dir, "gamsgetkey"),
|
|
56
|
+
access_code,
|
|
57
|
+
"-i",
|
|
58
|
+
input,
|
|
59
|
+
]
|
|
60
|
+
if checkout_duration:
|
|
61
|
+
command.append("-c")
|
|
62
|
+
command.append(str(checkout_duration))
|
|
63
|
+
|
|
52
64
|
process = subprocess.run(
|
|
53
|
-
|
|
54
|
-
os.path.join(gamspy_base_dir, "gamsgetkey"),
|
|
55
|
-
access_code,
|
|
56
|
-
"-i",
|
|
57
|
-
input,
|
|
58
|
-
],
|
|
65
|
+
command,
|
|
59
66
|
text=True,
|
|
60
67
|
capture_output=True,
|
|
61
68
|
)
|
|
@@ -55,6 +55,10 @@ def _set_default_options() -> None:
|
|
|
55
55
|
strategy = int(os.getenv("GAMSPY_DROP_DOMAIN_VIOLATIONS", 0))
|
|
56
56
|
configuration["DROP_DOMAIN_VIOLATIONS"] = strategy
|
|
57
57
|
|
|
58
|
+
# Do not allow ambiguity in MCP, EMP, MPEC models by default
|
|
59
|
+
ambiguity = os.getenv("GAMSPY_ALLOW_AMBIGUOUS_EQUATIONS", "auto")
|
|
60
|
+
configuration["ALLOW_AMBIGUOUS_EQUATIONS"] = ambiguity
|
|
61
|
+
|
|
58
62
|
|
|
59
63
|
def set_options(
|
|
60
64
|
options: dict[
|
|
@@ -67,6 +71,7 @@ def set_options(
|
|
|
67
71
|
"ASSUME_VARIABLE_SUFFIX",
|
|
68
72
|
"USE_PY_VAR_NAME",
|
|
69
73
|
"DROP_DOMAIN_VIOLATIONS",
|
|
74
|
+
"ALLOW_AMBIGUOUS_EQUATIONS",
|
|
70
75
|
],
|
|
71
76
|
Any,
|
|
72
77
|
],
|
|
@@ -45,7 +45,11 @@ def load_miro_symbol_records(container: Container):
|
|
|
45
45
|
for name in names:
|
|
46
46
|
symbol = container[name]
|
|
47
47
|
symbol._already_loaded = True
|
|
48
|
-
if
|
|
48
|
+
if (
|
|
49
|
+
isinstance(symbol, gp.Parameter)
|
|
50
|
+
and symbol._is_miro_table
|
|
51
|
+
and symbol._records is not None
|
|
52
|
+
):
|
|
49
53
|
symbol._records.columns = symbol.domain_names + ["value"]
|
|
50
54
|
|
|
51
55
|
# Load records of miro output symbols
|
|
@@ -134,7 +134,7 @@ class Alias(gt.Alias, operable.Operable, Symbol, SetMixin):
|
|
|
134
134
|
# reset some properties
|
|
135
135
|
self._requires_state_check = True
|
|
136
136
|
self.container._requires_state_check = True
|
|
137
|
-
self.
|
|
137
|
+
self._modified = True
|
|
138
138
|
self.alias_with = alias_with
|
|
139
139
|
else:
|
|
140
140
|
if container is None:
|
|
@@ -157,7 +157,7 @@ class Alias(gt.Alias, operable.Operable, Symbol, SetMixin):
|
|
|
157
157
|
self.where = condition.Condition(self)
|
|
158
158
|
self.container._add_statement(self)
|
|
159
159
|
|
|
160
|
-
self.
|
|
160
|
+
self._modified = False
|
|
161
161
|
self.container._synch_with_gams()
|
|
162
162
|
|
|
163
163
|
def _serialize(self) -> dict:
|
|
@@ -18,6 +18,7 @@ from gams.transfer._internals import (
|
|
|
18
18
|
import gamspy as gp
|
|
19
19
|
import gamspy._algebra.condition as condition
|
|
20
20
|
import gamspy._algebra.expression as expression
|
|
21
|
+
import gamspy._algebra.operable as operable
|
|
21
22
|
import gamspy._symbols.implicits as implicits
|
|
22
23
|
import gamspy._validation as validation
|
|
23
24
|
import gamspy.utils as utils
|
|
@@ -273,7 +274,7 @@ class Equation(gt.Equation, Symbol):
|
|
|
273
274
|
" domains are equal"
|
|
274
275
|
)
|
|
275
276
|
|
|
276
|
-
if self.
|
|
277
|
+
if self._domain_forwarding != domain_forwarding:
|
|
277
278
|
raise ValueError(
|
|
278
279
|
"Cannot overwrite symbol in container unless"
|
|
279
280
|
" 'domain_forwarding' is left unchanged"
|
|
@@ -287,8 +288,8 @@ class Equation(gt.Equation, Symbol):
|
|
|
287
288
|
|
|
288
289
|
previous_state = self.container._options.miro_protect
|
|
289
290
|
self.container._options.miro_protect = False
|
|
290
|
-
self.
|
|
291
|
-
self.
|
|
291
|
+
self._records = None
|
|
292
|
+
self._modified = True
|
|
292
293
|
self._init_definition(definition)
|
|
293
294
|
|
|
294
295
|
# only set records if records are provided
|
|
@@ -360,14 +361,14 @@ class Equation(gt.Equation, Symbol):
|
|
|
360
361
|
self.setRecords(records, uels_on_axes=uels_on_axes)
|
|
361
362
|
else:
|
|
362
363
|
if not self._is_miro_output:
|
|
363
|
-
self.
|
|
364
|
+
self._modified = False
|
|
364
365
|
self.container._synch_with_gams()
|
|
365
366
|
|
|
366
367
|
container._options.miro_protect = previous_state
|
|
367
368
|
|
|
368
369
|
def _serialize(self) -> dict:
|
|
369
370
|
info = {
|
|
370
|
-
"_domain_forwarding": self.
|
|
371
|
+
"_domain_forwarding": self._domain_forwarding,
|
|
371
372
|
"_is_miro_output": self._is_miro_output,
|
|
372
373
|
"_metadata": self._metadata,
|
|
373
374
|
"_synchronize": self._synchronize,
|
|
@@ -554,6 +555,37 @@ class Equation(gt.Equation, Symbol):
|
|
|
554
555
|
self.container._add_statement(statement)
|
|
555
556
|
self._definition = statement
|
|
556
557
|
|
|
558
|
+
def _check_ambiguity(self) -> None:
|
|
559
|
+
"""Ambiguity check for MCP, EMP, MPEC models. See #610"""
|
|
560
|
+
# Looks for =e=, =l= and =g= in an equation definition
|
|
561
|
+
# with a stack based inorder traversal algorithm (O(N)).
|
|
562
|
+
stack = []
|
|
563
|
+
|
|
564
|
+
assert self._definition is not None
|
|
565
|
+
node = self._definition.right
|
|
566
|
+
while True:
|
|
567
|
+
if node is not None:
|
|
568
|
+
stack.append(node)
|
|
569
|
+
node = getattr(node, "left", None) # type: ignore
|
|
570
|
+
elif stack:
|
|
571
|
+
node = stack.pop()
|
|
572
|
+
if (
|
|
573
|
+
isinstance(node, expression.Expression)
|
|
574
|
+
and node.operator in {"=e=", "=l=", "=g=", "=x=", "=n="}
|
|
575
|
+
and not isinstance(node.right, operable.Operable)
|
|
576
|
+
):
|
|
577
|
+
raise ValidationError(
|
|
578
|
+
f"Definition of `{self.name}` is ambigiuous. Please "
|
|
579
|
+
"use gp.Number for numeric values or disable ambiguity "
|
|
580
|
+
"check via gp.set_options({'ALLOW_AMBIGUOUS_EQUATIONS': 'no'}). "
|
|
581
|
+
"Using numeric values in equations without gp.Number can result in "
|
|
582
|
+
f"different order than expected. Print `{self.name}.getDefinition()` to "
|
|
583
|
+
"make sure that the equation definition is as expected."
|
|
584
|
+
)
|
|
585
|
+
node = getattr(node, "right", None)
|
|
586
|
+
else:
|
|
587
|
+
break # pragma: no cover
|
|
588
|
+
|
|
557
589
|
@property
|
|
558
590
|
def l(self): # noqa: E741, E743
|
|
559
591
|
"""
|
|
@@ -1000,12 +1032,12 @@ class Equation(gt.Equation, Symbol):
|
|
|
1000
1032
|
self._records = records
|
|
1001
1033
|
|
|
1002
1034
|
self._requires_state_check = True
|
|
1003
|
-
self.
|
|
1035
|
+
self._modified = True
|
|
1004
1036
|
|
|
1005
1037
|
self.container._requires_state_check = True
|
|
1006
1038
|
self.container.modified = True
|
|
1007
1039
|
|
|
1008
|
-
if self._records is not None and self.
|
|
1040
|
+
if self._records is not None and self._domain_forwarding:
|
|
1009
1041
|
self._domainForwarding()
|
|
1010
1042
|
|
|
1011
1043
|
# reset state check flags for all symbols in the container
|
|
@@ -1159,7 +1191,7 @@ class Equation(gt.Equation, Symbol):
|
|
|
1159
1191
|
output = f"Equation {self.name}"
|
|
1160
1192
|
|
|
1161
1193
|
if self.domain:
|
|
1162
|
-
output += self._get_domain_str(self.
|
|
1194
|
+
output += self._get_domain_str(self._domain_forwarding)
|
|
1163
1195
|
|
|
1164
1196
|
if self.description:
|
|
1165
1197
|
output += ' "' + self.description + '"'
|
{gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/implicit_equation.py
RENAMED
|
@@ -2,9 +2,11 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
+
import gamspy._symbols as syms
|
|
5
6
|
import gamspy._symbols.alias as alias
|
|
6
7
|
import gamspy._symbols.implicits as implicits
|
|
7
8
|
import gamspy._symbols.set as gams_set
|
|
9
|
+
import gamspy.utils as utils
|
|
8
10
|
from gamspy._symbols.implicits.implicit_symbol import ImplicitSymbol
|
|
9
11
|
|
|
10
12
|
if TYPE_CHECKING:
|
|
@@ -141,10 +143,22 @@ class ImplicitEquation(ImplicitSymbol):
|
|
|
141
143
|
if self.parent.records is None:
|
|
142
144
|
return None
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
temp_name = "ie" + utils._get_unique_name()
|
|
147
|
+
temp_param = syms.Parameter._constructor_bypass(
|
|
148
|
+
self.container, temp_name, self.parent.domain
|
|
149
|
+
)
|
|
150
|
+
domain = list(self.domain)
|
|
151
|
+
for i, d in self._scalar_domains:
|
|
152
|
+
domain.insert(i, d)
|
|
153
|
+
|
|
154
|
+
temp_param[domain] = self.l
|
|
155
|
+
del self.container.data[temp_name]
|
|
156
|
+
|
|
157
|
+
recs = temp_param.records
|
|
158
|
+
if recs is not None:
|
|
159
|
+
columns = recs.columns.to_list()
|
|
160
|
+
columns[columns.index("value")] = "level"
|
|
161
|
+
recs.columns = columns
|
|
148
162
|
|
|
149
163
|
return recs
|
|
150
164
|
|
{gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/implicit_parameter.py
RENAMED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from collections.abc import
|
|
4
|
+
from collections.abc import Sequence
|
|
5
5
|
from typing import TYPE_CHECKING, Any
|
|
6
6
|
|
|
7
7
|
import gamspy._algebra.expression as expression
|
|
8
8
|
import gamspy._algebra.operable as operable
|
|
9
9
|
import gamspy._algebra.operation as operation
|
|
10
10
|
import gamspy._symbols as syms
|
|
11
|
+
import gamspy._symbols.implicits as implicits
|
|
11
12
|
import gamspy._validation as validation
|
|
12
13
|
import gamspy.utils as utils
|
|
13
14
|
from gamspy._symbols.implicits.implicit_symbol import ImplicitSymbol
|
|
@@ -26,6 +27,7 @@ if TYPE_CHECKING:
|
|
|
26
27
|
)
|
|
27
28
|
from gamspy._algebra.expression import Expression
|
|
28
29
|
from gamspy._algebra.operation import Operation
|
|
30
|
+
from gamspy._types import EllipsisType
|
|
29
31
|
|
|
30
32
|
logger = logging.getLogger("GAMSPy")
|
|
31
33
|
logger.setLevel(logging.WARNING)
|
|
@@ -41,6 +43,11 @@ ATTR_MAPPING = {
|
|
|
41
43
|
"lo": "lower",
|
|
42
44
|
"up": "upper",
|
|
43
45
|
"scale": "scale",
|
|
46
|
+
"range": "range",
|
|
47
|
+
"slack": "slack",
|
|
48
|
+
"slacklo": "slacklo",
|
|
49
|
+
"slackup": "slackup",
|
|
50
|
+
"infeas": "infeas",
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
SET_ATTR_MAPPING = {
|
|
@@ -81,7 +88,10 @@ class ImplicitParameter(ImplicitSymbol, operable.Operable):
|
|
|
81
88
|
self._records = records
|
|
82
89
|
self._assignment = None
|
|
83
90
|
|
|
84
|
-
def __getitem__(
|
|
91
|
+
def __getitem__(
|
|
92
|
+
self,
|
|
93
|
+
indices: EllipsisType | slice | Sequence | str | implicits.ImplicitSet,
|
|
94
|
+
) -> ImplicitParameter:
|
|
85
95
|
domain = validation.validate_domain(self, indices)
|
|
86
96
|
|
|
87
97
|
return ImplicitParameter(
|
|
@@ -94,7 +104,7 @@ class ImplicitParameter(ImplicitSymbol, operable.Operable):
|
|
|
94
104
|
|
|
95
105
|
def __setitem__(
|
|
96
106
|
self,
|
|
97
|
-
indices:
|
|
107
|
+
indices: EllipsisType | slice | Sequence | str | implicits.ImplicitSet,
|
|
98
108
|
rhs: Expression | Operation | ImplicitParameter | int | float,
|
|
99
109
|
) -> None:
|
|
100
110
|
if (
|
|
@@ -146,32 +156,6 @@ class ImplicitParameter(ImplicitSymbol, operable.Operable):
|
|
|
146
156
|
def __repr__(self) -> str:
|
|
147
157
|
return f"ImplicitParameter(parent={self.parent}, name='{self.name}', domain={self.domain}, permutation={self.permutation}), parent_scalar_domains={self.parent_scalar_domains})"
|
|
148
158
|
|
|
149
|
-
def _add_new_attr_column(
|
|
150
|
-
self, extension: str, recs: pd.DataFrame
|
|
151
|
-
) -> pd.DataFrame:
|
|
152
|
-
parent_recs: pd.DataFrame = self.parent.records
|
|
153
|
-
if extension == "range":
|
|
154
|
-
recs[extension] = parent_recs["lower"] - parent_recs["upper"]
|
|
155
|
-
elif extension == "slacklo":
|
|
156
|
-
recs[extension] = (
|
|
157
|
-
parent_recs["level"] - parent_recs["lower"]
|
|
158
|
-
).clip(0)
|
|
159
|
-
elif extension == "slackup":
|
|
160
|
-
recs[extension] = (
|
|
161
|
-
parent_recs["upper"] - parent_recs["level"]
|
|
162
|
-
).clip(0)
|
|
163
|
-
elif extension == "slack":
|
|
164
|
-
slacklo = (parent_recs["level"] - parent_recs["lower"]).clip(0)
|
|
165
|
-
slackup = (parent_recs["upper"] - parent_recs["level"]).clip(0)
|
|
166
|
-
recs[extension] = slacklo.combine(slackup, min)
|
|
167
|
-
elif extension == "infeas":
|
|
168
|
-
distance_to_lower = parent_recs["lower"] - parent_recs["level"]
|
|
169
|
-
distance_to_upper = parent_recs["level"] - parent_recs["upper"]
|
|
170
|
-
max_distance = distance_to_lower.combine(distance_to_upper, max)
|
|
171
|
-
recs[extension] = max_distance.clip(lower=0)
|
|
172
|
-
|
|
173
|
-
return recs
|
|
174
|
-
|
|
175
159
|
@property
|
|
176
160
|
def records(self) -> pd.DataFrame | float | None:
|
|
177
161
|
if self.parent.records is None:
|
|
@@ -187,37 +171,49 @@ class ImplicitParameter(ImplicitSymbol, operable.Operable):
|
|
|
187
171
|
del self.container.data[temp_name]
|
|
188
172
|
return temp_param.records
|
|
189
173
|
elif isinstance(self.parent, syms.Parameter):
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
174
|
+
temp_name = "p" + utils._get_unique_name()
|
|
175
|
+
temp_param = syms.Parameter._constructor_bypass(
|
|
176
|
+
self.container, temp_name, self.parent.domain
|
|
177
|
+
)
|
|
178
|
+
domain = list(self.domain)
|
|
179
|
+
for i, d in self._scalar_domains:
|
|
180
|
+
domain.insert(i, d)
|
|
181
|
+
|
|
182
|
+
temp_param[domain] = self[...]
|
|
183
|
+
del self.container.data[temp_name]
|
|
184
|
+
|
|
185
|
+
recs = temp_param.records
|
|
186
|
+
if len(recs) == 1:
|
|
198
187
|
return float(recs["value"].squeeze())
|
|
199
188
|
|
|
200
189
|
return recs
|
|
201
190
|
elif isinstance(self.parent, (syms.Variable, syms.Equation)):
|
|
202
191
|
extension = self.name.split(".")[-1]
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if extension in ATTR_MAPPING:
|
|
192
|
+
if self.parent.dimension == 0:
|
|
206
193
|
extension = ATTR_MAPPING[extension]
|
|
207
|
-
|
|
194
|
+
return float(self.parent.records[extension].squeeze())
|
|
195
|
+
|
|
196
|
+
temp_name = "ip" + utils._get_unique_name()
|
|
197
|
+
temp_param = syms.Parameter._constructor_bypass(
|
|
198
|
+
self.container, temp_name, self.parent.domain
|
|
199
|
+
)
|
|
200
|
+
domain = list(self.domain)
|
|
201
|
+
for i, d in self._scalar_domains:
|
|
202
|
+
domain.insert(i, d)
|
|
203
|
+
|
|
204
|
+
temp_param[domain] = self
|
|
205
|
+
del self.container.data[temp_name]
|
|
208
206
|
|
|
209
|
-
recs =
|
|
210
|
-
if
|
|
211
|
-
|
|
212
|
-
recs = self._add_new_attr_column(extension, recs)
|
|
207
|
+
recs = temp_param.records
|
|
208
|
+
if recs is None:
|
|
209
|
+
return recs
|
|
213
210
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
211
|
+
extension = ATTR_MAPPING[extension]
|
|
212
|
+
columns = recs.columns.to_list()
|
|
213
|
+
columns[columns.index("value")] = extension
|
|
214
|
+
recs.columns = columns
|
|
217
215
|
|
|
218
|
-
if
|
|
219
|
-
isinstance(elem, str) and elem != "*" for elem in self.domain
|
|
220
|
-
):
|
|
216
|
+
if len(recs) == 1:
|
|
221
217
|
return float(recs[extension].squeeze())
|
|
222
218
|
|
|
223
219
|
return recs
|
|
@@ -9,6 +9,7 @@ import gamspy._symbols as syms
|
|
|
9
9
|
import gamspy._validation as validation
|
|
10
10
|
import gamspy.utils as utils
|
|
11
11
|
from gamspy._symbols.implicits.implicit_symbol import ImplicitSymbol
|
|
12
|
+
from gamspy.exceptions import ValidationError
|
|
12
13
|
|
|
13
14
|
if TYPE_CHECKING:
|
|
14
15
|
import pandas as pd
|
|
@@ -67,12 +68,22 @@ class ImplicitSet(ImplicitSymbol, operable.Operable):
|
|
|
67
68
|
if self.parent.records is None:
|
|
68
69
|
return None
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
if self.extension is not None:
|
|
72
|
+
raise ValidationError(
|
|
73
|
+
".records is not allowed for lag/lead operations."
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
temp_name = "is" + utils._get_unique_name()
|
|
77
|
+
temp_param = syms.Set._constructor_bypass(
|
|
78
|
+
self.container, temp_name, self.parent.domain
|
|
79
|
+
)
|
|
80
|
+
domain = list(self.domain)
|
|
81
|
+
for i, d in self._scalar_domains:
|
|
82
|
+
domain.insert(i, d)
|
|
74
83
|
|
|
75
|
-
|
|
84
|
+
temp_param[domain] = self
|
|
85
|
+
del self.container.data[temp_name]
|
|
86
|
+
return temp_param.records
|
|
76
87
|
|
|
77
88
|
def latexRepr(self):
|
|
78
89
|
name = self.name.replace("_", "\\_")
|
{gamspy-1.15.0.post1 → gamspy-1.15.1.post1}/src/gamspy/_symbols/implicits/implicit_variable.py
RENAMED
|
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
|
|
6
6
|
import gamspy._algebra.expression as expression
|
|
7
7
|
import gamspy._algebra.operable as operable
|
|
8
|
+
import gamspy._symbols as syms
|
|
8
9
|
import gamspy._symbols.implicits as implicits
|
|
9
10
|
import gamspy._validation as validation
|
|
10
11
|
import gamspy.utils as utils
|
|
@@ -217,10 +218,22 @@ class ImplicitVariable(ImplicitSymbol, operable.Operable):
|
|
|
217
218
|
if self.parent.records is None:
|
|
218
219
|
return None
|
|
219
220
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
221
|
+
temp_name = "iv" + utils._get_unique_name()
|
|
222
|
+
temp_param = syms.Parameter._constructor_bypass(
|
|
223
|
+
self.container, temp_name, self.parent.domain
|
|
224
|
+
)
|
|
225
|
+
domain = list(self.domain)
|
|
226
|
+
for i, d in self._scalar_domains:
|
|
227
|
+
domain.insert(i, d)
|
|
228
|
+
|
|
229
|
+
temp_param[domain] = self.l
|
|
230
|
+
del self.container.data[temp_name]
|
|
231
|
+
|
|
232
|
+
recs = temp_param.records
|
|
233
|
+
if recs is not None:
|
|
234
|
+
columns = recs.columns.to_list()
|
|
235
|
+
columns[columns.index("value")] = "level"
|
|
236
|
+
recs.columns = columns
|
|
224
237
|
|
|
225
238
|
return recs
|
|
226
239
|
|
|
@@ -234,7 +234,7 @@ class Parameter(gt.Parameter, operable.Operable, Symbol):
|
|
|
234
234
|
" domains are equal"
|
|
235
235
|
)
|
|
236
236
|
|
|
237
|
-
if self.
|
|
237
|
+
if self._domain_forwarding != domain_forwarding:
|
|
238
238
|
raise ValueError(
|
|
239
239
|
"Cannot overwrite symbol in container unless"
|
|
240
240
|
" 'domain_forwarding' is left unchanged"
|
|
@@ -248,8 +248,8 @@ class Parameter(gt.Parameter, operable.Operable, Symbol):
|
|
|
248
248
|
|
|
249
249
|
previous_state = self.container._options.miro_protect
|
|
250
250
|
self.container._options.miro_protect = False
|
|
251
|
-
self.
|
|
252
|
-
self.
|
|
251
|
+
self._records = None
|
|
252
|
+
self._modified = True
|
|
253
253
|
|
|
254
254
|
# only set records if records are provided
|
|
255
255
|
if records is not None:
|
|
@@ -301,7 +301,7 @@ class Parameter(gt.Parameter, operable.Operable, Symbol):
|
|
|
301
301
|
if records is not None:
|
|
302
302
|
super().setRecords(records, uels_on_axes=uels_on_axes)
|
|
303
303
|
if self.dimension == 0 and not self._is_miro_symbol:
|
|
304
|
-
self.
|
|
304
|
+
self._modified = False
|
|
305
305
|
|
|
306
306
|
if gp.get_option("DROP_DOMAIN_VIOLATIONS"):
|
|
307
307
|
if self.hasDomainViolations():
|
|
@@ -311,7 +311,7 @@ class Parameter(gt.Parameter, operable.Operable, Symbol):
|
|
|
311
311
|
self._domain_violations = None
|
|
312
312
|
else:
|
|
313
313
|
if not self._is_miro_symbol:
|
|
314
|
-
self.
|
|
314
|
+
self._modified = False
|
|
315
315
|
|
|
316
316
|
self.container._synch_with_gams(gams_to_gamspy=self._is_miro_input)
|
|
317
317
|
|
|
@@ -319,7 +319,7 @@ class Parameter(gt.Parameter, operable.Operable, Symbol):
|
|
|
319
319
|
|
|
320
320
|
def _serialize(self) -> dict:
|
|
321
321
|
info = {
|
|
322
|
-
"_domain_forwarding": self.
|
|
322
|
+
"_domain_forwarding": self._domain_forwarding,
|
|
323
323
|
"_is_miro_input": self._is_miro_input,
|
|
324
324
|
"_is_miro_output": self._is_miro_output,
|
|
325
325
|
"_is_miro_table": self._is_miro_table,
|
|
@@ -490,12 +490,12 @@ class Parameter(gt.Parameter, operable.Operable, Symbol):
|
|
|
490
490
|
self._records = records
|
|
491
491
|
|
|
492
492
|
self._requires_state_check = True
|
|
493
|
-
self.
|
|
493
|
+
self._modified = True
|
|
494
494
|
|
|
495
495
|
self.container._requires_state_check = True
|
|
496
496
|
self.container.modified = True
|
|
497
497
|
|
|
498
|
-
if self._records is not None and self.
|
|
498
|
+
if self._records is not None and self._domain_forwarding:
|
|
499
499
|
self._domainForwarding()
|
|
500
500
|
|
|
501
501
|
# reset state check flags for all symbols in the container
|
|
@@ -562,7 +562,7 @@ class Parameter(gt.Parameter, operable.Operable, Symbol):
|
|
|
562
562
|
"""
|
|
563
563
|
representation = self.name
|
|
564
564
|
if self.domain:
|
|
565
|
-
representation += self._get_domain_str(self.
|
|
565
|
+
representation += self._get_domain_str(self._domain_forwarding)
|
|
566
566
|
|
|
567
567
|
return representation
|
|
568
568
|
|
|
@@ -610,7 +610,7 @@ class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
|
610
610
|
" 'is_singleton' is left unchanged"
|
|
611
611
|
)
|
|
612
612
|
|
|
613
|
-
if self.
|
|
613
|
+
if self._domain_forwarding != domain_forwarding:
|
|
614
614
|
raise ValueError(
|
|
615
615
|
"Cannot overwrite symbol in container unless"
|
|
616
616
|
" 'domain_forwarding' is left unchanged"
|
|
@@ -624,8 +624,8 @@ class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
|
624
624
|
|
|
625
625
|
previous_state = self.container._options.miro_protect
|
|
626
626
|
self.container._options.miro_protect = False
|
|
627
|
-
self.
|
|
628
|
-
self.
|
|
627
|
+
self._records = None
|
|
628
|
+
self._modified = True
|
|
629
629
|
|
|
630
630
|
# only set records if records are provided
|
|
631
631
|
if records is not None:
|
|
@@ -680,7 +680,7 @@ class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
|
680
680
|
self.setRecords(records, uels_on_axes=uels_on_axes)
|
|
681
681
|
else:
|
|
682
682
|
if not self._is_miro_symbol:
|
|
683
|
-
self.
|
|
683
|
+
self._modified = False
|
|
684
684
|
self.container._synch_with_gams(
|
|
685
685
|
gams_to_gamspy=self._is_miro_input
|
|
686
686
|
)
|
|
@@ -689,7 +689,7 @@ class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
|
689
689
|
|
|
690
690
|
def _serialize(self) -> dict:
|
|
691
691
|
info = {
|
|
692
|
-
"_domain_forwarding": self.
|
|
692
|
+
"_domain_forwarding": self._domain_forwarding,
|
|
693
693
|
"_is_miro_input": self._is_miro_input,
|
|
694
694
|
"_is_miro_output": self._is_miro_output,
|
|
695
695
|
"_metadata": self._metadata,
|
|
@@ -824,12 +824,12 @@ class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
|
824
824
|
self._records = records
|
|
825
825
|
|
|
826
826
|
self._requires_state_check = True
|
|
827
|
-
self.
|
|
827
|
+
self._modified = True
|
|
828
828
|
|
|
829
829
|
self.container._requires_state_check = True
|
|
830
830
|
self.container.modified = True
|
|
831
831
|
|
|
832
|
-
if self._records is not None and self.
|
|
832
|
+
if self._records is not None and self._domain_forwarding:
|
|
833
833
|
self._domainForwarding()
|
|
834
834
|
|
|
835
835
|
# reset state check flags for all symbols in the container
|
|
@@ -917,7 +917,7 @@ class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
|
917
917
|
if self.is_singleton:
|
|
918
918
|
output = f"Singleton {output}"
|
|
919
919
|
|
|
920
|
-
output += self._get_domain_str(self.
|
|
920
|
+
output += self._get_domain_str(self._domain_forwarding)
|
|
921
921
|
|
|
922
922
|
if self.description:
|
|
923
923
|
output += f' "{self.description}"'
|