gamsapi 52.5.0__cp312-cp312-win_amd64.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.
- gams/__init__.py +27 -0
- gams/_version.py +1 -0
- gams/connect/__init__.py +28 -0
- gams/connect/agents/__init__.py +24 -0
- gams/connect/agents/_excel/__init__.py +32 -0
- gams/connect/agents/_excel/excelagent.py +312 -0
- gams/connect/agents/_excel/workbook.py +155 -0
- gams/connect/agents/_sqlconnectors/__init__.py +42 -0
- gams/connect/agents/_sqlconnectors/_accesshandler.py +211 -0
- gams/connect/agents/_sqlconnectors/_databasehandler.py +250 -0
- gams/connect/agents/_sqlconnectors/_mysqlhandler.py +168 -0
- gams/connect/agents/_sqlconnectors/_postgreshandler.py +131 -0
- gams/connect/agents/_sqlconnectors/_pyodbchandler.py +112 -0
- gams/connect/agents/_sqlconnectors/_sqlalchemyhandler.py +74 -0
- gams/connect/agents/_sqlconnectors/_sqlitehandler.py +262 -0
- gams/connect/agents/_sqlconnectors/_sqlserverhandler.py +179 -0
- gams/connect/agents/concatenate.py +440 -0
- gams/connect/agents/connectagent.py +743 -0
- gams/connect/agents/csvreader.py +675 -0
- gams/connect/agents/csvwriter.py +151 -0
- gams/connect/agents/domainwriter.py +143 -0
- gams/connect/agents/excelreader.py +756 -0
- gams/connect/agents/excelwriter.py +467 -0
- gams/connect/agents/filter.py +223 -0
- gams/connect/agents/gamsreader.py +112 -0
- gams/connect/agents/gamswriter.py +239 -0
- gams/connect/agents/gdxreader.py +109 -0
- gams/connect/agents/gdxwriter.py +146 -0
- gams/connect/agents/labelmanipulator.py +303 -0
- gams/connect/agents/projection.py +539 -0
- gams/connect/agents/pythoncode.py +71 -0
- gams/connect/agents/rawcsvreader.py +248 -0
- gams/connect/agents/rawexcelreader.py +312 -0
- gams/connect/agents/schema/CSVReader.yaml +92 -0
- gams/connect/agents/schema/CSVWriter.yaml +44 -0
- gams/connect/agents/schema/Concatenate.yaml +52 -0
- gams/connect/agents/schema/DomainWriter.yaml +25 -0
- gams/connect/agents/schema/ExcelReader.yaml +121 -0
- gams/connect/agents/schema/ExcelWriter.yaml +78 -0
- gams/connect/agents/schema/Filter.yaml +74 -0
- gams/connect/agents/schema/GAMSReader.yaml +20 -0
- gams/connect/agents/schema/GAMSWriter.yaml +47 -0
- gams/connect/agents/schema/GDXReader.yaml +23 -0
- gams/connect/agents/schema/GDXWriter.yaml +32 -0
- gams/connect/agents/schema/LabelManipulator.yaml +99 -0
- gams/connect/agents/schema/Projection.yaml +24 -0
- gams/connect/agents/schema/PythonCode.yaml +6 -0
- gams/connect/agents/schema/RawCSVReader.yaml +34 -0
- gams/connect/agents/schema/RawExcelReader.yaml +42 -0
- gams/connect/agents/schema/SQLReader.yaml +75 -0
- gams/connect/agents/schema/SQLWriter.yaml +103 -0
- gams/connect/agents/sqlreader.py +301 -0
- gams/connect/agents/sqlwriter.py +276 -0
- gams/connect/connectdatabase.py +275 -0
- gams/connect/connectvalidator.py +93 -0
- gams/connect/errors.py +34 -0
- gams/control/__init__.py +136 -0
- gams/control/database.py +2231 -0
- gams/control/execution.py +1900 -0
- gams/control/options.py +2792 -0
- gams/control/workspace.py +1198 -0
- gams/core/__init__.py +24 -0
- gams/core/cfg/__init__.py +26 -0
- gams/core/cfg/_cfgmcc.cp312-win_amd64.pyd +0 -0
- gams/core/cfg/cfgmcc.py +519 -0
- gams/core/dct/__init__.py +26 -0
- gams/core/dct/_dctmcc.cp312-win_amd64.pyd +0 -0
- gams/core/dct/dctmcc.py +574 -0
- gams/core/embedded/__init__.py +26 -0
- gams/core/embedded/gamsemb.py +1024 -0
- gams/core/emp/__init__.py +24 -0
- gams/core/emp/emplexer.py +89 -0
- gams/core/emp/empyacc.py +281 -0
- gams/core/gdx/__init__.py +26 -0
- gams/core/gdx/_gdxcc.cp312-win_amd64.pyd +0 -0
- gams/core/gdx/gdxcc.py +866 -0
- gams/core/gev/__init__.py +26 -0
- gams/core/gev/_gevmcc.cp312-win_amd64.pyd +0 -0
- gams/core/gev/gevmcc.py +855 -0
- gams/core/gmd/__init__.py +26 -0
- gams/core/gmd/_gmdcc.cp312-win_amd64.pyd +0 -0
- gams/core/gmd/gmdcc.py +917 -0
- gams/core/gmo/__init__.py +26 -0
- gams/core/gmo/_gmomcc.cp312-win_amd64.pyd +0 -0
- gams/core/gmo/gmomcc.py +2046 -0
- gams/core/idx/__init__.py +26 -0
- gams/core/idx/_idxcc.cp312-win_amd64.pyd +0 -0
- gams/core/idx/idxcc.py +510 -0
- gams/core/numpy/__init__.py +29 -0
- gams/core/numpy/_gams2numpy.cp312-win_amd64.pyd +0 -0
- gams/core/numpy/gams2numpy.py +1048 -0
- gams/core/opt/__init__.py +26 -0
- gams/core/opt/_optcc.cp312-win_amd64.pyd +0 -0
- gams/core/opt/optcc.py +840 -0
- gams/engine/__init__.py +204 -0
- gams/engine/api/__init__.py +13 -0
- gams/engine/api/auth_api.py +7653 -0
- gams/engine/api/cleanup_api.py +751 -0
- gams/engine/api/default_api.py +887 -0
- gams/engine/api/hypercube_api.py +2629 -0
- gams/engine/api/jobs_api.py +5229 -0
- gams/engine/api/licenses_api.py +2220 -0
- gams/engine/api/namespaces_api.py +7783 -0
- gams/engine/api/usage_api.py +5627 -0
- gams/engine/api/users_api.py +5931 -0
- gams/engine/api_client.py +804 -0
- gams/engine/api_response.py +21 -0
- gams/engine/configuration.py +601 -0
- gams/engine/exceptions.py +216 -0
- gams/engine/models/__init__.py +86 -0
- gams/engine/models/bad_input.py +89 -0
- gams/engine/models/cleanable_job_result.py +104 -0
- gams/engine/models/cleanable_job_result_page.py +113 -0
- gams/engine/models/engine_license.py +107 -0
- gams/engine/models/files_not_found.py +93 -0
- gams/engine/models/forwarded_token_response.py +112 -0
- gams/engine/models/generic_key_value_pair.py +89 -0
- gams/engine/models/hypercube.py +160 -0
- gams/engine/models/hypercube_page.py +111 -0
- gams/engine/models/hypercube_summary.py +91 -0
- gams/engine/models/hypercube_token.py +97 -0
- gams/engine/models/identity_provider.py +107 -0
- gams/engine/models/identity_provider_ldap.py +121 -0
- gams/engine/models/identity_provider_oauth2.py +146 -0
- gams/engine/models/identity_provider_oauth2_scope.py +89 -0
- gams/engine/models/identity_provider_oauth2_with_secret.py +152 -0
- gams/engine/models/identity_provider_oidc.py +133 -0
- gams/engine/models/identity_provider_oidc_with_secret.py +143 -0
- gams/engine/models/inex.py +91 -0
- gams/engine/models/invitation.py +136 -0
- gams/engine/models/invitation_quota.py +106 -0
- gams/engine/models/invitation_token.py +87 -0
- gams/engine/models/job.py +165 -0
- gams/engine/models/job_no_text_entry.py +138 -0
- gams/engine/models/job_no_text_entry_page.py +111 -0
- gams/engine/models/license.py +91 -0
- gams/engine/models/log_piece.py +96 -0
- gams/engine/models/message.py +87 -0
- gams/engine/models/message_and_token.py +99 -0
- gams/engine/models/message_with_webhook_id.py +89 -0
- gams/engine/models/model_auth_token.py +87 -0
- gams/engine/models/model_configuration.py +125 -0
- gams/engine/models/model_default_instance.py +99 -0
- gams/engine/models/model_default_user_instance.py +98 -0
- gams/engine/models/model_hypercube_job.py +106 -0
- gams/engine/models/model_hypercube_usage.py +130 -0
- gams/engine/models/model_instance_info.py +116 -0
- gams/engine/models/model_instance_info_full.py +123 -0
- gams/engine/models/model_instance_pool_info.py +112 -0
- gams/engine/models/model_job_labels.py +179 -0
- gams/engine/models/model_job_usage.py +133 -0
- gams/engine/models/model_pool_usage.py +124 -0
- gams/engine/models/model_usage.py +115 -0
- gams/engine/models/model_user.py +96 -0
- gams/engine/models/model_userinstance_info.py +119 -0
- gams/engine/models/model_userinstancepool_info.py +95 -0
- gams/engine/models/model_version.py +91 -0
- gams/engine/models/models.py +120 -0
- gams/engine/models/namespace.py +104 -0
- gams/engine/models/namespace_quota.py +96 -0
- gams/engine/models/namespace_with_permission.py +96 -0
- gams/engine/models/not_found.py +91 -0
- gams/engine/models/password_policy.py +97 -0
- gams/engine/models/perm_and_username.py +89 -0
- gams/engine/models/quota.py +117 -0
- gams/engine/models/quota_exceeded.py +97 -0
- gams/engine/models/status_code_meaning.py +89 -0
- gams/engine/models/stream_entry.py +89 -0
- gams/engine/models/system_wide_license.py +92 -0
- gams/engine/models/text_entries.py +87 -0
- gams/engine/models/text_entry.py +101 -0
- gams/engine/models/time_span.py +95 -0
- gams/engine/models/time_span_pool_worker.py +99 -0
- gams/engine/models/token_forward_error.py +87 -0
- gams/engine/models/user.py +127 -0
- gams/engine/models/user_group_member.py +96 -0
- gams/engine/models/user_groups.py +108 -0
- gams/engine/models/vapid_info.py +87 -0
- gams/engine/models/webhook.py +138 -0
- gams/engine/models/webhook_parameterized_event.py +99 -0
- gams/engine/py.typed +0 -0
- gams/engine/rest.py +258 -0
- gams/magic/__init__.py +32 -0
- gams/magic/gams_magic.py +142 -0
- gams/magic/interactive.py +402 -0
- gams/tools/__init__.py +30 -0
- gams/tools/errors.py +34 -0
- gams/tools/toolcollection/__init__.py +24 -0
- gams/tools/toolcollection/alg/__init__.py +24 -0
- gams/tools/toolcollection/alg/rank.py +51 -0
- gams/tools/toolcollection/data/__init__.py +24 -0
- gams/tools/toolcollection/data/csvread.py +444 -0
- gams/tools/toolcollection/data/csvwrite.py +311 -0
- gams/tools/toolcollection/data/exceldump.py +47 -0
- gams/tools/toolcollection/data/sqlitewrite.py +276 -0
- gams/tools/toolcollection/gdxservice/__init__.py +24 -0
- gams/tools/toolcollection/gdxservice/gdxencoding.py +104 -0
- gams/tools/toolcollection/gdxservice/gdxrename.py +94 -0
- gams/tools/toolcollection/linalg/__init__.py +24 -0
- gams/tools/toolcollection/linalg/cholesky.py +57 -0
- gams/tools/toolcollection/linalg/eigenvalue.py +56 -0
- gams/tools/toolcollection/linalg/eigenvector.py +58 -0
- gams/tools/toolcollection/linalg/invert.py +55 -0
- gams/tools/toolcollection/linalg/ols.py +138 -0
- gams/tools/toolcollection/tooltemplate.py +321 -0
- gams/tools/toolcollection/win32/__init__.py +24 -0
- gams/tools/toolcollection/win32/excelmerge.py +93 -0
- gams/tools/toolcollection/win32/exceltalk.py +76 -0
- gams/tools/toolcollection/win32/msappavail.py +49 -0
- gams/tools/toolcollection/win32/shellexecute.py +54 -0
- gams/tools/tools.py +116 -0
- gams/transfer/__init__.py +35 -0
- gams/transfer/_abcs/__init__.py +37 -0
- gams/transfer/_abcs/container_abcs.py +433 -0
- gams/transfer/_internals/__init__.py +63 -0
- gams/transfer/_internals/algorithms.py +436 -0
- gams/transfer/_internals/casepreservingdict.py +124 -0
- gams/transfer/_internals/constants.py +270 -0
- gams/transfer/_internals/domainviolation.py +103 -0
- gams/transfer/_internals/specialvalues.py +172 -0
- gams/transfer/containers/__init__.py +26 -0
- gams/transfer/containers/_container.py +1794 -0
- gams/transfer/containers/_io/__init__.py +28 -0
- gams/transfer/containers/_io/containers.py +164 -0
- gams/transfer/containers/_io/gdx.py +1029 -0
- gams/transfer/containers/_io/gmd.py +872 -0
- gams/transfer/containers/_mixins/__init__.py +26 -0
- gams/transfer/containers/_mixins/ccc.py +1274 -0
- gams/transfer/syms/__init__.py +33 -0
- gams/transfer/syms/_methods/__init__.py +24 -0
- gams/transfer/syms/_methods/tables.py +120 -0
- gams/transfer/syms/_methods/toDict.py +115 -0
- gams/transfer/syms/_methods/toList.py +83 -0
- gams/transfer/syms/_methods/toValue.py +60 -0
- gams/transfer/syms/_mixins/__init__.py +32 -0
- gams/transfer/syms/_mixins/equals.py +626 -0
- gams/transfer/syms/_mixins/generateRecords.py +499 -0
- gams/transfer/syms/_mixins/pivot.py +313 -0
- gams/transfer/syms/_mixins/pve.py +627 -0
- gams/transfer/syms/_mixins/sa.py +27 -0
- gams/transfer/syms/_mixins/sapve.py +27 -0
- gams/transfer/syms/_mixins/saua.py +27 -0
- gams/transfer/syms/_mixins/sauapve.py +199 -0
- gams/transfer/syms/_mixins/spve.py +1528 -0
- gams/transfer/syms/_mixins/ve.py +936 -0
- gams/transfer/syms/container_syms/__init__.py +31 -0
- gams/transfer/syms/container_syms/_alias.py +984 -0
- gams/transfer/syms/container_syms/_equation.py +333 -0
- gams/transfer/syms/container_syms/_parameter.py +973 -0
- gams/transfer/syms/container_syms/_set.py +604 -0
- gams/transfer/syms/container_syms/_universe_alias.py +461 -0
- gams/transfer/syms/container_syms/_variable.py +321 -0
- gamsapi-52.5.0.dist-info/METADATA +150 -0
- gamsapi-52.5.0.dist-info/RECORD +257 -0
- gamsapi-52.5.0.dist-info/WHEEL +5 -0
- gamsapi-52.5.0.dist-info/licenses/LICENSE +22 -0
- gamsapi-52.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1794 @@
|
|
|
1
|
+
#
|
|
2
|
+
# GAMS - General Algebraic Modeling System Python API
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2017-2026 GAMS Development Corp. <support@gams.com>
|
|
5
|
+
# Copyright (c) 2017-2026 GAMS Software GmbH <support@gams.com>
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
# furnished to do so, subject to the following conditions:
|
|
13
|
+
#
|
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
# copies or substantial portions of the Software.
|
|
16
|
+
#
|
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
# SOFTWARE.
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
import os
|
|
27
|
+
import pathlib
|
|
28
|
+
import pandas as pd
|
|
29
|
+
import numpy as np
|
|
30
|
+
import gams.core.numpy as gnp
|
|
31
|
+
from gams import GamsWorkspace, GamsDatabase
|
|
32
|
+
from gams.core import gmd
|
|
33
|
+
from gams.transfer._internals import (
|
|
34
|
+
CasePreservingDict,
|
|
35
|
+
DestinationType,
|
|
36
|
+
check_all_same,
|
|
37
|
+
)
|
|
38
|
+
import gams.transfer._abcs as abcs
|
|
39
|
+
from gams.transfer.containers._mixins import CCCMixin
|
|
40
|
+
import gams.transfer.containers._io as io
|
|
41
|
+
from gams.transfer.syms import (
|
|
42
|
+
Set,
|
|
43
|
+
Parameter,
|
|
44
|
+
Variable,
|
|
45
|
+
Equation,
|
|
46
|
+
Alias,
|
|
47
|
+
UniverseAlias,
|
|
48
|
+
)
|
|
49
|
+
from typing import Optional, Union, List, Dict, Any
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_system_directory(system_directory: Union[None, str]) -> str:
|
|
53
|
+
"""
|
|
54
|
+
Gets the GAMS system directory.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
system_directory : None | str
|
|
59
|
+
GAMS system directory. If None, itnwill try to get the default one.
|
|
60
|
+
|
|
61
|
+
Returns
|
|
62
|
+
-------
|
|
63
|
+
str
|
|
64
|
+
GAMS system directory.
|
|
65
|
+
|
|
66
|
+
Raises
|
|
67
|
+
------
|
|
68
|
+
Exception
|
|
69
|
+
If no default system directory for a GAMS installation is found.
|
|
70
|
+
"""
|
|
71
|
+
if system_directory is None:
|
|
72
|
+
try:
|
|
73
|
+
ws = GamsWorkspace()
|
|
74
|
+
sysdir = pathlib.Path(ws.system_directory)
|
|
75
|
+
except:
|
|
76
|
+
raise Exception(
|
|
77
|
+
"Could not find a GAMS installation, "
|
|
78
|
+
"must manually specify system_directory"
|
|
79
|
+
)
|
|
80
|
+
else:
|
|
81
|
+
sysdir = pathlib.Path(system_directory)
|
|
82
|
+
|
|
83
|
+
return os.fspath(sysdir.expanduser().resolve())
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Container(CCCMixin, abcs.ABCContainer):
|
|
87
|
+
"""
|
|
88
|
+
A container is an object that holds all symbols and operates on them.
|
|
89
|
+
|
|
90
|
+
Parameters
|
|
91
|
+
----------
|
|
92
|
+
load_from : GamsDatabase | PathLike | str | ABCContainer, optional
|
|
93
|
+
The data source to read from, by default None
|
|
94
|
+
system_directory : str, optional
|
|
95
|
+
Path to the directory that holds the GAMS installation, by default None
|
|
96
|
+
|
|
97
|
+
Examples
|
|
98
|
+
--------
|
|
99
|
+
>>> import gams.transfer as gt
|
|
100
|
+
>>> m = gt.Container()
|
|
101
|
+
>>> i = gt.Set(m, "i")
|
|
102
|
+
|
|
103
|
+
Attributes
|
|
104
|
+
----------
|
|
105
|
+
data : dict
|
|
106
|
+
Dictionary that lists symbol names and symbol objects
|
|
107
|
+
modified : bool
|
|
108
|
+
Flag that identifies if the container has been modified
|
|
109
|
+
summary : dict
|
|
110
|
+
Returns a dict of only the metadata
|
|
111
|
+
system_directory : str
|
|
112
|
+
Returns the path to the system directory
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
def __init__(
|
|
116
|
+
self,
|
|
117
|
+
load_from: Optional[
|
|
118
|
+
Union["GamsDatabase", os.PathLike, str, "abcs.ABCContainer"]
|
|
119
|
+
] = None,
|
|
120
|
+
system_directory: Optional[str] = None,
|
|
121
|
+
) -> None:
|
|
122
|
+
# set up
|
|
123
|
+
self.system_directory = get_system_directory(system_directory)
|
|
124
|
+
self._gams2np = gnp.Gams2Numpy._bypass_workspace(self.system_directory)
|
|
125
|
+
self.data = CasePreservingDict()
|
|
126
|
+
self.modified = True
|
|
127
|
+
self._requires_state_check = True
|
|
128
|
+
|
|
129
|
+
# read
|
|
130
|
+
if load_from is not None:
|
|
131
|
+
self.read(load_from)
|
|
132
|
+
|
|
133
|
+
def __iter__(self):
|
|
134
|
+
return iter(self.data.items())
|
|
135
|
+
|
|
136
|
+
def __repr__(self):
|
|
137
|
+
return f"<GAMS Transfer Container ({hex(id(self))})>"
|
|
138
|
+
|
|
139
|
+
def __str__(self):
|
|
140
|
+
if len(self):
|
|
141
|
+
return f"<GAMS Transfer Container (w/ {len(self)} symbols)>"
|
|
142
|
+
else:
|
|
143
|
+
return f"<GAMS Transfer Container (empty)>"
|
|
144
|
+
|
|
145
|
+
def __getitem__(self, sym):
|
|
146
|
+
try:
|
|
147
|
+
return self.data[sym]
|
|
148
|
+
except KeyError:
|
|
149
|
+
raise KeyError(
|
|
150
|
+
f"Attempted retrieval of symbol `{sym}`, but `{sym}` does not"
|
|
151
|
+
" exist in the Container"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def __contains__(self, sym) -> bool:
|
|
155
|
+
if isinstance(sym, abcs.AnyContainerSymbol):
|
|
156
|
+
return hex(id(sym)) in [hex(id(i)) for i in self.data.values()]
|
|
157
|
+
elif isinstance(sym, str):
|
|
158
|
+
return sym in self.data
|
|
159
|
+
else:
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
@property
|
|
163
|
+
def system_directory(self):
|
|
164
|
+
"""
|
|
165
|
+
This property returns the path to the GAMS system directory.
|
|
166
|
+
|
|
167
|
+
Returns
|
|
168
|
+
-------
|
|
169
|
+
str
|
|
170
|
+
The path to the system directory.
|
|
171
|
+
"""
|
|
172
|
+
return self._system_directory
|
|
173
|
+
|
|
174
|
+
@system_directory.setter
|
|
175
|
+
def system_directory(self, sysdir: Union[os.PathLike, str]) -> None:
|
|
176
|
+
"""
|
|
177
|
+
Path to the system directory.
|
|
178
|
+
|
|
179
|
+
Parameters
|
|
180
|
+
----------
|
|
181
|
+
sysdir : PathLike | str
|
|
182
|
+
The path to the system directory.
|
|
183
|
+
"""
|
|
184
|
+
if not isinstance(sysdir, (os.PathLike, str)):
|
|
185
|
+
raise TypeError(
|
|
186
|
+
"'system_directory' expects type str or PathLike object, got"
|
|
187
|
+
f" {type(sysdir)}"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
sysdir = pathlib.Path(sysdir).expanduser().resolve()
|
|
191
|
+
|
|
192
|
+
if not sysdir.is_dir():
|
|
193
|
+
raise Exception(
|
|
194
|
+
f"GAMS system_directory '{os.fspath(sysdir)}' is not a" " directory"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
if not sysdir.exists():
|
|
198
|
+
raise Exception(
|
|
199
|
+
f"GAMS system_directory '{os.fspath(sysdir)}' does not exist, "
|
|
200
|
+
"check spelling or path specification"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
if not pathlib.Path(sysdir, "optgams.def").is_file():
|
|
204
|
+
raise Exception(
|
|
205
|
+
f"GAMS system_directory '{os.fspath(sysdir)}' is not a valid"
|
|
206
|
+
" GAMS directory"
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
self._system_directory = os.fspath(sysdir)
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def summary(self) -> dict:
|
|
213
|
+
"""
|
|
214
|
+
This property returns a summary of the container.
|
|
215
|
+
|
|
216
|
+
Returns
|
|
217
|
+
-------
|
|
218
|
+
dict
|
|
219
|
+
A summary including the container's system directory and its number of symbols.
|
|
220
|
+
"""
|
|
221
|
+
return {
|
|
222
|
+
"system_directory": self.system_directory,
|
|
223
|
+
"number_symbols": len(self),
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
def _check_format_uels(self, symbols):
|
|
227
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
228
|
+
raise Exception("Argument 'symbols' must be type str, list or NoneType.")
|
|
229
|
+
|
|
230
|
+
if symbols is None:
|
|
231
|
+
symbols = self.listSymbols(is_valid=True)
|
|
232
|
+
|
|
233
|
+
if isinstance(symbols, str):
|
|
234
|
+
symbols = [symbols]
|
|
235
|
+
|
|
236
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
237
|
+
raise Exception("Argument 'symbols' must only contain type str")
|
|
238
|
+
|
|
239
|
+
return symbols
|
|
240
|
+
|
|
241
|
+
def _formatUELs(self, method, symbols=None):
|
|
242
|
+
symbols = self._check_format_uels(symbols)
|
|
243
|
+
|
|
244
|
+
# loop through symbol objects
|
|
245
|
+
for symobj in self.getSymbols(symbols):
|
|
246
|
+
do_format = getattr(symobj, method)
|
|
247
|
+
do_format()
|
|
248
|
+
|
|
249
|
+
def lowerUELs(self, symbols: Optional[Union[str, List[str]]] = None) -> "Container":
|
|
250
|
+
"""
|
|
251
|
+
This function converts the UELs of specific symbols to lowercase. If the 'symbols' parameter is set to None (default), all symbols in the container will be processed.
|
|
252
|
+
|
|
253
|
+
Parameters
|
|
254
|
+
----------
|
|
255
|
+
symbols : str | List[str], optional
|
|
256
|
+
The symbol or list of symbols whose UELs you want to convert to lowercase. By default, it is set to None.
|
|
257
|
+
|
|
258
|
+
Returns
|
|
259
|
+
-------
|
|
260
|
+
Container
|
|
261
|
+
The updated container with some UELs converted to lowercase.
|
|
262
|
+
"""
|
|
263
|
+
symbols = self._check_format_uels(symbols)
|
|
264
|
+
|
|
265
|
+
# loop through symbol objects
|
|
266
|
+
for symobj in self.getSymbols(symbols):
|
|
267
|
+
symobj.lowerUELs()
|
|
268
|
+
|
|
269
|
+
return self
|
|
270
|
+
|
|
271
|
+
def upperUELs(self, symbols: Optional[Union[str, List[str]]] = None) -> "Container":
|
|
272
|
+
"""
|
|
273
|
+
This function converts the UELs of specific symbols to uppercase. If the 'symbols' parameter is set to None (default), all symbols in the container will be processed.
|
|
274
|
+
|
|
275
|
+
Parameters
|
|
276
|
+
----------
|
|
277
|
+
symbols : str | List[str], optional
|
|
278
|
+
The symbol or list of symbols whose UELs you want to convert to uppercase. By default, it is set to None.
|
|
279
|
+
|
|
280
|
+
Returns
|
|
281
|
+
-------
|
|
282
|
+
Container
|
|
283
|
+
The updated container with some UELs converted to uppercase.
|
|
284
|
+
"""
|
|
285
|
+
symbols = self._check_format_uels(symbols)
|
|
286
|
+
|
|
287
|
+
# loop through symbol objects
|
|
288
|
+
for symobj in self.getSymbols(symbols):
|
|
289
|
+
symobj.upperUELs()
|
|
290
|
+
|
|
291
|
+
return self
|
|
292
|
+
|
|
293
|
+
def lstripUELs(
|
|
294
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
295
|
+
) -> "Container":
|
|
296
|
+
"""
|
|
297
|
+
This function removes leading whitespaces from the UELs of specific symbols. If the 'symbols' parameter is set to None (default), all symbols in the container will undergo this operation.
|
|
298
|
+
|
|
299
|
+
Parameters
|
|
300
|
+
----------
|
|
301
|
+
symbols : str | List[str], optional
|
|
302
|
+
The symbol or list of symbols whose UELs you wish to process. By default, it is set to None.
|
|
303
|
+
|
|
304
|
+
Returns
|
|
305
|
+
-------
|
|
306
|
+
Container
|
|
307
|
+
The updated container with leading whitespaces removed from the UELs of some symbols.
|
|
308
|
+
"""
|
|
309
|
+
symbols = self._check_format_uels(symbols)
|
|
310
|
+
|
|
311
|
+
# loop through symbol objects
|
|
312
|
+
for symobj in self.getSymbols(symbols):
|
|
313
|
+
symobj.lstripUELs()
|
|
314
|
+
|
|
315
|
+
return self
|
|
316
|
+
|
|
317
|
+
def rstripUELs(
|
|
318
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
319
|
+
) -> "Container":
|
|
320
|
+
"""
|
|
321
|
+
This function removes trailing whitespaces from the UELs of specific symbols. If the 'symbols' parameter is set to None (default), all symbols in the container will undergo this operation.
|
|
322
|
+
|
|
323
|
+
Parameters
|
|
324
|
+
----------
|
|
325
|
+
symbols : str | List[str], optional
|
|
326
|
+
The symbol or list of symbols whose UELs you wish to process. By default, it is set to None.
|
|
327
|
+
|
|
328
|
+
Returns
|
|
329
|
+
-------
|
|
330
|
+
Container
|
|
331
|
+
The updated container with trailing whitespaces removed from the UELs of some symbols.
|
|
332
|
+
"""
|
|
333
|
+
symbols = self._check_format_uels(symbols)
|
|
334
|
+
|
|
335
|
+
# loop through symbol objects
|
|
336
|
+
for symobj in self.getSymbols(symbols):
|
|
337
|
+
symobj.rstripUELs()
|
|
338
|
+
|
|
339
|
+
return self
|
|
340
|
+
|
|
341
|
+
def stripUELs(self, symbols: Optional[Union[str, List[str]]] = None) -> "Container":
|
|
342
|
+
"""
|
|
343
|
+
This function removes leading and trailing whitespaces from the UELs of specific symbols. If the 'symbols' parameter is set to None (default), all symbols in the container will undergo this operation.
|
|
344
|
+
|
|
345
|
+
Parameters
|
|
346
|
+
----------
|
|
347
|
+
symbols : str | List[str], optional
|
|
348
|
+
The symbol or list of symbols whose UELs you wish to process. By default, it is set to None.
|
|
349
|
+
|
|
350
|
+
Returns
|
|
351
|
+
-------
|
|
352
|
+
Container
|
|
353
|
+
The updated container with leading and trailing whitespaces removed from the UELs of some symbols.
|
|
354
|
+
"""
|
|
355
|
+
symbols = self._check_format_uels(symbols)
|
|
356
|
+
|
|
357
|
+
# loop through symbol objects
|
|
358
|
+
for symobj in self.getSymbols(symbols):
|
|
359
|
+
symobj.stripUELs()
|
|
360
|
+
|
|
361
|
+
return self
|
|
362
|
+
|
|
363
|
+
def capitalizeUELs(
|
|
364
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
365
|
+
) -> "Container":
|
|
366
|
+
"""
|
|
367
|
+
This function capitalizes the UELs of specific symbols. If the 'symbols' parameter is set to None (default), all symbols in the container will undergo this capitalization operation.
|
|
368
|
+
|
|
369
|
+
Parameters
|
|
370
|
+
----------
|
|
371
|
+
symbols : str | List[str], optional
|
|
372
|
+
The symbol or list of symbols whose UELs you wish to capitalize. By default, it is set to None.
|
|
373
|
+
|
|
374
|
+
Returns
|
|
375
|
+
-------
|
|
376
|
+
Container
|
|
377
|
+
The updated container with UELs capitalized for some symbols.
|
|
378
|
+
"""
|
|
379
|
+
symbols = self._check_format_uels(symbols)
|
|
380
|
+
|
|
381
|
+
# loop through symbol objects
|
|
382
|
+
for symobj in self.getSymbols(symbols):
|
|
383
|
+
symobj.capitalizeUELs()
|
|
384
|
+
|
|
385
|
+
return self
|
|
386
|
+
|
|
387
|
+
def casefoldUELs(
|
|
388
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
389
|
+
) -> "Container":
|
|
390
|
+
"""
|
|
391
|
+
This function performs case folding on the UELs of specific symbols, converting them to lowercase. If the 'symbols' parameter is set to None (default), all symbols in the container will undergo this case folding operation.
|
|
392
|
+
|
|
393
|
+
Parameters
|
|
394
|
+
----------
|
|
395
|
+
symbols : str | List[str], optional
|
|
396
|
+
The symbol or list of symbols whose UELs you wish to convert to lowercase. By default, it is set to None.
|
|
397
|
+
|
|
398
|
+
Returns
|
|
399
|
+
-------
|
|
400
|
+
Container
|
|
401
|
+
The updated container with UELs converted to lowercase for some symbols.
|
|
402
|
+
"""
|
|
403
|
+
symbols = self._check_format_uels(symbols)
|
|
404
|
+
|
|
405
|
+
# loop through symbol objects
|
|
406
|
+
for symobj in self.getSymbols(symbols):
|
|
407
|
+
symobj.casefoldUELs()
|
|
408
|
+
|
|
409
|
+
return self
|
|
410
|
+
|
|
411
|
+
def titleUELs(self, symbols: Optional[Union[str, List[str]]] = None) -> "Container":
|
|
412
|
+
"""
|
|
413
|
+
This function capitalizes the UELs of specific symbols in title case. If the 'symbols' parameter is set to None (default), all symbols in the container will undergo this capitalization operation.
|
|
414
|
+
|
|
415
|
+
Parameters
|
|
416
|
+
----------
|
|
417
|
+
symbols : str | List[str], optional
|
|
418
|
+
The symbol or list of symbols whose UELs you wish to capitalize in title case. By default, it is set to None.
|
|
419
|
+
|
|
420
|
+
Returns
|
|
421
|
+
-------
|
|
422
|
+
Container
|
|
423
|
+
The updated container with UELs capitalized in title case for some symbols.
|
|
424
|
+
|
|
425
|
+
"""
|
|
426
|
+
symbols = self._check_format_uels(symbols)
|
|
427
|
+
|
|
428
|
+
# loop through symbol objects
|
|
429
|
+
for symobj in self.getSymbols(symbols):
|
|
430
|
+
symobj.titleUELs()
|
|
431
|
+
|
|
432
|
+
return self
|
|
433
|
+
|
|
434
|
+
def ljustUELs(
|
|
435
|
+
self,
|
|
436
|
+
length: int,
|
|
437
|
+
fill_character: Optional[str] = None,
|
|
438
|
+
symbols: Optional[Union[str, List[str]]] = None,
|
|
439
|
+
) -> "Container":
|
|
440
|
+
"""
|
|
441
|
+
This function left-justifies the UELs of specific symbols within the container, padding them with a specified fill character to reach the desired length.
|
|
442
|
+
|
|
443
|
+
Parameters
|
|
444
|
+
----------
|
|
445
|
+
length : int
|
|
446
|
+
The target length to which UELs will be left-justified.
|
|
447
|
+
|
|
448
|
+
fill_character : str, optional
|
|
449
|
+
The character used for padding the UELs to the specified length. If not provided, it defaults to a whitespace.
|
|
450
|
+
|
|
451
|
+
symbols : str | List[str], optional
|
|
452
|
+
The symbol or list of symbols whose UELs you want to left-justify. By default, it is set to None, meaning all symbols in the container will undergo this left-justification.
|
|
453
|
+
|
|
454
|
+
Returns
|
|
455
|
+
-------
|
|
456
|
+
Container
|
|
457
|
+
The updated container with UELs left-justified for some symbols.
|
|
458
|
+
"""
|
|
459
|
+
symbols = self._check_format_uels(symbols)
|
|
460
|
+
|
|
461
|
+
# loop through symbol objects
|
|
462
|
+
for symobj in self.getSymbols(symbols):
|
|
463
|
+
try:
|
|
464
|
+
symobj.ljustUELs(length, fill_character)
|
|
465
|
+
except Exception as err:
|
|
466
|
+
raise Exception(
|
|
467
|
+
"Could not successfully left justify (ljust) categories"
|
|
468
|
+
f" in `{symobj.name}`. Reason: {err}"
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
return self
|
|
472
|
+
|
|
473
|
+
def rjustUELs(
|
|
474
|
+
self,
|
|
475
|
+
length: int,
|
|
476
|
+
fill_character: Optional[str] = None,
|
|
477
|
+
symbols: Optional[Union[str, List[str]]] = None,
|
|
478
|
+
) -> "Container":
|
|
479
|
+
"""
|
|
480
|
+
This function right-justifies the UELs of specific symbols within the container, padding them with a specified fill character to reach the desired length.
|
|
481
|
+
|
|
482
|
+
Parameters
|
|
483
|
+
----------
|
|
484
|
+
length : int
|
|
485
|
+
The target length to which UELs will be right-justified.
|
|
486
|
+
|
|
487
|
+
fill_character : str, optional
|
|
488
|
+
The character used for padding the UELs to the specified length. If not provided, it defaults to a whitespace.
|
|
489
|
+
|
|
490
|
+
symbols : str | List[str], optional
|
|
491
|
+
The symbol or list of symbols whose UELs you want to right-justify. By default, it is set to None, meaning all symbols in the container will undergo this right-justification.
|
|
492
|
+
|
|
493
|
+
Returns
|
|
494
|
+
-------
|
|
495
|
+
Container
|
|
496
|
+
The updated container with UELs right-justified for some symbols.
|
|
497
|
+
"""
|
|
498
|
+
symbols = self._check_format_uels(symbols)
|
|
499
|
+
|
|
500
|
+
# loop through symbol objects
|
|
501
|
+
for symobj in self.getSymbols(symbols):
|
|
502
|
+
try:
|
|
503
|
+
symobj.rjustUELs(length, fill_character)
|
|
504
|
+
except Exception as err:
|
|
505
|
+
raise Exception(
|
|
506
|
+
"Could not successfully right justify (rjust) categories"
|
|
507
|
+
f" in `{symobj.name}`. Reason: {err}"
|
|
508
|
+
)
|
|
509
|
+
return self
|
|
510
|
+
|
|
511
|
+
def getUELs(
|
|
512
|
+
self,
|
|
513
|
+
symbols: Optional[Union[str, List[str]]] = None,
|
|
514
|
+
ignore_unused: bool = False,
|
|
515
|
+
unique_only: bool = False,
|
|
516
|
+
) -> List[str]:
|
|
517
|
+
"""
|
|
518
|
+
Retrieve the (UELs) associated with one or more symbols in the Container.
|
|
519
|
+
|
|
520
|
+
This method retrieves the (UELs) corresponding to the specified symbols in the Container.
|
|
521
|
+
|
|
522
|
+
Parameters
|
|
523
|
+
----------
|
|
524
|
+
symbols : str | List[str], optional
|
|
525
|
+
An optional parameter specifying the symbol names for which to retrieve UELs, by default None.
|
|
526
|
+
|
|
527
|
+
ignore_unused : bool, optional
|
|
528
|
+
A flag to whether or not include unused symbols, by default False
|
|
529
|
+
|
|
530
|
+
unique_only : bool, optional
|
|
531
|
+
A flag to whether or not return only unique UELs, by default False
|
|
532
|
+
|
|
533
|
+
Returns
|
|
534
|
+
-------
|
|
535
|
+
List[str]
|
|
536
|
+
A list of (UELs) associated with the specified symbols.
|
|
537
|
+
|
|
538
|
+
Raises
|
|
539
|
+
------
|
|
540
|
+
TypeError
|
|
541
|
+
If 'unique_only' is not of type bool.
|
|
542
|
+
TypeError
|
|
543
|
+
If 'symbols' is not of type str, iterable, or NoneType.
|
|
544
|
+
TypeError
|
|
545
|
+
If 'ignore_unused' is not of type bool.
|
|
546
|
+
Exception
|
|
547
|
+
If an element in 'symbols' is not of type str.
|
|
548
|
+
"""
|
|
549
|
+
|
|
550
|
+
if not isinstance(unique_only, bool):
|
|
551
|
+
raise Exception("Argument 'unique_only' must be type bool.")
|
|
552
|
+
|
|
553
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
554
|
+
raise Exception("Argument 'symbols' must be type str, list or NoneType.")
|
|
555
|
+
|
|
556
|
+
if symbols is None:
|
|
557
|
+
symbols = self.listSymbols(is_valid=True)
|
|
558
|
+
|
|
559
|
+
if isinstance(symbols, str):
|
|
560
|
+
symbols = [symbols]
|
|
561
|
+
|
|
562
|
+
if not isinstance(ignore_unused, bool):
|
|
563
|
+
raise TypeError(f"Argument 'ignore_unused' must be type bool")
|
|
564
|
+
|
|
565
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
566
|
+
raise Exception("Argument 'symbols' must only contain type str")
|
|
567
|
+
|
|
568
|
+
# loop through symbol objects and get UELs
|
|
569
|
+
uni = {}
|
|
570
|
+
for symobj in self.getSymbols(symbols):
|
|
571
|
+
if not isinstance(symobj, abcs.AnyContainerAlias):
|
|
572
|
+
if symobj.records is not None:
|
|
573
|
+
uni.update(
|
|
574
|
+
dict.fromkeys(symobj.getUELs(ignore_unused=ignore_unused))
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
if unique_only:
|
|
578
|
+
return list(CasePreservingDict().fromkeys(uni.keys()).keys())
|
|
579
|
+
else:
|
|
580
|
+
return list(uni.keys())
|
|
581
|
+
|
|
582
|
+
def renameUELs(
|
|
583
|
+
self,
|
|
584
|
+
uels: Dict[str, str],
|
|
585
|
+
symbols: Optional[List[str]] = None,
|
|
586
|
+
allow_merge: bool = False,
|
|
587
|
+
) -> None:
|
|
588
|
+
"""
|
|
589
|
+
Rename unique element labels (UELs) associated with symbols in the Container.
|
|
590
|
+
|
|
591
|
+
Parameters
|
|
592
|
+
----------
|
|
593
|
+
uels : Dict[str, str]
|
|
594
|
+
A dictionary mapping old UELs to their new names. The keys are the old UELs that you want to rename,
|
|
595
|
+
and the values are the new names for those UELs
|
|
596
|
+
|
|
597
|
+
symbols : List[str]], optional
|
|
598
|
+
An optional parameter specifying the symbol names for which you want to rename UELs, by default None
|
|
599
|
+
|
|
600
|
+
allow_merge : bool, optional
|
|
601
|
+
A flag that allows merging UELs with existing UELs, by default False
|
|
602
|
+
|
|
603
|
+
Raises
|
|
604
|
+
------
|
|
605
|
+
Exception
|
|
606
|
+
If the Container is currently invalid (not valid) because UELs (categories) cannot be accessed.
|
|
607
|
+
TypeError
|
|
608
|
+
If 'uels' is not of type dict.
|
|
609
|
+
TypeError
|
|
610
|
+
If 'symbols' is not of type list or NoneType.
|
|
611
|
+
TypeError
|
|
612
|
+
If an element in 'symbols' is not of type str.
|
|
613
|
+
"""
|
|
614
|
+
if not self.isValid():
|
|
615
|
+
raise Exception(
|
|
616
|
+
"Container is currently invalid -- must be valid in order to"
|
|
617
|
+
" access UELs (categories)."
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
# ARG: uels
|
|
621
|
+
if not isinstance(uels, dict):
|
|
622
|
+
raise TypeError("Argument 'uels' must be type dict")
|
|
623
|
+
|
|
624
|
+
# ARG: symbols
|
|
625
|
+
if not isinstance(symbols, (list, type(None))):
|
|
626
|
+
raise TypeError("Argument 'symbols' must be type list or NoneType")
|
|
627
|
+
|
|
628
|
+
if symbols is None:
|
|
629
|
+
symbols = list(self.data.keys())
|
|
630
|
+
|
|
631
|
+
if isinstance(symbols, list):
|
|
632
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
633
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
634
|
+
|
|
635
|
+
for symobj in self.getSymbols(symbols):
|
|
636
|
+
if not isinstance(symobj, abcs.ABCUniverseAlias):
|
|
637
|
+
symobj.renameUELs(uels, allow_merge=allow_merge)
|
|
638
|
+
|
|
639
|
+
def removeUELs(
|
|
640
|
+
self,
|
|
641
|
+
uels: Optional[Union[str, List[str]]] = None,
|
|
642
|
+
symbols: Optional[List[str]] = None,
|
|
643
|
+
) -> None:
|
|
644
|
+
"""
|
|
645
|
+
Remove specific unique element labels (UELs) from one or more symbols in the Container.
|
|
646
|
+
|
|
647
|
+
Parameters
|
|
648
|
+
----------
|
|
649
|
+
uels : str | List[str], optional
|
|
650
|
+
An optional parameter specifying the unique element labels (UELs) to be removed from the symbols, by default None
|
|
651
|
+
|
|
652
|
+
symbols : List[str], optional
|
|
653
|
+
An optional parameter specifying the symbols from which to remove the specified UELs, by default None
|
|
654
|
+
|
|
655
|
+
Raises
|
|
656
|
+
------
|
|
657
|
+
TypeError
|
|
658
|
+
If 'uels' is not of type list, str, or NoneType.
|
|
659
|
+
TypeError
|
|
660
|
+
If an element in 'uels' is not of type str.
|
|
661
|
+
TypeError
|
|
662
|
+
If 'symbols' is not of type list or NoneType.
|
|
663
|
+
TypeError
|
|
664
|
+
If an element in 'symbols' is not of type str.
|
|
665
|
+
|
|
666
|
+
Exception
|
|
667
|
+
If the Container is currently invalid, as it must be valid to access UELs (categories).
|
|
668
|
+
"""
|
|
669
|
+
if not self.isValid():
|
|
670
|
+
raise Exception(
|
|
671
|
+
"Container is currently invalid -- must be valid in order to"
|
|
672
|
+
" access UELs (categories)."
|
|
673
|
+
)
|
|
674
|
+
|
|
675
|
+
if not isinstance(uels, (list, str, type(None))):
|
|
676
|
+
raise TypeError("Argument 'uels' must be type list, str or NoneType")
|
|
677
|
+
|
|
678
|
+
if isinstance(uels, str):
|
|
679
|
+
uels = [uels]
|
|
680
|
+
|
|
681
|
+
if isinstance(uels, list):
|
|
682
|
+
if any(not isinstance(i, str) for i in uels):
|
|
683
|
+
raise TypeError("Argument 'uels' must contain only type str")
|
|
684
|
+
|
|
685
|
+
if not isinstance(symbols, (list, type(None))):
|
|
686
|
+
raise TypeError("Argument 'symbols' must be type list or NoneType")
|
|
687
|
+
|
|
688
|
+
if symbols is None:
|
|
689
|
+
symbols = list(self.data.keys())
|
|
690
|
+
|
|
691
|
+
if isinstance(symbols, list):
|
|
692
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
693
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
694
|
+
|
|
695
|
+
for symobj in self.getSymbols(symbols):
|
|
696
|
+
if not isinstance(symobj, abcs.ABCUniverseAlias):
|
|
697
|
+
symobj.removeUELs(uels)
|
|
698
|
+
|
|
699
|
+
def getDomainViolations(
|
|
700
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
701
|
+
) -> Union[list, None]:
|
|
702
|
+
"""
|
|
703
|
+
Get domain violations for one or more symbols in the Container.
|
|
704
|
+
|
|
705
|
+
Parameters
|
|
706
|
+
----------
|
|
707
|
+
symbols : str | List[str], optional
|
|
708
|
+
An optional parameter specifying the symbols for which to retrieve domain violations, by default None
|
|
709
|
+
|
|
710
|
+
Returns
|
|
711
|
+
-------
|
|
712
|
+
list | None
|
|
713
|
+
A list of domain violations for the specified symbols, or None if there are no domain violations.
|
|
714
|
+
|
|
715
|
+
Raises
|
|
716
|
+
------
|
|
717
|
+
TypeError
|
|
718
|
+
If 'symbols' is not of type list, str, or NoneType.
|
|
719
|
+
TypeError
|
|
720
|
+
If an element in 'symbols' is not of type str.
|
|
721
|
+
"""
|
|
722
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
723
|
+
raise TypeError("Argument 'symbols' must be type list or NoneType")
|
|
724
|
+
|
|
725
|
+
if symbols is None:
|
|
726
|
+
symbols = list(self.data.keys())
|
|
727
|
+
|
|
728
|
+
if isinstance(symbols, str):
|
|
729
|
+
symbols = [symbols]
|
|
730
|
+
|
|
731
|
+
if isinstance(symbols, list):
|
|
732
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
733
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
734
|
+
|
|
735
|
+
dvs = []
|
|
736
|
+
for symobj in self.getSymbols(symbols):
|
|
737
|
+
violations = symobj.getDomainViolations()
|
|
738
|
+
if violations is not None:
|
|
739
|
+
dvs.extend(violations)
|
|
740
|
+
|
|
741
|
+
if len(dvs) != 0:
|
|
742
|
+
return dvs
|
|
743
|
+
else:
|
|
744
|
+
return None
|
|
745
|
+
|
|
746
|
+
def hasDomainViolations(
|
|
747
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
748
|
+
) -> bool:
|
|
749
|
+
"""
|
|
750
|
+
Check if domain violations exist for one or more symbols in the Container.
|
|
751
|
+
|
|
752
|
+
Parameters
|
|
753
|
+
----------
|
|
754
|
+
symbols : str | List[str], optional
|
|
755
|
+
An optional parameter specifying the symbols to check for domain violations, by default None
|
|
756
|
+
|
|
757
|
+
Returns
|
|
758
|
+
-------
|
|
759
|
+
bool
|
|
760
|
+
True if domain violations exist for any of the specified symbols, False otherwise.
|
|
761
|
+
|
|
762
|
+
Raises
|
|
763
|
+
------
|
|
764
|
+
TypeError
|
|
765
|
+
If 'symbols' is not of type list, str, or NoneType.
|
|
766
|
+
TypeError
|
|
767
|
+
If an element in 'symbols' is not of type str.
|
|
768
|
+
"""
|
|
769
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
770
|
+
raise TypeError("Argument 'symbols' must be type list or NoneType")
|
|
771
|
+
|
|
772
|
+
if symbols is None:
|
|
773
|
+
symbols = list(self.data.keys())
|
|
774
|
+
|
|
775
|
+
if isinstance(symbols, str):
|
|
776
|
+
symbols = [symbols]
|
|
777
|
+
|
|
778
|
+
if isinstance(symbols, list):
|
|
779
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
780
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
781
|
+
|
|
782
|
+
for symobj in self.getSymbols(symbols):
|
|
783
|
+
if symobj.hasDomainViolations():
|
|
784
|
+
return True
|
|
785
|
+
|
|
786
|
+
return False
|
|
787
|
+
|
|
788
|
+
def countDomainViolations(
|
|
789
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
790
|
+
) -> Dict[str, int]:
|
|
791
|
+
"""
|
|
792
|
+
Count domain violations for one or more symbols in the Container.
|
|
793
|
+
|
|
794
|
+
Parameters
|
|
795
|
+
----------
|
|
796
|
+
symbols : str | List[str], optional
|
|
797
|
+
An optional parameter specifying the symbols to count domain violations for, by default None
|
|
798
|
+
|
|
799
|
+
Returns
|
|
800
|
+
-------
|
|
801
|
+
Dict[str, int]
|
|
802
|
+
A dictionary where keys are symbol names with domain violations, and values are the corresponding counts of domain violations.
|
|
803
|
+
|
|
804
|
+
Raises
|
|
805
|
+
------
|
|
806
|
+
TypeError
|
|
807
|
+
If 'symbols' is not of type list, str, or NoneType.
|
|
808
|
+
TypeError
|
|
809
|
+
If an element in 'symbols' is not of type str.
|
|
810
|
+
"""
|
|
811
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
812
|
+
raise TypeError("Argument 'symbols' must be type list or NoneType")
|
|
813
|
+
|
|
814
|
+
if symbols is None:
|
|
815
|
+
symbols = list(self.data.keys())
|
|
816
|
+
|
|
817
|
+
if isinstance(symbols, str):
|
|
818
|
+
symbols = [symbols]
|
|
819
|
+
|
|
820
|
+
if isinstance(symbols, list):
|
|
821
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
822
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
823
|
+
|
|
824
|
+
dvs = {}
|
|
825
|
+
|
|
826
|
+
for symobj in self.getSymbols(symbols):
|
|
827
|
+
count = symobj.countDomainViolations()
|
|
828
|
+
if count != 0:
|
|
829
|
+
dvs.update({symobj.name: count})
|
|
830
|
+
|
|
831
|
+
return dvs
|
|
832
|
+
|
|
833
|
+
def dropDomainViolations(
|
|
834
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
835
|
+
) -> None:
|
|
836
|
+
"""
|
|
837
|
+
Drop domain violations for one or more symbols in the Container.
|
|
838
|
+
|
|
839
|
+
Parameters
|
|
840
|
+
----------
|
|
841
|
+
symbols : str | List[str], optional
|
|
842
|
+
An optional parameter specifying the symbols to drop domain violations for, by default None
|
|
843
|
+
|
|
844
|
+
Raises
|
|
845
|
+
------
|
|
846
|
+
TypeError
|
|
847
|
+
If 'symbols' is not of type list, str, or NoneType.
|
|
848
|
+
TypeError
|
|
849
|
+
If an element in 'symbols' is not of type str.
|
|
850
|
+
"""
|
|
851
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
852
|
+
raise TypeError("Argument 'symbols' must be type str, list or NoneType")
|
|
853
|
+
|
|
854
|
+
if symbols is None:
|
|
855
|
+
symbols = list(self.countDomainViolations().keys())
|
|
856
|
+
|
|
857
|
+
if isinstance(symbols, str):
|
|
858
|
+
symbols = [symbols]
|
|
859
|
+
|
|
860
|
+
if isinstance(symbols, list):
|
|
861
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
862
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
863
|
+
|
|
864
|
+
for symobj in self.getSymbols(symbols):
|
|
865
|
+
symobj.records.drop(index=symobj.findDomainViolations().index, inplace=True)
|
|
866
|
+
|
|
867
|
+
def countDuplicateRecords(
|
|
868
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
869
|
+
) -> Dict[str, int]:
|
|
870
|
+
"""
|
|
871
|
+
Count duplicate records for one or more symbols in the Container.
|
|
872
|
+
|
|
873
|
+
Parameters
|
|
874
|
+
----------
|
|
875
|
+
symbols : str | List[str], optional
|
|
876
|
+
An optional parameter specifying the symbols to count duplicate records for, by default None
|
|
877
|
+
|
|
878
|
+
Returns
|
|
879
|
+
-------
|
|
880
|
+
Dict[str, int]
|
|
881
|
+
A dictionary where keys are symbol names with duplicate records, and values are the count of duplicate records for each symbol.
|
|
882
|
+
|
|
883
|
+
Raises
|
|
884
|
+
------
|
|
885
|
+
TypeError
|
|
886
|
+
If 'symbols' is not of type list, str, or NoneType.
|
|
887
|
+
TypeError
|
|
888
|
+
If an element in 'symbols' is not of type str.
|
|
889
|
+
"""
|
|
890
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
891
|
+
raise TypeError("Argument 'symbols' must be type list or NoneType")
|
|
892
|
+
|
|
893
|
+
if symbols is None:
|
|
894
|
+
symbols = list(self.data.keys())
|
|
895
|
+
|
|
896
|
+
if isinstance(symbols, str):
|
|
897
|
+
symbols = [symbols]
|
|
898
|
+
|
|
899
|
+
if isinstance(symbols, list):
|
|
900
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
901
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
902
|
+
|
|
903
|
+
dups = {}
|
|
904
|
+
|
|
905
|
+
for symobj in self.getSymbols(symbols):
|
|
906
|
+
count = symobj.countDuplicateRecords()
|
|
907
|
+
if count != 0:
|
|
908
|
+
dups.update({symobj.name: count})
|
|
909
|
+
|
|
910
|
+
return dups
|
|
911
|
+
|
|
912
|
+
def hasDuplicateRecords(
|
|
913
|
+
self, symbols: Optional[Union[str, List[str]]] = None
|
|
914
|
+
) -> bool:
|
|
915
|
+
"""
|
|
916
|
+
Check if the Container has any duplicate records for one or more symbols.
|
|
917
|
+
|
|
918
|
+
Parameters
|
|
919
|
+
----------
|
|
920
|
+
symbols : str | List[str], optional
|
|
921
|
+
An optional parameter specifying the symbols to check for duplicate records, by default None
|
|
922
|
+
|
|
923
|
+
Returns
|
|
924
|
+
-------
|
|
925
|
+
bool
|
|
926
|
+
True if duplicate records are found for any of the specified symbols; False otherwise.
|
|
927
|
+
|
|
928
|
+
Raises
|
|
929
|
+
------
|
|
930
|
+
TypeError
|
|
931
|
+
If 'symbols' is not of type list, str, or NoneType.
|
|
932
|
+
TypeError
|
|
933
|
+
If an element in 'symbols' is not of type str.
|
|
934
|
+
"""
|
|
935
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
936
|
+
raise TypeError("Argument 'symbols' must be type list or NoneType")
|
|
937
|
+
|
|
938
|
+
if symbols is None:
|
|
939
|
+
symbols = list(self.data.keys())
|
|
940
|
+
|
|
941
|
+
if isinstance(symbols, str):
|
|
942
|
+
symbols = [symbols]
|
|
943
|
+
|
|
944
|
+
if isinstance(symbols, list):
|
|
945
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
946
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
947
|
+
|
|
948
|
+
for symobj in self.getSymbols(symbols):
|
|
949
|
+
if symobj.hasDuplicateRecords():
|
|
950
|
+
return True
|
|
951
|
+
|
|
952
|
+
return False
|
|
953
|
+
|
|
954
|
+
def dropDuplicateRecords(
|
|
955
|
+
self,
|
|
956
|
+
symbols: Optional[Union[str, List[str]]] = None,
|
|
957
|
+
keep: str = "first",
|
|
958
|
+
) -> None:
|
|
959
|
+
"""
|
|
960
|
+
Remove duplicate records from the specified symbols in the Container.
|
|
961
|
+
|
|
962
|
+
Parameters
|
|
963
|
+
----------
|
|
964
|
+
symbols : str | List[str], optional
|
|
965
|
+
An optional parameter specifying the symbols from which to remove duplicate records, by default None
|
|
966
|
+
|
|
967
|
+
keep : str, optional
|
|
968
|
+
A string indicating which duplicate records to keep, by default "first"
|
|
969
|
+
|
|
970
|
+
Raises
|
|
971
|
+
------
|
|
972
|
+
TypeError
|
|
973
|
+
If 'symbols' is not of type list, str, or NoneType.
|
|
974
|
+
TypeError
|
|
975
|
+
If an element in 'symbols' is not of type str.
|
|
976
|
+
"""
|
|
977
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
978
|
+
raise TypeError("Argument 'symbols' must be type list or NoneType")
|
|
979
|
+
|
|
980
|
+
if symbols is None:
|
|
981
|
+
symbols = list(self.countDuplicateRecords().keys())
|
|
982
|
+
|
|
983
|
+
if isinstance(symbols, str):
|
|
984
|
+
symbols = [symbols]
|
|
985
|
+
|
|
986
|
+
if isinstance(symbols, list):
|
|
987
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
988
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
989
|
+
|
|
990
|
+
for symobj in self.getSymbols(symbols):
|
|
991
|
+
symobj.records.drop(
|
|
992
|
+
index=symobj.findDuplicateRecords(keep).index, inplace=True
|
|
993
|
+
)
|
|
994
|
+
|
|
995
|
+
def _assert_valid_records(self, symbols=None):
|
|
996
|
+
if symbols is None:
|
|
997
|
+
symbols = self.listSymbols()
|
|
998
|
+
|
|
999
|
+
for symobj in self.getSymbols(symbols):
|
|
1000
|
+
if not isinstance(symobj, abcs.ABCUniverseAlias):
|
|
1001
|
+
symobj._assert_valid_records()
|
|
1002
|
+
|
|
1003
|
+
def _assert_is_valid(self, symbols):
|
|
1004
|
+
if self._requires_state_check:
|
|
1005
|
+
# make sure that all symbols have consistent naming
|
|
1006
|
+
for symname, symobj in zip(symbols, self.getSymbols(symbols)):
|
|
1007
|
+
if symname.casefold() != symobj.name.casefold():
|
|
1008
|
+
raise Exception(
|
|
1009
|
+
"Container data dict key is inconsistent with the"
|
|
1010
|
+
f" symbol object name (`{symname}` !="
|
|
1011
|
+
f" `{symobj.name}`). This inconsistency could have"
|
|
1012
|
+
" resulted from a symbol copy/deepcopy operation"
|
|
1013
|
+
" (i.e., `m[<new_symbol>] ="
|
|
1014
|
+
" copy.deepcopy(m[<existing_symbol>])`). Update"
|
|
1015
|
+
" symbol name with `<new_symbol>.name`."
|
|
1016
|
+
)
|
|
1017
|
+
|
|
1018
|
+
# make sure that all symbols reference the correct Container instance
|
|
1019
|
+
for symobj in self.getSymbols(symbols):
|
|
1020
|
+
if self != symobj.container:
|
|
1021
|
+
raise Exception(
|
|
1022
|
+
f"Symbol `{symobj.name}` has a broken Container"
|
|
1023
|
+
" reference. Symbol references Container at"
|
|
1024
|
+
f" {hex(id(symobj.container))} -- should be"
|
|
1025
|
+
f" referencing Container at {hex(id(self))}. This"
|
|
1026
|
+
" inconsistency could have resulted from a `deepcopy`"
|
|
1027
|
+
" of a symbol object (i.e., `new_container[<symbol>]"
|
|
1028
|
+
" = copy.deepcopy(old_container[<symbol>])`). Update"
|
|
1029
|
+
" symbol reference with `<symbol>.container ="
|
|
1030
|
+
" <new_container>`."
|
|
1031
|
+
)
|
|
1032
|
+
|
|
1033
|
+
if any(not symobj.isValid() for symobj in self.getSymbols(symbols)):
|
|
1034
|
+
raise Exception(
|
|
1035
|
+
"Container contains invalid symbols; invalid symbols can"
|
|
1036
|
+
" be found with the"
|
|
1037
|
+
" `<container>.listSymbols(is_valid=False)` method. Debug"
|
|
1038
|
+
" invalid symbol(s) by running"
|
|
1039
|
+
" `<symbol>.isValid(verbose=True, force=True)`` method on"
|
|
1040
|
+
" the symbol object."
|
|
1041
|
+
)
|
|
1042
|
+
|
|
1043
|
+
# check if there are graph cycles in the sets
|
|
1044
|
+
try:
|
|
1045
|
+
self._validSymbolOrder()
|
|
1046
|
+
except Exception as err:
|
|
1047
|
+
raise err
|
|
1048
|
+
|
|
1049
|
+
# if no exceptions, then turn self._requires_state_check 'off'
|
|
1050
|
+
self._requires_state_check = False
|
|
1051
|
+
|
|
1052
|
+
@property
|
|
1053
|
+
def modified(self) -> Union[bool, None]:
|
|
1054
|
+
return self._modified
|
|
1055
|
+
|
|
1056
|
+
@modified.setter
|
|
1057
|
+
def modified(self, modified: bool) -> None:
|
|
1058
|
+
if not isinstance(modified, bool):
|
|
1059
|
+
raise TypeError("Attribute 'modified' must be type bool")
|
|
1060
|
+
|
|
1061
|
+
self._modified = modified
|
|
1062
|
+
|
|
1063
|
+
if modified is False:
|
|
1064
|
+
for symname, symobj in self:
|
|
1065
|
+
symobj.modified = False
|
|
1066
|
+
|
|
1067
|
+
def _validSymbolOrder(self):
|
|
1068
|
+
ordered_symbols = []
|
|
1069
|
+
symbols_to_sort = [k for k, _ in self]
|
|
1070
|
+
|
|
1071
|
+
idx = 0
|
|
1072
|
+
while symbols_to_sort:
|
|
1073
|
+
sym = symbols_to_sort[idx]
|
|
1074
|
+
|
|
1075
|
+
# special 1D sets (universe domain & relaxed sets)
|
|
1076
|
+
if (
|
|
1077
|
+
isinstance(self.data[sym], abcs.ABCSet)
|
|
1078
|
+
and self.data[sym].dimension == 1
|
|
1079
|
+
and isinstance(self.data[sym].domain[0], str)
|
|
1080
|
+
):
|
|
1081
|
+
ordered_symbols.append(self.data[sym].name)
|
|
1082
|
+
symbols_to_sort.pop(symbols_to_sort.index(sym))
|
|
1083
|
+
idx = 0
|
|
1084
|
+
|
|
1085
|
+
# everything else
|
|
1086
|
+
else:
|
|
1087
|
+
doi = []
|
|
1088
|
+
for i in self.data[sym].domain:
|
|
1089
|
+
if isinstance(i, str):
|
|
1090
|
+
doi.append(True)
|
|
1091
|
+
elif (
|
|
1092
|
+
isinstance(i, abcs.AnyContainerDomainSymbol)
|
|
1093
|
+
and i.name in ordered_symbols
|
|
1094
|
+
):
|
|
1095
|
+
doi.append(True)
|
|
1096
|
+
else:
|
|
1097
|
+
doi.append(False)
|
|
1098
|
+
|
|
1099
|
+
if all(doi):
|
|
1100
|
+
ordered_symbols.append(sym)
|
|
1101
|
+
symbols_to_sort.pop(symbols_to_sort.index(sym))
|
|
1102
|
+
idx = 0
|
|
1103
|
+
else:
|
|
1104
|
+
idx += 1
|
|
1105
|
+
|
|
1106
|
+
if idx == len(symbols_to_sort) and symbols_to_sort != []:
|
|
1107
|
+
raise Exception(
|
|
1108
|
+
"Graph cycle detected among symbols:"
|
|
1109
|
+
f" {[i for i in symbols_to_sort if isinstance(self.data[i], abcs.ABCSet)]} --"
|
|
1110
|
+
" must resolve circular domain referencing"
|
|
1111
|
+
)
|
|
1112
|
+
|
|
1113
|
+
return ordered_symbols
|
|
1114
|
+
|
|
1115
|
+
def reorderSymbols(self) -> None:
|
|
1116
|
+
"""
|
|
1117
|
+
Reorder symbols in order to avoid domain violations
|
|
1118
|
+
"""
|
|
1119
|
+
self.data = CasePreservingDict(
|
|
1120
|
+
{k: self.data[k] for k in self._validSymbolOrder()}
|
|
1121
|
+
)
|
|
1122
|
+
|
|
1123
|
+
def _isValidSymbolOrder(self):
|
|
1124
|
+
valid_order = self._validSymbolOrder()
|
|
1125
|
+
current_order = [k for k, _ in self]
|
|
1126
|
+
|
|
1127
|
+
h = []
|
|
1128
|
+
for i in current_order:
|
|
1129
|
+
if isinstance(self.data[i], abcs.AnyContainerDomainSymbol):
|
|
1130
|
+
if current_order.index(i) <= valid_order.index(i):
|
|
1131
|
+
h.append(True)
|
|
1132
|
+
else:
|
|
1133
|
+
h.append(False)
|
|
1134
|
+
else:
|
|
1135
|
+
h.append(True)
|
|
1136
|
+
|
|
1137
|
+
if all(h):
|
|
1138
|
+
return True
|
|
1139
|
+
else:
|
|
1140
|
+
return False
|
|
1141
|
+
|
|
1142
|
+
def hasSymbols(self, symbols: Union[List[str], str]) -> Union[List[bool], bool]:
|
|
1143
|
+
"""
|
|
1144
|
+
Checks if specific symbol names exist in a Container
|
|
1145
|
+
|
|
1146
|
+
Parameters
|
|
1147
|
+
----------
|
|
1148
|
+
symbols : List[str] | str
|
|
1149
|
+
Symbols to check from the Container
|
|
1150
|
+
|
|
1151
|
+
Returns
|
|
1152
|
+
-------
|
|
1153
|
+
List[bool] | bool
|
|
1154
|
+
Flag to indicate whether a symbol exists or not
|
|
1155
|
+
"""
|
|
1156
|
+
if not isinstance(symbols, (str, list)):
|
|
1157
|
+
raise TypeError("Argument 'symbols' must be type str or list")
|
|
1158
|
+
|
|
1159
|
+
if isinstance(symbols, list):
|
|
1160
|
+
return [sym in self for sym in symbols]
|
|
1161
|
+
|
|
1162
|
+
if isinstance(symbols, str):
|
|
1163
|
+
return symbols in self
|
|
1164
|
+
|
|
1165
|
+
def renameSymbol(self, old_name: str, new_name: str) -> None:
|
|
1166
|
+
"""
|
|
1167
|
+
Rename a symbol in the Container
|
|
1168
|
+
|
|
1169
|
+
Parameters
|
|
1170
|
+
----------
|
|
1171
|
+
old_name : str
|
|
1172
|
+
Old name of the symbol
|
|
1173
|
+
new_name : str
|
|
1174
|
+
New name of the symbol
|
|
1175
|
+
"""
|
|
1176
|
+
if not isinstance(old_name, str):
|
|
1177
|
+
raise Exception("Argument 'old_name' must be type str")
|
|
1178
|
+
|
|
1179
|
+
if not isinstance(new_name, str):
|
|
1180
|
+
raise Exception("Argument 'new_name' must be type str")
|
|
1181
|
+
|
|
1182
|
+
if old_name.casefold() not in self:
|
|
1183
|
+
raise KeyError(f"Symbol `{old_name}` does not exist")
|
|
1184
|
+
|
|
1185
|
+
if old_name != new_name:
|
|
1186
|
+
self.data[old_name].name = new_name
|
|
1187
|
+
self._requires_state_check = True
|
|
1188
|
+
|
|
1189
|
+
def removeSymbols(self, symbols: Optional[Union[List[str], str]] = None) -> None:
|
|
1190
|
+
"""
|
|
1191
|
+
Remove symbols from the Container. If symbols=None, it will remove all symbols.
|
|
1192
|
+
|
|
1193
|
+
Parameters
|
|
1194
|
+
----------
|
|
1195
|
+
symbols : List[str] | str, optional
|
|
1196
|
+
Symbols to remove from the Container, also sets the symbols container to None. If symbols=None, will remove all symbols.
|
|
1197
|
+
"""
|
|
1198
|
+
if symbols is None:
|
|
1199
|
+
self.data = CasePreservingDict()
|
|
1200
|
+
return
|
|
1201
|
+
|
|
1202
|
+
# ARG: symbols
|
|
1203
|
+
if not isinstance(symbols, (str, list)):
|
|
1204
|
+
raise Exception("Argument 'symbols' must be type str or list")
|
|
1205
|
+
|
|
1206
|
+
if isinstance(symbols, str):
|
|
1207
|
+
symbols = [symbols]
|
|
1208
|
+
|
|
1209
|
+
if not all([isinstance(i, str) for i in symbols]):
|
|
1210
|
+
raise Exception("Argument 'symbols' must contain only type str")
|
|
1211
|
+
|
|
1212
|
+
# test if all symbols are in the Container
|
|
1213
|
+
for i in symbols:
|
|
1214
|
+
if i not in self:
|
|
1215
|
+
raise ValueError(
|
|
1216
|
+
f"User specified to remove symbol `{i}`, "
|
|
1217
|
+
"but it does not exist in the container."
|
|
1218
|
+
)
|
|
1219
|
+
|
|
1220
|
+
# find sets or aliases that are being removed
|
|
1221
|
+
set_or_alias = []
|
|
1222
|
+
[
|
|
1223
|
+
set_or_alias.append(symobj)
|
|
1224
|
+
for symobj in self.getSymbols(symbols)
|
|
1225
|
+
if isinstance(symobj, abcs.AnyContainerDomainSymbol)
|
|
1226
|
+
]
|
|
1227
|
+
|
|
1228
|
+
# remove symbols
|
|
1229
|
+
for symobj in self.getSymbols(symbols):
|
|
1230
|
+
# mark symbol container as None and reset state check flag
|
|
1231
|
+
symobj._container = None
|
|
1232
|
+
symobj._requires_state_check = True
|
|
1233
|
+
|
|
1234
|
+
# remove the symbol
|
|
1235
|
+
self.data.pop(symobj.name)
|
|
1236
|
+
|
|
1237
|
+
# remove alias symbols if parent is removed
|
|
1238
|
+
symbols = list(self)
|
|
1239
|
+
for symname, symobj in symbols:
|
|
1240
|
+
if isinstance(symobj, abcs.ABCAlias):
|
|
1241
|
+
if symobj.alias_with in set_or_alias:
|
|
1242
|
+
self.removeSymbols(symobj.name)
|
|
1243
|
+
|
|
1244
|
+
# search through all symbols and remove domain references
|
|
1245
|
+
for symname, symobj in self:
|
|
1246
|
+
# find new domain
|
|
1247
|
+
new_domain = []
|
|
1248
|
+
for n, symdom in enumerate(symobj.domain):
|
|
1249
|
+
if symdom in set_or_alias:
|
|
1250
|
+
new_domain.append("*")
|
|
1251
|
+
else:
|
|
1252
|
+
new_domain.append(symdom)
|
|
1253
|
+
|
|
1254
|
+
# set new (relaxed) domain
|
|
1255
|
+
symobj.domain = new_domain
|
|
1256
|
+
|
|
1257
|
+
# reset flags
|
|
1258
|
+
if set_or_alias:
|
|
1259
|
+
for symname, symobj in self:
|
|
1260
|
+
symobj._requires_state_check = True
|
|
1261
|
+
symobj.modified = True
|
|
1262
|
+
|
|
1263
|
+
# reset state check flag for the container
|
|
1264
|
+
self._requires_state_check = True
|
|
1265
|
+
|
|
1266
|
+
def addSet(
|
|
1267
|
+
self,
|
|
1268
|
+
name: str,
|
|
1269
|
+
domain: Optional[List[Union["Set", str]]] = None,
|
|
1270
|
+
is_singleton: bool = False,
|
|
1271
|
+
records: Optional[Any] = None,
|
|
1272
|
+
domain_forwarding: bool = False,
|
|
1273
|
+
description: str = "",
|
|
1274
|
+
uels_on_axes: bool = False,
|
|
1275
|
+
) -> "Set":
|
|
1276
|
+
"""
|
|
1277
|
+
Add a Set symbol to the Container or update an existing Set symbol.
|
|
1278
|
+
|
|
1279
|
+
Parameters
|
|
1280
|
+
----------
|
|
1281
|
+
name : str
|
|
1282
|
+
The name of the Set symbol to be added or updated.
|
|
1283
|
+
|
|
1284
|
+
domain : List[Set | str], optional
|
|
1285
|
+
An optional parameter specifying the domain (index set) of the Set symbol, by default None
|
|
1286
|
+
|
|
1287
|
+
is_singleton : bool, optional
|
|
1288
|
+
A boolean indicating whether the Set is a singleton set, by default False
|
|
1289
|
+
|
|
1290
|
+
records : Any, optional
|
|
1291
|
+
An optional parameter specifying the records (elements) of the Set symbol.
|
|
1292
|
+
|
|
1293
|
+
domain_forwarding : bool, optional
|
|
1294
|
+
A boolean indicating whether domain forwarding is enabled for the Set symbol, by default False
|
|
1295
|
+
|
|
1296
|
+
description : str, optional
|
|
1297
|
+
A description or comment for the Set symbol.
|
|
1298
|
+
|
|
1299
|
+
uels_on_axes : bool, optional
|
|
1300
|
+
A boolean indicating whether unique element lists (UELs) are used as axis values in the symbol, by default False
|
|
1301
|
+
|
|
1302
|
+
Returns
|
|
1303
|
+
-------
|
|
1304
|
+
Set
|
|
1305
|
+
The Set object that was added or updated in the Container.
|
|
1306
|
+
|
|
1307
|
+
Raises
|
|
1308
|
+
------
|
|
1309
|
+
ValueError
|
|
1310
|
+
If an attempt is made to update an existing Set symbol with conflicting properties.
|
|
1311
|
+
TypeError
|
|
1312
|
+
If 'domain' is not of type list, Set, or str.
|
|
1313
|
+
TypeError
|
|
1314
|
+
If 'is_singleton' is not of type bool.
|
|
1315
|
+
TypeError
|
|
1316
|
+
If 'domain_forwarding' is not of type bool.
|
|
1317
|
+
TypeError
|
|
1318
|
+
If 'uels_on_axes' is not of type bool.
|
|
1319
|
+
|
|
1320
|
+
Examples
|
|
1321
|
+
--------
|
|
1322
|
+
>>> import gams.transfer as gt
|
|
1323
|
+
>>> m = gt.Container()
|
|
1324
|
+
>>> i = m.addSet("i", records=['i1','i2'])
|
|
1325
|
+
>>> print(i.getUELs())
|
|
1326
|
+
['i1', 'i2']
|
|
1327
|
+
|
|
1328
|
+
"""
|
|
1329
|
+
# allows overwriting
|
|
1330
|
+
return Set(
|
|
1331
|
+
self,
|
|
1332
|
+
name,
|
|
1333
|
+
domain,
|
|
1334
|
+
is_singleton,
|
|
1335
|
+
records,
|
|
1336
|
+
domain_forwarding,
|
|
1337
|
+
description,
|
|
1338
|
+
uels_on_axes,
|
|
1339
|
+
)
|
|
1340
|
+
|
|
1341
|
+
def addParameter(
|
|
1342
|
+
self,
|
|
1343
|
+
name: str,
|
|
1344
|
+
domain: Optional[List[Union[str, "Set"]]] = None,
|
|
1345
|
+
records: Optional[Any] = None,
|
|
1346
|
+
domain_forwarding: bool = False,
|
|
1347
|
+
description: str = "",
|
|
1348
|
+
uels_on_axes: bool = False,
|
|
1349
|
+
) -> "Parameter":
|
|
1350
|
+
"""
|
|
1351
|
+
Add a Parameter symbol to the Container or update an existing Parameter symbol.
|
|
1352
|
+
|
|
1353
|
+
Parameters
|
|
1354
|
+
----------
|
|
1355
|
+
name : str
|
|
1356
|
+
The name of the Parameter symbol to be added or updated.
|
|
1357
|
+
|
|
1358
|
+
domain : List[Set | str], optional
|
|
1359
|
+
An optional parameter specifying the domain (index set) of the Parameter symbol, by default None
|
|
1360
|
+
|
|
1361
|
+
records : Any, optional
|
|
1362
|
+
An optional parameter specifying the records (elements) of the Parameter symbol.
|
|
1363
|
+
|
|
1364
|
+
domain_forwarding : bool, optional
|
|
1365
|
+
A boolean indicating whether domain forwarding is enabled for the Parameter symbol, by default False
|
|
1366
|
+
|
|
1367
|
+
description : str, optional
|
|
1368
|
+
A description or comment for the Parameter symbol.
|
|
1369
|
+
|
|
1370
|
+
uels_on_axes : bool, optional
|
|
1371
|
+
A boolean indicating whether unique element lists (UELs) are used as axis values in the symbol, by default False
|
|
1372
|
+
|
|
1373
|
+
Returns
|
|
1374
|
+
-------
|
|
1375
|
+
Parameter
|
|
1376
|
+
The Parameter symbol that was added or updated in the Container.
|
|
1377
|
+
|
|
1378
|
+
Raises
|
|
1379
|
+
------
|
|
1380
|
+
ValueError
|
|
1381
|
+
If an attempt is made to update an existing Parameter symbol with conflicting properties.
|
|
1382
|
+
TypeError
|
|
1383
|
+
If 'domain' is not of type list, Set, or str.
|
|
1384
|
+
TypeError
|
|
1385
|
+
If 'is_singleton' is not of type bool.
|
|
1386
|
+
TypeError
|
|
1387
|
+
If 'domain_forwarding' is not of type bool.
|
|
1388
|
+
TypeError
|
|
1389
|
+
If 'uels_on_axes' is not of type bool.
|
|
1390
|
+
|
|
1391
|
+
Examples
|
|
1392
|
+
--------
|
|
1393
|
+
>>> import gams.transfer as gt
|
|
1394
|
+
>>> m = gt.Container()
|
|
1395
|
+
>>> a = m.addParameter("a", records=5)
|
|
1396
|
+
>>> print(a.toValue())
|
|
1397
|
+
5.0
|
|
1398
|
+
|
|
1399
|
+
"""
|
|
1400
|
+
# allows overwriting
|
|
1401
|
+
return Parameter(
|
|
1402
|
+
self,
|
|
1403
|
+
name,
|
|
1404
|
+
domain,
|
|
1405
|
+
records,
|
|
1406
|
+
domain_forwarding,
|
|
1407
|
+
description,
|
|
1408
|
+
uels_on_axes,
|
|
1409
|
+
)
|
|
1410
|
+
|
|
1411
|
+
def addVariable(
|
|
1412
|
+
self,
|
|
1413
|
+
name: str,
|
|
1414
|
+
type: str = "free",
|
|
1415
|
+
domain: Optional[List[Union[str, "Set"]]] = None,
|
|
1416
|
+
records: Optional[Any] = None,
|
|
1417
|
+
domain_forwarding: bool = False,
|
|
1418
|
+
description: str = "",
|
|
1419
|
+
uels_on_axes: bool = False,
|
|
1420
|
+
) -> "Variable":
|
|
1421
|
+
"""
|
|
1422
|
+
Add a Variable symbol to the Container or update an existing Variable symbol.
|
|
1423
|
+
|
|
1424
|
+
Parameters
|
|
1425
|
+
----------
|
|
1426
|
+
name : str
|
|
1427
|
+
The name of the Variable symbol to be added or updated.
|
|
1428
|
+
|
|
1429
|
+
type : str, optional
|
|
1430
|
+
The type of the Variable symbol, by default "free"
|
|
1431
|
+
|
|
1432
|
+
domain : List[Set | str], optional
|
|
1433
|
+
An optional parameter specifying the domain (index set) of the Variable symbol, by default None
|
|
1434
|
+
|
|
1435
|
+
records : Any, optional
|
|
1436
|
+
An optional parameter specifying the records (elements) of the Variable symbol.
|
|
1437
|
+
|
|
1438
|
+
domain_forwarding : bool, optional
|
|
1439
|
+
A boolean indicating whether domain forwarding is enabled for the Variable symbol, by default False
|
|
1440
|
+
|
|
1441
|
+
description : str, optional
|
|
1442
|
+
A description or comment for the Variable symbol.
|
|
1443
|
+
|
|
1444
|
+
uels_on_axes : bool, optional
|
|
1445
|
+
A boolean indicating whether unique element lists (UELs) are used as axis values in the symbol, by default False
|
|
1446
|
+
|
|
1447
|
+
Returns
|
|
1448
|
+
-------
|
|
1449
|
+
Variable
|
|
1450
|
+
The Variable object that was added or updated in the Container.
|
|
1451
|
+
|
|
1452
|
+
Raises
|
|
1453
|
+
------
|
|
1454
|
+
ValueError
|
|
1455
|
+
If an attempt is made to update an existing Variable symbol with conflicting properties.
|
|
1456
|
+
TypeError
|
|
1457
|
+
If 'domain' is not of type list, Set, or str.
|
|
1458
|
+
TypeError
|
|
1459
|
+
If 'is_singleton' is not of type bool.
|
|
1460
|
+
TypeError
|
|
1461
|
+
If 'domain_forwarding' is not of type bool.
|
|
1462
|
+
TypeError
|
|
1463
|
+
If 'uels_on_axes' is not of type bool.
|
|
1464
|
+
|
|
1465
|
+
Examples
|
|
1466
|
+
--------
|
|
1467
|
+
>>> import gams.transfer as gt
|
|
1468
|
+
>>> m = gt.Container()
|
|
1469
|
+
>>> i = m.addSet("i", records=['i1','i2'])
|
|
1470
|
+
>>> v = m.addVariable("a", domain=[i])
|
|
1471
|
+
>>> print(v.domain[0] == m["i"])
|
|
1472
|
+
True
|
|
1473
|
+
|
|
1474
|
+
"""
|
|
1475
|
+
# allows overwriting
|
|
1476
|
+
return Variable(
|
|
1477
|
+
self,
|
|
1478
|
+
name,
|
|
1479
|
+
type,
|
|
1480
|
+
domain,
|
|
1481
|
+
records,
|
|
1482
|
+
domain_forwarding,
|
|
1483
|
+
description,
|
|
1484
|
+
uels_on_axes,
|
|
1485
|
+
)
|
|
1486
|
+
|
|
1487
|
+
def addEquation(
|
|
1488
|
+
self,
|
|
1489
|
+
name: str,
|
|
1490
|
+
type: str = "regular",
|
|
1491
|
+
domain: Optional[List[Union["Set", str]]] = None,
|
|
1492
|
+
records: Optional[Any] = None,
|
|
1493
|
+
domain_forwarding: bool = False,
|
|
1494
|
+
description: str = "",
|
|
1495
|
+
uels_on_axes: bool = False,
|
|
1496
|
+
) -> "Equation":
|
|
1497
|
+
"""
|
|
1498
|
+
Add an Equation symbol to the Container or update an existing Equation symbol.
|
|
1499
|
+
|
|
1500
|
+
Parameters
|
|
1501
|
+
----------
|
|
1502
|
+
name : str
|
|
1503
|
+
The name of the Equation symbol to be added or updated.
|
|
1504
|
+
|
|
1505
|
+
type : str, optional
|
|
1506
|
+
The type of the Equation symbol, by default "free"
|
|
1507
|
+
|
|
1508
|
+
domain : List[Set | str], optional
|
|
1509
|
+
An optional parameter specifying the domain (index set) of the Equation symbol, by default None
|
|
1510
|
+
|
|
1511
|
+
records : Any, optional
|
|
1512
|
+
An optional parameter specifying the records (elements) of the Equation symbol.
|
|
1513
|
+
|
|
1514
|
+
domain_forwarding : bool, optional
|
|
1515
|
+
A boolean indicating whether domain forwarding is enabled for the Equation symbol, by default False
|
|
1516
|
+
|
|
1517
|
+
description : str, optional
|
|
1518
|
+
A description or comment for the Equation symbol.
|
|
1519
|
+
|
|
1520
|
+
uels_on_axes : bool, optional
|
|
1521
|
+
A boolean indicating whether unique element lists (UELs) are used as axis values in the symbol, by default False
|
|
1522
|
+
|
|
1523
|
+
Returns
|
|
1524
|
+
-------
|
|
1525
|
+
Equation
|
|
1526
|
+
The Equation object that was added or updated in the Container.
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
"""
|
|
1530
|
+
# allows overwriting
|
|
1531
|
+
return Equation(
|
|
1532
|
+
self,
|
|
1533
|
+
name,
|
|
1534
|
+
type,
|
|
1535
|
+
domain,
|
|
1536
|
+
records,
|
|
1537
|
+
domain_forwarding,
|
|
1538
|
+
description,
|
|
1539
|
+
uels_on_axes,
|
|
1540
|
+
)
|
|
1541
|
+
|
|
1542
|
+
def addAlias(self, name: str, alias_with: "Set") -> "Alias":
|
|
1543
|
+
"""
|
|
1544
|
+
Adds an Alias to the Container.
|
|
1545
|
+
|
|
1546
|
+
Parameters
|
|
1547
|
+
----------
|
|
1548
|
+
name : str
|
|
1549
|
+
The name of the Alias symbol
|
|
1550
|
+
alias_with : Set
|
|
1551
|
+
The Set to alias
|
|
1552
|
+
|
|
1553
|
+
Returns
|
|
1554
|
+
-------
|
|
1555
|
+
Alias
|
|
1556
|
+
The Alias object that was added
|
|
1557
|
+
|
|
1558
|
+
Examples
|
|
1559
|
+
--------
|
|
1560
|
+
>>> import gams.transfer as gt
|
|
1561
|
+
>>> m = gt.Container()
|
|
1562
|
+
>>> i = m.addSet("i", records=['i1','i2'])
|
|
1563
|
+
>>> j = m.addAlias("j", i)
|
|
1564
|
+
>>> print(j.getUELs())
|
|
1565
|
+
['i1', 'i2']
|
|
1566
|
+
|
|
1567
|
+
"""
|
|
1568
|
+
# allows overwriting
|
|
1569
|
+
return Alias(self, name, alias_with)
|
|
1570
|
+
|
|
1571
|
+
def addUniverseAlias(self, name: str) -> "UniverseAlias":
|
|
1572
|
+
"""
|
|
1573
|
+
Add a Universe Alias to the Container
|
|
1574
|
+
|
|
1575
|
+
Parameters
|
|
1576
|
+
----------
|
|
1577
|
+
name : str
|
|
1578
|
+
The name of the Universe Alias symbol
|
|
1579
|
+
|
|
1580
|
+
Returns
|
|
1581
|
+
-------
|
|
1582
|
+
UniverseAlias
|
|
1583
|
+
The Universe Alias object that was added
|
|
1584
|
+
|
|
1585
|
+
Examples
|
|
1586
|
+
--------
|
|
1587
|
+
>>> import gams.transfer as gt
|
|
1588
|
+
>>> m = gt.Container()
|
|
1589
|
+
>>> i = m.addSet("i", records=['i1','i2'])
|
|
1590
|
+
>>> j = m.addSet("j", records=['j1','j2','j3'])
|
|
1591
|
+
>>> ij = m.addUniverseAlias("ij")
|
|
1592
|
+
>>> print(ij.getUELs())
|
|
1593
|
+
['i1', 'i2', 'j1', 'j2', 'j3']
|
|
1594
|
+
|
|
1595
|
+
"""
|
|
1596
|
+
# allows overwriting
|
|
1597
|
+
return UniverseAlias(self, name)
|
|
1598
|
+
|
|
1599
|
+
def _gdx_read(self, load_from, symbols, records, mode, encoding):
|
|
1600
|
+
return io.gdx.container_read(self, load_from, symbols, records, mode, encoding)
|
|
1601
|
+
|
|
1602
|
+
def _gdx_write(self, write_to, symbols, uel_priority, compress, mode, eps_to_zero):
|
|
1603
|
+
return io.gdx.container_write(
|
|
1604
|
+
self, write_to, symbols, uel_priority, compress, mode, eps_to_zero
|
|
1605
|
+
)
|
|
1606
|
+
|
|
1607
|
+
def _gmd_read(self, load_from, symbols, records, mode, encoding):
|
|
1608
|
+
return io.gmd.container_read(self, load_from, symbols, records, mode, encoding)
|
|
1609
|
+
|
|
1610
|
+
def _gmd_write(
|
|
1611
|
+
self, write_to, symbols, uel_priority, merge_symbols, mode, eps_to_zero
|
|
1612
|
+
):
|
|
1613
|
+
return io.gmd.container_write(
|
|
1614
|
+
self,
|
|
1615
|
+
write_to,
|
|
1616
|
+
symbols,
|
|
1617
|
+
uel_priority,
|
|
1618
|
+
merge_symbols,
|
|
1619
|
+
mode,
|
|
1620
|
+
eps_to_zero,
|
|
1621
|
+
)
|
|
1622
|
+
|
|
1623
|
+
def _container_read(self, load_from, symbols, records):
|
|
1624
|
+
return io.containers.read(self, load_from, symbols, records)
|
|
1625
|
+
|
|
1626
|
+
def write(
|
|
1627
|
+
self,
|
|
1628
|
+
write_to: Union["GamsDatabase", os.PathLike, str],
|
|
1629
|
+
symbols: Optional[Union[List[str], str]] = None,
|
|
1630
|
+
compress: bool = False,
|
|
1631
|
+
uel_priority: Optional[Union[List[str], str]] = None,
|
|
1632
|
+
merge_symbols: Optional[Union[List[str], str]] = None,
|
|
1633
|
+
mode: Optional[str] = None,
|
|
1634
|
+
eps_to_zero: bool = True,
|
|
1635
|
+
) -> None:
|
|
1636
|
+
"""
|
|
1637
|
+
Write data from the Container to a GDX or GMD file.
|
|
1638
|
+
|
|
1639
|
+
Parameters
|
|
1640
|
+
----------
|
|
1641
|
+
write_to : GamsDatabase | PathLike | str
|
|
1642
|
+
The destination where the data should be written.
|
|
1643
|
+
|
|
1644
|
+
symbols : List[str] | str, optional
|
|
1645
|
+
An optional parameter specifying the symbols to be written, by default None
|
|
1646
|
+
|
|
1647
|
+
compress : bool, optional
|
|
1648
|
+
A boolean indicating whether to compress the GDX file, by default False
|
|
1649
|
+
|
|
1650
|
+
uel_priority : List[str] | str, optional
|
|
1651
|
+
An optional parameter specifying the UEL (Unique Element List) priority, by default None
|
|
1652
|
+
|
|
1653
|
+
merge_symbols : List[str] | str, optional
|
|
1654
|
+
An optional parameter specifying symbols to merge when writing to a GMD object, by default None
|
|
1655
|
+
|
|
1656
|
+
mode : Optional[str], optional
|
|
1657
|
+
An optional parameter specifying the writing mode, by default None
|
|
1658
|
+
|
|
1659
|
+
Raises
|
|
1660
|
+
------
|
|
1661
|
+
TypeError
|
|
1662
|
+
If 'symbols' is not of type str, list, or NoneType.
|
|
1663
|
+
TypeError
|
|
1664
|
+
If 'compress' is not of type bool.
|
|
1665
|
+
TypeError
|
|
1666
|
+
If 'uel_priority' is not of type str, list, or NoneType.
|
|
1667
|
+
TypeError
|
|
1668
|
+
If 'merge_symbols' is not of type str, list, or NoneType.
|
|
1669
|
+
TypeError
|
|
1670
|
+
If 'mode' is not of type str or NoneType.
|
|
1671
|
+
ValueError
|
|
1672
|
+
If 'write_to' is not a valid destination (GamsDatabase, GDX file path, or GMD object).
|
|
1673
|
+
ValueError
|
|
1674
|
+
If 'mode' is not one of the valid values ("string", "category", or None).
|
|
1675
|
+
"""
|
|
1676
|
+
# check symbols argument
|
|
1677
|
+
if not isinstance(symbols, (str, list, type(None))):
|
|
1678
|
+
raise TypeError("Argument 'symbols' must be type str, list or NoneType")
|
|
1679
|
+
|
|
1680
|
+
if isinstance(symbols, str):
|
|
1681
|
+
symbols = [symbols]
|
|
1682
|
+
|
|
1683
|
+
if symbols is not None:
|
|
1684
|
+
if any(not isinstance(i, str) for i in symbols):
|
|
1685
|
+
raise TypeError("Argument 'symbols' must contain only type str")
|
|
1686
|
+
|
|
1687
|
+
# check compress argument
|
|
1688
|
+
if not isinstance(compress, bool):
|
|
1689
|
+
raise TypeError(
|
|
1690
|
+
"Argument 'compress' must be of type bool; default "
|
|
1691
|
+
"False (no compression); ignored if writing to a GMD object."
|
|
1692
|
+
)
|
|
1693
|
+
|
|
1694
|
+
# check eps_to_zero
|
|
1695
|
+
if not isinstance(eps_to_zero, bool):
|
|
1696
|
+
raise TypeError("Argument 'eps_to_zero' must be type bool")
|
|
1697
|
+
|
|
1698
|
+
# check uel_priority argument
|
|
1699
|
+
if not isinstance(uel_priority, (str, list, type(None))):
|
|
1700
|
+
raise TypeError(
|
|
1701
|
+
"Argument 'uel_priority' must be type str, list or NoneType"
|
|
1702
|
+
)
|
|
1703
|
+
|
|
1704
|
+
if isinstance(uel_priority, str):
|
|
1705
|
+
uel_priority = [uel_priority]
|
|
1706
|
+
|
|
1707
|
+
# check merge_symbols argument
|
|
1708
|
+
if not isinstance(merge_symbols, (str, list, type(None))):
|
|
1709
|
+
raise TypeError(
|
|
1710
|
+
"Argument 'merge_symbols' must be type str, list or NoneType"
|
|
1711
|
+
)
|
|
1712
|
+
|
|
1713
|
+
if isinstance(merge_symbols, str):
|
|
1714
|
+
merge_symbols = [merge_symbols]
|
|
1715
|
+
|
|
1716
|
+
if merge_symbols is None:
|
|
1717
|
+
merge_symbols = []
|
|
1718
|
+
|
|
1719
|
+
if isinstance(merge_symbols, list):
|
|
1720
|
+
if any(not isinstance(i, str) for i in merge_symbols):
|
|
1721
|
+
raise TypeError("Argument 'merge_symbols' must contain only type str")
|
|
1722
|
+
|
|
1723
|
+
# check mode argument
|
|
1724
|
+
if not isinstance(mode, (str, type(None))):
|
|
1725
|
+
raise TypeError("Argument 'mode' must be type str or NoneType")
|
|
1726
|
+
|
|
1727
|
+
if mode is None:
|
|
1728
|
+
mode = "category"
|
|
1729
|
+
else:
|
|
1730
|
+
mode = mode.casefold()
|
|
1731
|
+
if mode not in ["string", "category"]:
|
|
1732
|
+
raise ValueError(
|
|
1733
|
+
"Argument 'mode' must be `string`, `category` or `None`"
|
|
1734
|
+
)
|
|
1735
|
+
|
|
1736
|
+
#
|
|
1737
|
+
# figure out data write_to type
|
|
1738
|
+
if isinstance(write_to, GamsDatabase):
|
|
1739
|
+
dest = DestinationType.GMD
|
|
1740
|
+
write_to = write_to._gmd
|
|
1741
|
+
|
|
1742
|
+
elif isinstance(write_to, (os.PathLike, str)):
|
|
1743
|
+
fpath = pathlib.Path(write_to)
|
|
1744
|
+
|
|
1745
|
+
if not os.fspath(fpath.expanduser().resolve()).casefold().endswith(".gdx"):
|
|
1746
|
+
raise Exception(
|
|
1747
|
+
"Unexpected file type passed to 'write_to' argument "
|
|
1748
|
+
"-- expected file extension '.gdx'"
|
|
1749
|
+
)
|
|
1750
|
+
|
|
1751
|
+
dest = DestinationType.GDX
|
|
1752
|
+
write_to = os.fspath(fpath.expanduser().resolve())
|
|
1753
|
+
|
|
1754
|
+
else:
|
|
1755
|
+
# try GMD, if not, then mark as unknown
|
|
1756
|
+
try:
|
|
1757
|
+
ret = gmd.gmdInfo(write_to, gmd.GMD_NRSYMBOLSWITHALIAS)
|
|
1758
|
+
assert ret[0] == 1
|
|
1759
|
+
dest = DestinationType.GMD
|
|
1760
|
+
except:
|
|
1761
|
+
dest = DestinationType.UNKNOWN
|
|
1762
|
+
|
|
1763
|
+
# throw error if user wants to merge symbols but write_to is not a GMD object
|
|
1764
|
+
if dest is DestinationType.GDX and len(merge_symbols) != 0:
|
|
1765
|
+
raise Exception(
|
|
1766
|
+
"Symbol merge operations are only possible when writing to a"
|
|
1767
|
+
" valid GMD object."
|
|
1768
|
+
)
|
|
1769
|
+
|
|
1770
|
+
#
|
|
1771
|
+
# test and write to different destinations
|
|
1772
|
+
#
|
|
1773
|
+
if dest is DestinationType.UNKNOWN:
|
|
1774
|
+
raise TypeError(
|
|
1775
|
+
"Argument 'write_to' expects "
|
|
1776
|
+
"type str or Pathlike object (i.e., a path to a GDX file) "
|
|
1777
|
+
"or a valid gmdHandle (or GamsDatabase instance) "
|
|
1778
|
+
f"User passed: '{type(write_to)}'."
|
|
1779
|
+
)
|
|
1780
|
+
|
|
1781
|
+
if dest is DestinationType.GDX:
|
|
1782
|
+
self._gdx_write(
|
|
1783
|
+
write_to, symbols, uel_priority, compress, mode, eps_to_zero
|
|
1784
|
+
)
|
|
1785
|
+
|
|
1786
|
+
if dest is DestinationType.GMD:
|
|
1787
|
+
self._gmd_write(
|
|
1788
|
+
write_to,
|
|
1789
|
+
symbols,
|
|
1790
|
+
uel_priority,
|
|
1791
|
+
merge_symbols,
|
|
1792
|
+
mode,
|
|
1793
|
+
eps_to_zero,
|
|
1794
|
+
)
|