gamspy 1.18.2__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/cli.py +2 -1
- gamspy/_cli/install.py +18 -13
- gamspy/_cli/mps2gms.py +128 -0
- gamspy/_cli/show.py +0 -9
- gamspy/_container.py +288 -62
- gamspy/_convert.py +25 -18
- gamspy/_model.py +85 -20
- gamspy/_options.py +91 -13
- gamspy/_serialization.py +13 -1
- gamspy/_symbols/alias.py +8 -2
- gamspy/_symbols/equation.py +158 -49
- gamspy/_symbols/parameter.py +72 -33
- gamspy/_symbols/set.py +121 -59
- gamspy/_symbols/universe_alias.py +5 -1
- gamspy/_symbols/variable.py +121 -37
- gamspy/_validation.py +9 -0
- gamspy/utils.py +20 -0
- {gamspy-1.18.2.dist-info → gamspy-1.18.4.dist-info}/METADATA +1 -1
- {gamspy-1.18.2.dist-info → gamspy-1.18.4.dist-info}/RECORD +28 -27
- {gamspy-1.18.2.dist-info → gamspy-1.18.4.dist-info}/WHEEL +0 -0
- {gamspy-1.18.2.dist-info → gamspy-1.18.4.dist-info}/entry_points.txt +0 -0
- {gamspy-1.18.2.dist-info → gamspy-1.18.4.dist-info}/licenses/LICENSE +0 -0
- {gamspy-1.18.2.dist-info → gamspy-1.18.4.dist-info}/top_level.txt +0 -0
gamspy/_symbols/set.py
CHANGED
|
@@ -35,11 +35,14 @@ class SetMixin:
|
|
|
35
35
|
@property
|
|
36
36
|
def pos(self: Set | Alias) -> ImplicitParameter:
|
|
37
37
|
"""
|
|
38
|
-
|
|
38
|
+
Returns the element position in the current set, starting with 1.
|
|
39
|
+
|
|
40
|
+
This attribute corresponds to the `.pos` attribute in GAMS.
|
|
39
41
|
|
|
40
42
|
Returns
|
|
41
43
|
-------
|
|
42
44
|
ImplicitParameter
|
|
45
|
+
The position of the element.
|
|
43
46
|
|
|
44
47
|
Examples
|
|
45
48
|
--------
|
|
@@ -60,6 +63,7 @@ class SetMixin:
|
|
|
60
63
|
Returns
|
|
61
64
|
-------
|
|
62
65
|
ImplicitParameter
|
|
66
|
+
The ordinal position of the element.
|
|
63
67
|
|
|
64
68
|
Examples
|
|
65
69
|
--------
|
|
@@ -75,11 +79,15 @@ class SetMixin:
|
|
|
75
79
|
@property
|
|
76
80
|
def off(self: Set | Alias) -> ImplicitParameter:
|
|
77
81
|
"""
|
|
78
|
-
|
|
82
|
+
Returns the element position in the current set minus 1.
|
|
83
|
+
|
|
84
|
+
Mathematically: `.off` = `.pos` - 1.
|
|
85
|
+
This attribute corresponds to the `.off` attribute in GAMS.
|
|
79
86
|
|
|
80
87
|
Returns
|
|
81
88
|
-------
|
|
82
89
|
ImplicitParameter
|
|
90
|
+
The offset position of the element.
|
|
83
91
|
|
|
84
92
|
Examples
|
|
85
93
|
--------
|
|
@@ -95,12 +103,15 @@ class SetMixin:
|
|
|
95
103
|
@property
|
|
96
104
|
def rev(self: Set | Alias) -> ImplicitParameter:
|
|
97
105
|
"""
|
|
98
|
-
|
|
99
|
-
|
|
106
|
+
Returns the reverse element position in the current set.
|
|
107
|
+
|
|
108
|
+
The value for the last element is 0, the penultimate is 1, and so on.
|
|
109
|
+
This attribute corresponds to the `.rev` attribute in GAMS.
|
|
100
110
|
|
|
101
111
|
Returns
|
|
102
112
|
-------
|
|
103
113
|
ImplicitParameter
|
|
114
|
+
The reverse position value.
|
|
104
115
|
|
|
105
116
|
Examples
|
|
106
117
|
--------
|
|
@@ -116,11 +127,14 @@ class SetMixin:
|
|
|
116
127
|
@property
|
|
117
128
|
def uel(self: Set | Alias) -> ImplicitParameter:
|
|
118
129
|
"""
|
|
119
|
-
|
|
130
|
+
Returns the element position in the global Unique Element List (UEL).
|
|
131
|
+
|
|
132
|
+
This attribute corresponds to the `.uel` attribute in GAMS.
|
|
120
133
|
|
|
121
134
|
Returns
|
|
122
135
|
-------
|
|
123
136
|
ImplicitParameter
|
|
137
|
+
The position index in the UEL table.
|
|
124
138
|
|
|
125
139
|
Examples
|
|
126
140
|
--------
|
|
@@ -136,11 +150,14 @@ class SetMixin:
|
|
|
136
150
|
@property
|
|
137
151
|
def len(self: Set | Alias) -> ImplicitParameter:
|
|
138
152
|
"""
|
|
139
|
-
|
|
153
|
+
Returns the length of the set element name (count of characters).
|
|
154
|
+
|
|
155
|
+
This attribute corresponds to the `.len` attribute in GAMS.
|
|
140
156
|
|
|
141
157
|
Returns
|
|
142
158
|
-------
|
|
143
159
|
ImplicitParameter
|
|
160
|
+
The character count of the element name.
|
|
144
161
|
|
|
145
162
|
Examples
|
|
146
163
|
--------
|
|
@@ -156,11 +173,14 @@ class SetMixin:
|
|
|
156
173
|
@property
|
|
157
174
|
def tlen(self: Set | Alias) -> ImplicitParameter:
|
|
158
175
|
"""
|
|
159
|
-
|
|
176
|
+
Returns the length of the set element explanatory text (count of characters).
|
|
177
|
+
|
|
178
|
+
This attribute corresponds to the `.tlen` attribute in GAMS.
|
|
160
179
|
|
|
161
180
|
Returns
|
|
162
181
|
-------
|
|
163
182
|
ImplicitParameter
|
|
183
|
+
The character count of the element text.
|
|
164
184
|
|
|
165
185
|
Examples
|
|
166
186
|
--------
|
|
@@ -176,14 +196,15 @@ class SetMixin:
|
|
|
176
196
|
@property
|
|
177
197
|
def val(self: Set | Alias) -> ImplicitParameter:
|
|
178
198
|
"""
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
If
|
|
182
|
-
|
|
199
|
+
Returns the numerical value if the set element name is a number.
|
|
200
|
+
|
|
201
|
+
If the element is not a number, this attribute is undefined and may result in an error or ignored record.
|
|
202
|
+
This attribute corresponds to the `.val` attribute in GAMS.
|
|
183
203
|
|
|
184
204
|
Returns
|
|
185
205
|
-------
|
|
186
206
|
ImplicitParameter
|
|
207
|
+
The numerical value of the element name.
|
|
187
208
|
|
|
188
209
|
Examples
|
|
189
210
|
--------
|
|
@@ -199,14 +220,15 @@ class SetMixin:
|
|
|
199
220
|
@property
|
|
200
221
|
def tval(self: Set | Alias) -> ImplicitParameter:
|
|
201
222
|
"""
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
If
|
|
205
|
-
|
|
223
|
+
Returns the numerical value if the set element text is a number.
|
|
224
|
+
|
|
225
|
+
If the element text is not a number, this attribute is undefined.
|
|
226
|
+
This attribute corresponds to the `.tval` attribute in GAMS.
|
|
206
227
|
|
|
207
228
|
Returns
|
|
208
229
|
-------
|
|
209
230
|
ImplicitParameter
|
|
231
|
+
The numerical value of the element text.
|
|
210
232
|
|
|
211
233
|
Examples
|
|
212
234
|
--------
|
|
@@ -222,11 +244,14 @@ class SetMixin:
|
|
|
222
244
|
@property
|
|
223
245
|
def first(self: Set | Alias) -> ImplicitParameter:
|
|
224
246
|
"""
|
|
225
|
-
Returns 1
|
|
247
|
+
Returns 1 if the element is the first in the set, otherwise 0.
|
|
248
|
+
|
|
249
|
+
This attribute corresponds to the `.first` attribute in GAMS.
|
|
226
250
|
|
|
227
251
|
Returns
|
|
228
252
|
-------
|
|
229
253
|
ImplicitParameter
|
|
254
|
+
An implicit parameter with value 1 for the first element.
|
|
230
255
|
|
|
231
256
|
Examples
|
|
232
257
|
--------
|
|
@@ -242,11 +267,14 @@ class SetMixin:
|
|
|
242
267
|
@property
|
|
243
268
|
def last(self: Set | Alias) -> ImplicitParameter:
|
|
244
269
|
"""
|
|
245
|
-
Returns 1
|
|
270
|
+
Returns 1 if the element is the last in the set, otherwise 0.
|
|
271
|
+
|
|
272
|
+
This attribute corresponds to the `.last` attribute in GAMS.
|
|
246
273
|
|
|
247
274
|
Returns
|
|
248
275
|
-------
|
|
249
276
|
ImplicitParameter
|
|
277
|
+
An implicit parameter with value 1 for the last element.
|
|
250
278
|
|
|
251
279
|
Examples
|
|
252
280
|
--------
|
|
@@ -265,39 +293,38 @@ class SetMixin:
|
|
|
265
293
|
type: Literal["linear", "circular"] = "linear",
|
|
266
294
|
) -> ImplicitSet:
|
|
267
295
|
"""
|
|
268
|
-
|
|
296
|
+
Shifts the values of a Set or Alias by `n` positions to the left (lag).
|
|
269
297
|
|
|
270
298
|
Parameters
|
|
271
299
|
----------
|
|
272
300
|
n : OperableType
|
|
301
|
+
The number of positions to shift. Can be an integer or a GAMS symbol.
|
|
273
302
|
type : 'linear' or 'circular', optional
|
|
303
|
+
The type of lag to perform:
|
|
304
|
+
- 'linear' (default): Elements shifted out of bounds are dropped.
|
|
305
|
+
- 'circular': Elements shifted out of bounds wrap around to the end.
|
|
274
306
|
|
|
275
307
|
Returns
|
|
276
308
|
-------
|
|
277
309
|
ImplicitSet
|
|
310
|
+
The shifted set expression.
|
|
278
311
|
|
|
279
312
|
Raises
|
|
280
313
|
------
|
|
281
314
|
ValueError
|
|
282
|
-
|
|
315
|
+
If `type` is not 'linear' or 'circular'.
|
|
283
316
|
|
|
284
317
|
Examples
|
|
285
318
|
--------
|
|
286
319
|
>>> import gamspy as gp
|
|
287
|
-
>>>
|
|
288
320
|
>>> m = gp.Container()
|
|
289
321
|
>>> t = gp.Set(m, name="t", description="time sequence", records=[f"y-{x}" for x in range(1987, 1992)])
|
|
290
322
|
>>> a = gp.Parameter(m, name="a", domain=[t])
|
|
291
323
|
>>> b = gp.Parameter(m, name="b", domain=[t])
|
|
292
|
-
>>> c = gp.Parameter(m, name="c", domain=[t])
|
|
293
324
|
>>> a[t] = 1986 + gp.Ord(t)
|
|
294
|
-
>>> b[t] = -1
|
|
295
325
|
>>> b[t] = a[t.lag(1, "linear")]
|
|
296
326
|
>>> b.records.values.tolist()
|
|
297
327
|
[['y-1988', 1987.0], ['y-1989', 1988.0], ['y-1990', 1989.0], ['y-1991', 1990.0]]
|
|
298
|
-
>>> c[t] = a[t.lag(1, "circular")]
|
|
299
|
-
>>> c.records.values.tolist()
|
|
300
|
-
[['y-1987', 1991.0], ['y-1988', 1987.0], ['y-1989', 1988.0], ['y-1990', 1989.0], ['y-1991', 1990.0]]
|
|
301
328
|
|
|
302
329
|
"""
|
|
303
330
|
assert isinstance(self, (gp.Set, gp.Alias))
|
|
@@ -317,39 +344,38 @@ class SetMixin:
|
|
|
317
344
|
type: Literal["linear", "circular"] = "linear",
|
|
318
345
|
) -> ImplicitSet:
|
|
319
346
|
"""
|
|
320
|
-
|
|
347
|
+
Shifts the values of a Set or Alias by `n` positions to the right (lead).
|
|
321
348
|
|
|
322
349
|
Parameters
|
|
323
350
|
----------
|
|
324
351
|
n : OperableType
|
|
352
|
+
The number of positions to shift. Can be an integer or a GAMS symbol.
|
|
325
353
|
type : 'linear' or 'circular', optional
|
|
354
|
+
The type of lead to perform:
|
|
355
|
+
- 'linear' (default): Elements shifted out of bounds are dropped.
|
|
356
|
+
- 'circular': Elements shifted out of bounds wrap around to the beginning.
|
|
326
357
|
|
|
327
358
|
Returns
|
|
328
359
|
-------
|
|
329
360
|
ImplicitSet
|
|
361
|
+
The shifted set expression.
|
|
330
362
|
|
|
331
363
|
Raises
|
|
332
364
|
------
|
|
333
365
|
ValueError
|
|
334
|
-
|
|
366
|
+
If `type` is not 'linear' or 'circular'.
|
|
335
367
|
|
|
336
368
|
Examples
|
|
337
369
|
--------
|
|
338
370
|
>>> import gamspy as gp
|
|
339
|
-
>>>
|
|
340
371
|
>>> m = gp.Container()
|
|
341
372
|
>>> t = gp.Set(m, name="t", description="time sequence", records=[f"y-{x}" for x in range(1987, 1992)])
|
|
342
373
|
>>> a = gp.Parameter(m, name="a", domain=[t])
|
|
343
374
|
>>> c = gp.Parameter(m, name="c", domain=[t])
|
|
344
|
-
>>> d = gp.Parameter(m, name="d", domain=[t])
|
|
345
375
|
>>> a[t] = 1986 + gp.Ord(t)
|
|
346
|
-
>>> c[t] = -1
|
|
347
376
|
>>> c[t.lead(2, "linear")] = a[t]
|
|
348
377
|
>>> c.records.values.tolist()
|
|
349
|
-
[['y-
|
|
350
|
-
>>> d[t.lead(2, "circular")] = a[t]
|
|
351
|
-
>>> d.records.values.tolist()
|
|
352
|
-
[['y-1987', 1990.0], ['y-1988', 1991.0], ['y-1989', 1987.0], ['y-1990', 1988.0], ['y-1991', 1989.0]]
|
|
378
|
+
[['y-1989', 1987.0], ['y-1990', 1988.0], ['y-1991', 1989.0]]
|
|
353
379
|
|
|
354
380
|
"""
|
|
355
381
|
assert isinstance(self, (gp.Set, gp.Alias))
|
|
@@ -365,25 +391,28 @@ class SetMixin:
|
|
|
365
391
|
|
|
366
392
|
def sameAs(self, other: Set | Alias | str) -> MathOp:
|
|
367
393
|
"""
|
|
368
|
-
Evaluates to
|
|
394
|
+
Evaluates to True if the current set element is identical to the given symbol or string.
|
|
395
|
+
|
|
396
|
+
This corresponds to the `sameAs` operator in GAMS.
|
|
369
397
|
|
|
370
398
|
Parameters
|
|
371
399
|
----------
|
|
372
|
-
other : Set | Alias
|
|
400
|
+
other : Set | Alias | str
|
|
401
|
+
The other set, alias, or string label to compare against.
|
|
373
402
|
|
|
374
403
|
Returns
|
|
375
404
|
-------
|
|
376
405
|
MathOp
|
|
406
|
+
A boolean expression that evaluates to True (1) if they match, False (0) otherwise.
|
|
377
407
|
|
|
378
408
|
Examples
|
|
379
409
|
--------
|
|
380
410
|
>>> import gamspy as gp
|
|
381
|
-
|
|
382
411
|
>>> m = gp.Container()
|
|
383
412
|
>>> i = gp.Set(m, name="i", records=["seattle", "san-diego"])
|
|
384
413
|
>>> j = gp.Set(m, name="j", records=["new-york", "seattle"])
|
|
385
|
-
>>> attr = gp.Parameter(m, "attr", domain
|
|
386
|
-
>>> attr[i,j]
|
|
414
|
+
>>> attr = gp.Parameter(m, "attr", domain=[i, j])
|
|
415
|
+
>>> attr[i,j] = i.sameAs(j)
|
|
387
416
|
>>> attr.records.values.tolist()
|
|
388
417
|
[['seattle', 'seattle', 1.0]]
|
|
389
418
|
|
|
@@ -396,36 +425,56 @@ class SetMixin:
|
|
|
396
425
|
class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
397
426
|
"""
|
|
398
427
|
Represents a Set symbol in GAMS.
|
|
399
|
-
|
|
428
|
+
|
|
429
|
+
See https://gamspy.readthedocs.io/en/latest/user/basics/set.html for more details.
|
|
400
430
|
|
|
401
431
|
Parameters
|
|
402
432
|
----------
|
|
403
433
|
container : Container
|
|
404
|
-
Container
|
|
434
|
+
The Container object that this set belongs to.
|
|
405
435
|
name : str, optional
|
|
406
|
-
Name of the set.
|
|
436
|
+
Name of the set. If not provided, a unique name is generated automatically.
|
|
407
437
|
domain : Sequence[Set | Alias | str] | Set | Alias | str, optional
|
|
408
|
-
|
|
438
|
+
The domain of the set. Can be a list of other Sets/Aliases, a single Set/Alias,
|
|
439
|
+
or strings representing set names. Use "*" for the universe set. Default is ["*"].
|
|
409
440
|
is_singleton : bool, optional
|
|
410
|
-
|
|
441
|
+
If True, restricts the set to contain at most one element. Default is False.
|
|
411
442
|
records : pd.DataFrame | np.ndarray | list, optional
|
|
412
|
-
|
|
443
|
+
Initial elements to populate the set.
|
|
413
444
|
domain_forwarding : bool | list[bool], optional
|
|
414
|
-
|
|
445
|
+
If True, adding records to this set will implicitly add new elements to the
|
|
446
|
+
domain sets (if they are dynamic). Default is False.
|
|
415
447
|
description : str, optional
|
|
416
|
-
|
|
417
|
-
uels_on_axes : bool
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
448
|
+
A human-readable description of the set.
|
|
449
|
+
uels_on_axes : bool, optional
|
|
450
|
+
If True, implies that the Unique Element Labels (UELs) for the domain are
|
|
451
|
+
contained in the axes (index/columns) of the provided `records` object
|
|
452
|
+
(e.g., pandas DataFrame). Default is False.
|
|
453
|
+
is_miro_input : bool, optional
|
|
454
|
+
If True, flags this set as an input symbol for GAMS MIRO. Default is False.
|
|
455
|
+
is_miro_output : bool, optional
|
|
456
|
+
If True, flags this set as an output symbol for GAMS MIRO. Default is False.
|
|
423
457
|
|
|
424
458
|
Examples
|
|
425
459
|
--------
|
|
460
|
+
Simple set:
|
|
461
|
+
|
|
462
|
+
|
|
426
463
|
>>> import gamspy as gp
|
|
427
464
|
>>> m = gp.Container()
|
|
428
|
-
>>> i =
|
|
465
|
+
>>> i = m.addSet("i", records=["a", "b"])
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
Indexed set:
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
>>> j = m.addSet("j", domain=i)
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
Singleton set:
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
>>> s = m.addSet("s", is_singleton=True, records=["s1"])
|
|
429
478
|
|
|
430
479
|
"""
|
|
431
480
|
|
|
@@ -821,20 +870,28 @@ class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
|
821
870
|
|
|
822
871
|
def setRecords(self, records: Any, uels_on_axes: bool = False) -> None:
|
|
823
872
|
"""
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
873
|
+
Sets the records (elements) of the Set.
|
|
874
|
+
|
|
875
|
+
This is a convenience method to load data into the set. It handles various
|
|
876
|
+
input formats like lists and pandas DataFrames.
|
|
828
877
|
|
|
829
878
|
Parameters
|
|
830
879
|
----------
|
|
831
880
|
records : Any
|
|
881
|
+
The data to load. Common formats:
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
- List of strings: `['i1', 'i2']`
|
|
885
|
+
- List of tuples (for multi-dimensional sets): `[('a', '1'), ('b', '2')]`
|
|
886
|
+
- pandas DataFrame.
|
|
832
887
|
uels_on_axes : bool, optional
|
|
888
|
+
If True, assumes that the domain information is located in the axes
|
|
889
|
+
(index/columns) of the `records` object rather than the data values.
|
|
890
|
+
Use this when passing a DataFrame where the indices represent the set elements.
|
|
833
891
|
|
|
834
892
|
Examples
|
|
835
893
|
--------
|
|
836
894
|
>>> import gamspy as gp
|
|
837
|
-
>>> import numpy as np
|
|
838
895
|
>>> m = gp.Container()
|
|
839
896
|
>>> i = gp.Set(m, name="i")
|
|
840
897
|
>>> i.setRecords(["seattle", "san-diego"])
|
|
@@ -907,6 +964,11 @@ class Set(gt.Set, operable.Operable, Symbol, SetMixin):
|
|
|
907
964
|
-------
|
|
908
965
|
str
|
|
909
966
|
|
|
967
|
+
Raises
|
|
968
|
+
------
|
|
969
|
+
ValueError
|
|
970
|
+
When type is not circular or linear
|
|
971
|
+
|
|
910
972
|
Examples
|
|
911
973
|
--------
|
|
912
974
|
>>> import gamspy as gp
|
|
@@ -96,7 +96,11 @@ class UniverseAlias(gt.UniverseAlias):
|
|
|
96
96
|
|
|
97
97
|
def __init__(self, container: Container | None = None, name: str = "universe"):
|
|
98
98
|
# check if the name is a reserved word
|
|
99
|
-
name
|
|
99
|
+
if name is not None:
|
|
100
|
+
name = validation.validate_name(name)
|
|
101
|
+
else:
|
|
102
|
+
name = container._get_symbol_name(prefix="u")
|
|
103
|
+
|
|
100
104
|
if container is None:
|
|
101
105
|
try:
|
|
102
106
|
container = gp._ctx_managers[(os.getpid(), threading.get_native_id())]
|