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
gams/control/database.py
ADDED
|
@@ -0,0 +1,2231 @@
|
|
|
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
|
+
from gams.core.gdx import *
|
|
27
|
+
from gams.core.gmd import *
|
|
28
|
+
import gams.control.workspace
|
|
29
|
+
import os
|
|
30
|
+
|
|
31
|
+
SV_UNDEF = GMS_SV_UNDEF
|
|
32
|
+
SV_EPS = 4.94066e-324 # copied from value in C#
|
|
33
|
+
|
|
34
|
+
_spec_values = doubleArray(5)
|
|
35
|
+
_spec_values[0] = SV_UNDEF
|
|
36
|
+
_spec_values[1] = float("nan")
|
|
37
|
+
_spec_values[2] = float("inf")
|
|
38
|
+
_spec_values[3] = float("-inf")
|
|
39
|
+
_spec_values[4] = SV_EPS
|
|
40
|
+
|
|
41
|
+
_default_scale = 1.0
|
|
42
|
+
_default_level = 0.0
|
|
43
|
+
_default_marginal = 0.0
|
|
44
|
+
_par_level_default = 0.0
|
|
45
|
+
|
|
46
|
+
_var_lower_default = {}
|
|
47
|
+
_var_upper_default = {}
|
|
48
|
+
|
|
49
|
+
_equ_lower_default = {}
|
|
50
|
+
_equ_upper_default = {}
|
|
51
|
+
|
|
52
|
+
_var_lower_default[GMS_VARTYPE_UNKNOWN] = 0.0
|
|
53
|
+
_var_lower_default[GMS_VARTYPE_BINARY] = 0.0
|
|
54
|
+
_var_lower_default[GMS_VARTYPE_INTEGER] = 0.0
|
|
55
|
+
_var_lower_default[GMS_VARTYPE_POSITIVE] = 0.0
|
|
56
|
+
_var_lower_default[GMS_VARTYPE_NEGATIVE] = _spec_values[GMS_SVIDX_MINF]
|
|
57
|
+
_var_lower_default[GMS_VARTYPE_FREE] = _spec_values[GMS_SVIDX_MINF]
|
|
58
|
+
_var_lower_default[GMS_VARTYPE_SOS1] = 0.0
|
|
59
|
+
_var_lower_default[GMS_VARTYPE_SOS2] = 0.0
|
|
60
|
+
_var_lower_default[GMS_VARTYPE_SEMICONT] = 1.0
|
|
61
|
+
_var_lower_default[GMS_VARTYPE_SEMIINT] = 1.0
|
|
62
|
+
|
|
63
|
+
_var_upper_default[GMS_VARTYPE_UNKNOWN] = 0.0
|
|
64
|
+
_var_upper_default[GMS_VARTYPE_BINARY] = 1.0
|
|
65
|
+
_var_upper_default[GMS_VARTYPE_INTEGER] = 100.0
|
|
66
|
+
_var_upper_default[GMS_VARTYPE_POSITIVE] = _spec_values[GMS_SVIDX_PINF]
|
|
67
|
+
_var_upper_default[GMS_VARTYPE_NEGATIVE] = 0.0
|
|
68
|
+
_var_upper_default[GMS_VARTYPE_FREE] = _spec_values[GMS_SVIDX_PINF]
|
|
69
|
+
_var_upper_default[GMS_VARTYPE_SOS1] = _spec_values[GMS_SVIDX_PINF]
|
|
70
|
+
_var_upper_default[GMS_VARTYPE_SOS2] = _spec_values[GMS_SVIDX_PINF]
|
|
71
|
+
_var_upper_default[GMS_VARTYPE_SEMICONT] = _spec_values[GMS_SVIDX_PINF]
|
|
72
|
+
_var_upper_default[GMS_VARTYPE_SEMIINT] = 100.0
|
|
73
|
+
|
|
74
|
+
_equ_lower_default[GMS_EQUTYPE_E] = 0.0
|
|
75
|
+
_equ_lower_default[GMS_EQUTYPE_G] = 0.0
|
|
76
|
+
_equ_lower_default[GMS_EQUTYPE_L] = _spec_values[GMS_SVIDX_MINF]
|
|
77
|
+
_equ_lower_default[GMS_EQUTYPE_N] = _spec_values[GMS_SVIDX_MINF]
|
|
78
|
+
_equ_lower_default[GMS_EQUTYPE_X] = 0.0
|
|
79
|
+
_equ_lower_default[GMS_EQUTYPE_C] = 0.0
|
|
80
|
+
|
|
81
|
+
_equ_upper_default[GMS_EQUTYPE_E] = 0.0
|
|
82
|
+
_equ_upper_default[GMS_EQUTYPE_G] = _spec_values[GMS_SVIDX_PINF]
|
|
83
|
+
_equ_upper_default[GMS_EQUTYPE_L] = 0.0
|
|
84
|
+
_equ_upper_default[GMS_EQUTYPE_N] = _spec_values[GMS_SVIDX_PINF]
|
|
85
|
+
_equ_upper_default[GMS_EQUTYPE_X] = 0.0
|
|
86
|
+
_equ_upper_default[GMS_EQUTYPE_C] = _spec_values[GMS_SVIDX_PINF]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _int_value_and_free(intP):
|
|
90
|
+
intp_val = intp_value(intP)
|
|
91
|
+
delete_intp(intP)
|
|
92
|
+
return intp_val
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class _GamsSymbolRecord(object):
|
|
96
|
+
"""
|
|
97
|
+
@brief This is the representation of a single record of a GamsSymbol.
|
|
98
|
+
@details Derived classes are GamsEquationRecord, GamsParameterRecord, GamsSetRecord and GamsVariableRecord
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def __eq__(self, other):
|
|
102
|
+
if isinstance(other, self.__class__):
|
|
103
|
+
return bool(
|
|
104
|
+
gmdSameRecord(
|
|
105
|
+
self._symbol._database._gmd, self._sym_iter_ptr, other._sym_iter_ptr
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
else:
|
|
109
|
+
return False
|
|
110
|
+
|
|
111
|
+
def __ne__(self, other):
|
|
112
|
+
return not self.__eq__(other)
|
|
113
|
+
|
|
114
|
+
def get_keys(self):
|
|
115
|
+
rc, keys = gmdGetKeys(
|
|
116
|
+
self._symbol._database._gmd, self._sym_iter_ptr, self._symbol._dim
|
|
117
|
+
)
|
|
118
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
119
|
+
return keys
|
|
120
|
+
|
|
121
|
+
## @brief Retrieve keys of GamsSymbolRecord
|
|
122
|
+
keys = property(get_keys)
|
|
123
|
+
|
|
124
|
+
def key(self, index):
|
|
125
|
+
"""
|
|
126
|
+
@brief Retrieve key of GamsSymbolRecord on position index
|
|
127
|
+
@param index Index position of key to be returned
|
|
128
|
+
@return Key at position index
|
|
129
|
+
"""
|
|
130
|
+
rc, key = gmdGetKey(self._symbol._database._gmd, self._sym_iter_ptr, index)
|
|
131
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
132
|
+
return key
|
|
133
|
+
|
|
134
|
+
def get_symbol(self):
|
|
135
|
+
return self._symbol
|
|
136
|
+
|
|
137
|
+
## @brief Retrieve the GamsSymbol that contains this record
|
|
138
|
+
symbol = property(get_symbol)
|
|
139
|
+
|
|
140
|
+
def __init__(self, symbol, sym_iter_ptr):
|
|
141
|
+
# get already existing record from GMD
|
|
142
|
+
symbol._database._workspace._debug_out(
|
|
143
|
+
"---- Entering _GamsSymbolRecord constructor ----", 0
|
|
144
|
+
)
|
|
145
|
+
self._symbol = symbol
|
|
146
|
+
self._sym_iter_ptr = sym_iter_ptr
|
|
147
|
+
|
|
148
|
+
def move_next(self):
|
|
149
|
+
"""
|
|
150
|
+
@brief Iterate to next GamsSymbolRecord of GamsSymbol
|
|
151
|
+
@return True if everything worked, False otherwise
|
|
152
|
+
"""
|
|
153
|
+
rc = gmdRecordMoveNext(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
154
|
+
return bool(rc)
|
|
155
|
+
|
|
156
|
+
def move_previous(self):
|
|
157
|
+
"""
|
|
158
|
+
@brief Iterate to previous GamsSymbolRecord of GamsSymbol
|
|
159
|
+
@return True if everything worked, False otherwise
|
|
160
|
+
"""
|
|
161
|
+
rc = gmdRecordMovePrev(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
162
|
+
return bool(rc)
|
|
163
|
+
|
|
164
|
+
def _keys_representation(self):
|
|
165
|
+
s = self._symbol.name
|
|
166
|
+
|
|
167
|
+
if self._symbol._dim > 0:
|
|
168
|
+
s += "("
|
|
169
|
+
|
|
170
|
+
sep = False
|
|
171
|
+
for k in self.keys:
|
|
172
|
+
if sep:
|
|
173
|
+
s += ", "
|
|
174
|
+
s += k
|
|
175
|
+
sep = True
|
|
176
|
+
|
|
177
|
+
if self._symbol._dim > 0:
|
|
178
|
+
s += ")"
|
|
179
|
+
s += ":"
|
|
180
|
+
return s
|
|
181
|
+
|
|
182
|
+
def __del__(self):
|
|
183
|
+
self._symbol._database._workspace._debug_out(
|
|
184
|
+
"---- Entering _GamsSymbolRecord destructor ----", 0
|
|
185
|
+
)
|
|
186
|
+
if self._sym_iter_ptr:
|
|
187
|
+
rc = gmdFreeSymbolIterator(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
188
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
189
|
+
self._sym_iter_ptr = None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class GamsEquationRecord(_GamsSymbolRecord):
|
|
193
|
+
"""
|
|
194
|
+
@brief This is the representation of a single record of a GamsEquation.
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
def get_level(self):
|
|
198
|
+
rc, v = gmdGetLevel(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
199
|
+
if rc:
|
|
200
|
+
return v
|
|
201
|
+
else:
|
|
202
|
+
return float("nan")
|
|
203
|
+
|
|
204
|
+
def set_level(self, value):
|
|
205
|
+
rc = gmdSetLevel(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
206
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
207
|
+
|
|
208
|
+
## @brief Get or set the level of this record
|
|
209
|
+
level = property(get_level, set_level)
|
|
210
|
+
|
|
211
|
+
def get_marginal(self):
|
|
212
|
+
rc, v = gmdGetMarginal(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
213
|
+
if rc:
|
|
214
|
+
return v
|
|
215
|
+
else:
|
|
216
|
+
return float("nan")
|
|
217
|
+
|
|
218
|
+
def set_marginal(self, value):
|
|
219
|
+
rc = gmdSetMarginal(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
220
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
221
|
+
|
|
222
|
+
## @brief Get or set the marginal of this record
|
|
223
|
+
marginal = property(get_marginal, set_marginal)
|
|
224
|
+
|
|
225
|
+
def get_upper(self):
|
|
226
|
+
rc, v = gmdGetUpper(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
227
|
+
if rc:
|
|
228
|
+
return v
|
|
229
|
+
else:
|
|
230
|
+
return float("nan")
|
|
231
|
+
|
|
232
|
+
def set_upper(self, value):
|
|
233
|
+
rc = gmdSetUpper(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
234
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
235
|
+
|
|
236
|
+
## @brief Get or set the upper bound of this record
|
|
237
|
+
upper = property(get_upper, set_upper)
|
|
238
|
+
|
|
239
|
+
def get_lower(self):
|
|
240
|
+
rc, v = gmdGetLower(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
241
|
+
if rc:
|
|
242
|
+
return v
|
|
243
|
+
else:
|
|
244
|
+
return float("nan")
|
|
245
|
+
|
|
246
|
+
def set_lower(self, value):
|
|
247
|
+
rc = gmdSetLower(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
248
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
249
|
+
|
|
250
|
+
## @brief Get or set the lower bound of this record
|
|
251
|
+
lower = property(get_lower, set_lower)
|
|
252
|
+
|
|
253
|
+
def get_scale(self):
|
|
254
|
+
rc, v = gmdGetScale(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
255
|
+
if rc:
|
|
256
|
+
return v
|
|
257
|
+
else:
|
|
258
|
+
return float("nan")
|
|
259
|
+
|
|
260
|
+
def set_scale(self, value):
|
|
261
|
+
rc = gmdSetScale(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
262
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
263
|
+
|
|
264
|
+
## @brief Get or set the scale of this record
|
|
265
|
+
scale = property(get_scale, set_scale)
|
|
266
|
+
|
|
267
|
+
def __init__(self, equation, sym_iter_ptr):
|
|
268
|
+
super(GamsEquationRecord, self).__init__(equation, sym_iter_ptr)
|
|
269
|
+
|
|
270
|
+
## @brief Retrieve a string representation of this record
|
|
271
|
+
def __str__(self):
|
|
272
|
+
s = self._keys_representation()
|
|
273
|
+
|
|
274
|
+
level = self.level
|
|
275
|
+
marginal = self.marginal
|
|
276
|
+
lower = self.lower
|
|
277
|
+
upper = self.upper
|
|
278
|
+
scale = self.scale
|
|
279
|
+
|
|
280
|
+
if level != _default_level:
|
|
281
|
+
s += " level=" + str(level)
|
|
282
|
+
if marginal != _default_marginal:
|
|
283
|
+
s += " marginal=" + str(marginal)
|
|
284
|
+
if lower != _equ_lower_default[self._symbol._equtype]:
|
|
285
|
+
s += " lower=" + str(lower)
|
|
286
|
+
if upper != _equ_upper_default[self._symbol._equtype]:
|
|
287
|
+
s += " upper=" + str(upper)
|
|
288
|
+
if scale != _default_scale:
|
|
289
|
+
s += " scale=" + str(scale)
|
|
290
|
+
|
|
291
|
+
return s
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class GamsParameterRecord(_GamsSymbolRecord):
|
|
295
|
+
"""
|
|
296
|
+
@brief This is the representation of a single record of a GamsParameter.
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
def get_value(self):
|
|
300
|
+
rc, v = gmdGetLevel(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
301
|
+
if rc:
|
|
302
|
+
return v
|
|
303
|
+
else:
|
|
304
|
+
return float("nan")
|
|
305
|
+
|
|
306
|
+
def set_value(self, value):
|
|
307
|
+
rc = gmdSetLevel(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
308
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
309
|
+
|
|
310
|
+
## @brief Get or set the value of this record
|
|
311
|
+
value = property(get_value, set_value)
|
|
312
|
+
|
|
313
|
+
def __init__(self, set, sym_iter_ptr):
|
|
314
|
+
super(GamsParameterRecord, self).__init__(set, sym_iter_ptr)
|
|
315
|
+
|
|
316
|
+
## @brief Retrieve a string representation of this record
|
|
317
|
+
def __str__(self):
|
|
318
|
+
s = self._keys_representation()
|
|
319
|
+
|
|
320
|
+
value = self.value
|
|
321
|
+
|
|
322
|
+
if value != _par_level_default:
|
|
323
|
+
s += " value=" + str(value)
|
|
324
|
+
|
|
325
|
+
return s
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
class GamsSetRecord(_GamsSymbolRecord):
|
|
329
|
+
"""
|
|
330
|
+
@brief This is the representation of a single record of a GamsSet.
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
def get_text(self):
|
|
334
|
+
text = ""
|
|
335
|
+
rc, text = gmdGetElemText(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
336
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
337
|
+
return text
|
|
338
|
+
|
|
339
|
+
def set_text(self, value):
|
|
340
|
+
rc = gmdSetElemText(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
341
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
342
|
+
|
|
343
|
+
## @brief Get or set the explanatory text of this record
|
|
344
|
+
text = property(get_text, set_text)
|
|
345
|
+
|
|
346
|
+
def __init__(self, set, sym_iter_ptr):
|
|
347
|
+
super(GamsSetRecord, self).__init__(set, sym_iter_ptr)
|
|
348
|
+
|
|
349
|
+
## @brief Retrieve a string representation of this record
|
|
350
|
+
def __str__(self):
|
|
351
|
+
s = self._keys_representation()
|
|
352
|
+
|
|
353
|
+
text = self.text
|
|
354
|
+
if text != "" and text != " ":
|
|
355
|
+
s += " " + text
|
|
356
|
+
else:
|
|
357
|
+
s += " yes"
|
|
358
|
+
|
|
359
|
+
return s
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
class GamsVariableRecord(_GamsSymbolRecord):
|
|
363
|
+
"""
|
|
364
|
+
@brief This is the representation of a single record of a GamsVariable.
|
|
365
|
+
"""
|
|
366
|
+
|
|
367
|
+
# TODO: additional get_variable call beside get_symbol call in GamsSymbolRecord?
|
|
368
|
+
|
|
369
|
+
def get_level(self):
|
|
370
|
+
rc, v = gmdGetLevel(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
371
|
+
if rc:
|
|
372
|
+
return v
|
|
373
|
+
else:
|
|
374
|
+
return float("nan")
|
|
375
|
+
|
|
376
|
+
def set_level(self, value):
|
|
377
|
+
rc = gmdSetLevel(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
378
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
379
|
+
|
|
380
|
+
## @brief Get or set the level of this record
|
|
381
|
+
level = property(get_level, set_level)
|
|
382
|
+
|
|
383
|
+
def get_marginal(self):
|
|
384
|
+
rc, v = gmdGetMarginal(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
385
|
+
if rc:
|
|
386
|
+
return v
|
|
387
|
+
else:
|
|
388
|
+
return float("nan")
|
|
389
|
+
|
|
390
|
+
def set_marginal(self, value):
|
|
391
|
+
rc = gmdSetMarginal(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
392
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
393
|
+
|
|
394
|
+
## @brief Get or set the marginal of this record
|
|
395
|
+
marginal = property(get_marginal, set_marginal)
|
|
396
|
+
|
|
397
|
+
def get_upper(self):
|
|
398
|
+
rc, v = gmdGetUpper(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
399
|
+
if rc:
|
|
400
|
+
return v
|
|
401
|
+
else:
|
|
402
|
+
return float("nan")
|
|
403
|
+
|
|
404
|
+
def set_upper(self, value):
|
|
405
|
+
rc = gmdSetUpper(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
406
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
407
|
+
|
|
408
|
+
## @brief Get or set the upper bound of this record
|
|
409
|
+
upper = property(get_upper, set_upper)
|
|
410
|
+
|
|
411
|
+
def get_lower(self):
|
|
412
|
+
rc, v = gmdGetLower(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
413
|
+
if rc:
|
|
414
|
+
return v
|
|
415
|
+
else:
|
|
416
|
+
return float("nan")
|
|
417
|
+
|
|
418
|
+
def set_lower(self, value):
|
|
419
|
+
rc = gmdSetLower(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
420
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
421
|
+
|
|
422
|
+
## @brief Get or set the lower bound of this record
|
|
423
|
+
lower = property(get_lower, set_lower)
|
|
424
|
+
|
|
425
|
+
def get_scale(self):
|
|
426
|
+
rc, v = gmdGetScale(self._symbol._database._gmd, self._sym_iter_ptr)
|
|
427
|
+
if rc:
|
|
428
|
+
return v
|
|
429
|
+
else:
|
|
430
|
+
return float("nan")
|
|
431
|
+
|
|
432
|
+
def set_scale(self, value):
|
|
433
|
+
rc = gmdSetScale(self._symbol._database._gmd, self._sym_iter_ptr, value)
|
|
434
|
+
self._symbol._database._check_for_gmd_error(rc)
|
|
435
|
+
|
|
436
|
+
## @brief Get or set the scale of this record
|
|
437
|
+
scale = property(get_scale, set_scale)
|
|
438
|
+
|
|
439
|
+
def __init__(self, variable, sym_iter_ptr):
|
|
440
|
+
super(GamsVariableRecord, self).__init__(variable, sym_iter_ptr)
|
|
441
|
+
|
|
442
|
+
## @brief Retrieve a string representation of this record
|
|
443
|
+
def __str__(self):
|
|
444
|
+
s = self._keys_representation()
|
|
445
|
+
|
|
446
|
+
level = self.level
|
|
447
|
+
marginal = self.marginal
|
|
448
|
+
lower = self.lower
|
|
449
|
+
upper = self.upper
|
|
450
|
+
scale = self.scale
|
|
451
|
+
|
|
452
|
+
if level != _default_level:
|
|
453
|
+
s += " level=" + str(level)
|
|
454
|
+
if marginal != _default_marginal:
|
|
455
|
+
s += " marginal=" + str(marginal)
|
|
456
|
+
if lower != _var_lower_default[self._symbol._vartype]:
|
|
457
|
+
s += " lower=" + str(lower)
|
|
458
|
+
if upper != _var_upper_default[self._symbol._vartype]:
|
|
459
|
+
s += " upper=" + str(upper)
|
|
460
|
+
if scale != _default_scale:
|
|
461
|
+
s += " scale=" + str(scale)
|
|
462
|
+
|
|
463
|
+
return s
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class _GamsSymbol(object):
|
|
467
|
+
"""
|
|
468
|
+
@brief This is the representation of a symbol in GAMS.
|
|
469
|
+
@details It exists in a GamsDatabase and contains GamsSymbolRecords which one can iterate through.
|
|
470
|
+
Derived classes are GamsEquation, GamsParameter, GamsSet and GamsVariable.
|
|
471
|
+
"""
|
|
472
|
+
|
|
473
|
+
def __eq__(self, other):
|
|
474
|
+
if isinstance(other, self.__class__):
|
|
475
|
+
return self._sym_ptr == other._sym_ptr
|
|
476
|
+
else:
|
|
477
|
+
return False
|
|
478
|
+
|
|
479
|
+
def __ne__(self, other):
|
|
480
|
+
return not self.__eq__(other)
|
|
481
|
+
|
|
482
|
+
def get_domains(self):
|
|
483
|
+
if self._domains == None:
|
|
484
|
+
self._domains = []
|
|
485
|
+
if self._dim == 0:
|
|
486
|
+
return self._domains
|
|
487
|
+
retDom = gmdGetDomain(self._database._gmd, self._sym_ptr, self._dim)
|
|
488
|
+
self._database._check_for_gmd_error(retDom[0])
|
|
489
|
+
domains = retDom[1]
|
|
490
|
+
for i in range(self._dim):
|
|
491
|
+
if domains[i] != None:
|
|
492
|
+
retSym = gmdSymbolInfo(self._database._gmd, domains[i], GMD_NAME)
|
|
493
|
+
self._database._check_for_gmd_error(retSym[0])
|
|
494
|
+
name = retSym[3]
|
|
495
|
+
if name == "*":
|
|
496
|
+
self._domains.append("*")
|
|
497
|
+
else:
|
|
498
|
+
self._domains.append(
|
|
499
|
+
GamsSet(self._database, sym_ptr=domains[i])
|
|
500
|
+
)
|
|
501
|
+
else:
|
|
502
|
+
self._domains.append(retDom[2][i])
|
|
503
|
+
return self._domains
|
|
504
|
+
|
|
505
|
+
## @brief Domains of Symbol, each element is either a GamsSet (real domain) or a string (relaxed domain)
|
|
506
|
+
domains = property(get_domains)
|
|
507
|
+
|
|
508
|
+
def get_domains_as_strings(self):
|
|
509
|
+
if self._domains_as_strings == None:
|
|
510
|
+
self._domains_as_strings = []
|
|
511
|
+
if self._dim == 0:
|
|
512
|
+
return self._domains_as_strings
|
|
513
|
+
ret = gmdGetDomain(self._database._gmd, self._sym_ptr, self._dim)
|
|
514
|
+
self._database._check_for_gmd_error(ret[0])
|
|
515
|
+
|
|
516
|
+
for i in range(self._dim):
|
|
517
|
+
self._domains_as_strings.append(ret[2][i])
|
|
518
|
+
return self._domains_as_strings
|
|
519
|
+
|
|
520
|
+
## @brief Domains of Symbol, each element is a string. Note: If the domains is as alias in GAMS, this call will return the name of the alias, not the name of the aliased set
|
|
521
|
+
domains_as_strings = property(get_domains_as_strings)
|
|
522
|
+
|
|
523
|
+
def get_dimension(self):
|
|
524
|
+
return self._dim
|
|
525
|
+
|
|
526
|
+
## @brief Get GamsSymbol dimension
|
|
527
|
+
dimension = property(get_dimension)
|
|
528
|
+
|
|
529
|
+
def get_text(self):
|
|
530
|
+
return self._text
|
|
531
|
+
|
|
532
|
+
## @brief Get explanatory text of GamsSymbol
|
|
533
|
+
text = property(get_text)
|
|
534
|
+
|
|
535
|
+
def get_name(self):
|
|
536
|
+
return self._name
|
|
537
|
+
|
|
538
|
+
## Get GamsSymbol name
|
|
539
|
+
name = property(get_name)
|
|
540
|
+
|
|
541
|
+
def get_database(self):
|
|
542
|
+
return self._database
|
|
543
|
+
|
|
544
|
+
## @brief Get GamsDatabase containing GamsSymbol
|
|
545
|
+
database = property(get_database)
|
|
546
|
+
|
|
547
|
+
def get_number_records(self):
|
|
548
|
+
ret = gmdSymbolInfo(self._database._gmd, self._sym_ptr, GMD_NRRECORDS)
|
|
549
|
+
self._database._check_for_gmd_error(ret[0])
|
|
550
|
+
return ret[1]
|
|
551
|
+
|
|
552
|
+
## @brief Retrieve the number of records of the GamsSymbol
|
|
553
|
+
# @note This is the same as calling len(symbol)
|
|
554
|
+
number_records = property(get_number_records)
|
|
555
|
+
|
|
556
|
+
## @brief Retrieve the number of records of the GamsSymbol
|
|
557
|
+
def __len__(self):
|
|
558
|
+
return self.get_number_records()
|
|
559
|
+
|
|
560
|
+
def __init__(
|
|
561
|
+
self,
|
|
562
|
+
database,
|
|
563
|
+
identifier=None,
|
|
564
|
+
dimension=None,
|
|
565
|
+
explanatory_text="",
|
|
566
|
+
sym_ptr=None,
|
|
567
|
+
):
|
|
568
|
+
database._workspace._debug_out("---- Entering _GamsSymbol constructor ----", 0)
|
|
569
|
+
self._sym_iter_ptr = None
|
|
570
|
+
self._database = database
|
|
571
|
+
self._domains = None
|
|
572
|
+
self._domains_as_strings = None
|
|
573
|
+
|
|
574
|
+
# receive an already existing symbol from GMD
|
|
575
|
+
if not (identifier or dimension or explanatory_text) and sym_ptr:
|
|
576
|
+
if sym_ptr == None:
|
|
577
|
+
raise gams.control.workspace.GamsException("Symbol does not exist")
|
|
578
|
+
|
|
579
|
+
self._sym_ptr = sym_ptr
|
|
580
|
+
|
|
581
|
+
rc, type = gmdSymbolType(self._database._gmd, self._sym_ptr)
|
|
582
|
+
self._database._check_for_gmd_error(rc)
|
|
583
|
+
|
|
584
|
+
rc, ival, dval, self._name = gmdSymbolInfo(
|
|
585
|
+
self._database._gmd, self._sym_ptr, GMD_NAME
|
|
586
|
+
)
|
|
587
|
+
self._database._check_for_gmd_error(rc)
|
|
588
|
+
|
|
589
|
+
rc, self._dim, dval, sval = gmdSymbolInfo(
|
|
590
|
+
self._database._gmd, self._sym_ptr, GMD_DIM
|
|
591
|
+
)
|
|
592
|
+
self._database._check_for_gmd_error(rc)
|
|
593
|
+
|
|
594
|
+
rc, ival, dval, self._text = gmdSymbolInfo(
|
|
595
|
+
self._database._gmd, self._sym_ptr, GMD_EXPLTEXT
|
|
596
|
+
)
|
|
597
|
+
self._database._check_for_gmd_error(rc)
|
|
598
|
+
|
|
599
|
+
# create a new symbol in GMD
|
|
600
|
+
elif not sym_ptr and identifier and dimension != None:
|
|
601
|
+
if dimension < 0 or dimension > GMS_MAX_INDEX_DIM:
|
|
602
|
+
raise gams.control.workspace.GamsException(
|
|
603
|
+
"Invalid dimension specified "
|
|
604
|
+
+ str(dimension)
|
|
605
|
+
+ " is not in [0,"
|
|
606
|
+
+ str(GMS_MAX_INDEX_DIM)
|
|
607
|
+
+ "]"
|
|
608
|
+
)
|
|
609
|
+
self._name = identifier
|
|
610
|
+
self._dim = dimension
|
|
611
|
+
self._text = explanatory_text
|
|
612
|
+
|
|
613
|
+
else:
|
|
614
|
+
raise gams.control.workspace.GamsException(
|
|
615
|
+
"Invalid combination of parameters"
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
def __del__(self):
|
|
619
|
+
self._database._workspace._debug_out(
|
|
620
|
+
"---- Entering _GamsSymbol destructor ----", 0
|
|
621
|
+
)
|
|
622
|
+
if self._sym_iter_ptr:
|
|
623
|
+
rc = gmdFreeSymbolIterator(self._database._gmd, self._sym_iter_ptr)
|
|
624
|
+
self._database._check_for_gmd_error(rc)
|
|
625
|
+
self._sym_iter_ptr = None
|
|
626
|
+
|
|
627
|
+
def copy_symbol(self, target):
|
|
628
|
+
"""
|
|
629
|
+
@brief Copys all records from the GamsSymbol to the target GamsSymbol (if target had records, they will be deleted)
|
|
630
|
+
@param target Target GamsSymbol
|
|
631
|
+
@returns True if everything worked, else false
|
|
632
|
+
"""
|
|
633
|
+
if target._database._record_lock:
|
|
634
|
+
raise gams.control.workspace.GamsException(
|
|
635
|
+
"Cannot add data records to record-locked database"
|
|
636
|
+
)
|
|
637
|
+
rc = gmdCopySymbol(self._database._gmd, target._sym_ptr, self._sym_ptr)
|
|
638
|
+
self._database._check_for_gmd_error(rc)
|
|
639
|
+
return True
|
|
640
|
+
|
|
641
|
+
def _check_keys(self, keys):
|
|
642
|
+
if len(keys) != self._dim:
|
|
643
|
+
raise gams.control.workspace.GamsException(
|
|
644
|
+
"Different dimensions: " + str(len(keys)) + " vs. " + str(self._dim)
|
|
645
|
+
)
|
|
646
|
+
for i in range(self._dim):
|
|
647
|
+
if keys[i] == None:
|
|
648
|
+
raise gams.control.workspace.GamsException(
|
|
649
|
+
"'Key' not allowed to be None (found at dimension "
|
|
650
|
+
+ str(i + 1)
|
|
651
|
+
+ ")"
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
def delete_record(self, keys=None):
|
|
655
|
+
"""
|
|
656
|
+
@brief Delete GamsSymbol record
|
|
657
|
+
@param keys List of keys
|
|
658
|
+
@return True if everything worked, else False
|
|
659
|
+
"""
|
|
660
|
+
if self._database._record_lock:
|
|
661
|
+
raise gams.control.workspace.GamsException(
|
|
662
|
+
"Cannot remove data records to record-locked database"
|
|
663
|
+
)
|
|
664
|
+
if not (
|
|
665
|
+
isinstance(keys, str)
|
|
666
|
+
or isinstance(keys, list)
|
|
667
|
+
or isinstance(keys, tuple)
|
|
668
|
+
or keys == None
|
|
669
|
+
):
|
|
670
|
+
raise gams.control.workspace.GamsException(
|
|
671
|
+
"Wrong type of keys argument in delete_record. Valid types are 'str', 'list', 'tuple' and their subclasses"
|
|
672
|
+
)
|
|
673
|
+
if isinstance(keys, str):
|
|
674
|
+
keys = [keys]
|
|
675
|
+
elif isinstance(keys, tuple):
|
|
676
|
+
keys = list(keys)
|
|
677
|
+
elif not keys:
|
|
678
|
+
keys = []
|
|
679
|
+
self._check_keys(keys)
|
|
680
|
+
rc = new_intp()
|
|
681
|
+
sym_iter_ptr = gmdFindRecordPy(self._database._gmd, self._sym_ptr, keys, rc)
|
|
682
|
+
if not _int_value_and_free(rc):
|
|
683
|
+
return False
|
|
684
|
+
rc = gmdDeleteRecord(self._database._gmd, sym_iter_ptr)
|
|
685
|
+
self._database._check_for_gmd_error(rc)
|
|
686
|
+
rc = gmdFreeSymbolIterator(self._database._gmd, sym_iter_ptr)
|
|
687
|
+
self._database._check_for_gmd_error(rc)
|
|
688
|
+
sym_iter_ptr = None
|
|
689
|
+
return True
|
|
690
|
+
|
|
691
|
+
def clear(self):
|
|
692
|
+
"""
|
|
693
|
+
@brief Clear symbol
|
|
694
|
+
@returns True if everything worked, else False
|
|
695
|
+
"""
|
|
696
|
+
if self._database._record_lock:
|
|
697
|
+
raise gams.control.workspace.GamsException(
|
|
698
|
+
"Cannot remove data records to record-locked database"
|
|
699
|
+
)
|
|
700
|
+
return bool(gmdClearSymbol(self._database._gmd, self._sym_ptr))
|
|
701
|
+
|
|
702
|
+
def __iter__(self):
|
|
703
|
+
self._sym_iter_ptr = None
|
|
704
|
+
return self
|
|
705
|
+
|
|
706
|
+
def _concat_keys(self, keys):
|
|
707
|
+
if not keys or len(keys) == 0:
|
|
708
|
+
return ""
|
|
709
|
+
else:
|
|
710
|
+
ret = ""
|
|
711
|
+
for i in range(len(keys) - 1):
|
|
712
|
+
ret += keys[i] + ","
|
|
713
|
+
ret += keys[len(keys) - 1]
|
|
714
|
+
return ret
|
|
715
|
+
|
|
716
|
+
def _check_and_return_record(self, sym_iter_ptr, cb_msg):
|
|
717
|
+
if sym_iter_ptr == None:
|
|
718
|
+
raise gams.control.workspace.GamsException(cb_msg())
|
|
719
|
+
if self._sym_ptr == None:
|
|
720
|
+
raise gams.control.workspace.GamsException("Invalid Pointer")
|
|
721
|
+
if isinstance(self, GamsVariable):
|
|
722
|
+
return GamsVariableRecord(self, sym_iter_ptr)
|
|
723
|
+
if isinstance(self, GamsEquation):
|
|
724
|
+
return GamsEquationRecord(self, sym_iter_ptr)
|
|
725
|
+
if isinstance(self, GamsParameter):
|
|
726
|
+
return GamsParameterRecord(self, sym_iter_ptr)
|
|
727
|
+
if isinstance(self, GamsSet):
|
|
728
|
+
return GamsSetRecord(self, sym_iter_ptr)
|
|
729
|
+
else:
|
|
730
|
+
raise gams.control.workspace.GamsException("Invalid symbol type")
|
|
731
|
+
|
|
732
|
+
def next(self):
|
|
733
|
+
|
|
734
|
+
if self._sym_iter_ptr == None:
|
|
735
|
+
rc = new_intp()
|
|
736
|
+
self._sym_iter_ptr = gmdFindFirstRecordPy(
|
|
737
|
+
self._database._gmd, self._sym_ptr, rc
|
|
738
|
+
)
|
|
739
|
+
delete_intp(rc)
|
|
740
|
+
if self._sym_iter_ptr == None:
|
|
741
|
+
raise StopIteration
|
|
742
|
+
else:
|
|
743
|
+
if not gmdRecordMoveNext(self._database._gmd, self._sym_iter_ptr):
|
|
744
|
+
raise StopIteration
|
|
745
|
+
if self._sym_iter_ptr == None:
|
|
746
|
+
raise StopIteration
|
|
747
|
+
else:
|
|
748
|
+
cb_msg = lambda: "No next record available in symbol '" + self._name + "'"
|
|
749
|
+
rc = new_intp()
|
|
750
|
+
rec = gmdCopySymbolIteratorPy(self._database._gmd, self._sym_iter_ptr, rc)
|
|
751
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
752
|
+
return self._check_and_return_record(rec, cb_msg)
|
|
753
|
+
|
|
754
|
+
def __next__(self):
|
|
755
|
+
return self.next()
|
|
756
|
+
|
|
757
|
+
def find_record(self, keys=None):
|
|
758
|
+
"""
|
|
759
|
+
@brief Find record in GamsSymbol
|
|
760
|
+
@param keys List of keys
|
|
761
|
+
@return Reference to found record
|
|
762
|
+
"""
|
|
763
|
+
if not (
|
|
764
|
+
isinstance(keys, str)
|
|
765
|
+
or isinstance(keys, list)
|
|
766
|
+
or isinstance(keys, tuple)
|
|
767
|
+
or keys == None
|
|
768
|
+
):
|
|
769
|
+
raise gams.control.workspace.GamsException(
|
|
770
|
+
"Wrong type of keys argument in find_record. Valid types are 'str', 'list', 'tuple' and their subclasses"
|
|
771
|
+
)
|
|
772
|
+
if not keys:
|
|
773
|
+
keys = []
|
|
774
|
+
if isinstance(keys, str):
|
|
775
|
+
keys = [keys]
|
|
776
|
+
elif isinstance(keys, tuple):
|
|
777
|
+
keys = list(keys)
|
|
778
|
+
self._check_keys(keys)
|
|
779
|
+
rc = new_intp()
|
|
780
|
+
sym_iter_ptr = gmdFindRecordPy(self._database._gmd, self._sym_ptr, keys, rc)
|
|
781
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
782
|
+
cb_msg = (
|
|
783
|
+
lambda: "Cannot find record '"
|
|
784
|
+
+ self._concat_keys(keys)
|
|
785
|
+
+ "' in symbol '"
|
|
786
|
+
+ self._name
|
|
787
|
+
+ "'"
|
|
788
|
+
)
|
|
789
|
+
return self._check_and_return_record(sym_iter_ptr, cb_msg)
|
|
790
|
+
|
|
791
|
+
def __getitem__(self, keys=None):
|
|
792
|
+
return self.find_record(keys)
|
|
793
|
+
|
|
794
|
+
def add_record(self, keys=None):
|
|
795
|
+
"""
|
|
796
|
+
@brief Add record to GamsSymbol
|
|
797
|
+
@param keys List of keys
|
|
798
|
+
@return Reference to added record
|
|
799
|
+
"""
|
|
800
|
+
if self._database._record_lock:
|
|
801
|
+
raise gams.control.workspace.GamsException(
|
|
802
|
+
"Cannot add data records to record-locked database"
|
|
803
|
+
)
|
|
804
|
+
if not (
|
|
805
|
+
isinstance(keys, str)
|
|
806
|
+
or isinstance(keys, list)
|
|
807
|
+
or isinstance(keys, tuple)
|
|
808
|
+
or keys == None
|
|
809
|
+
):
|
|
810
|
+
raise gams.control.workspace.GamsException(
|
|
811
|
+
"Wrong type of keys argument in add_record. Valid types are 'str', 'list', 'tuple' and their subclasses"
|
|
812
|
+
)
|
|
813
|
+
if isinstance(keys, str):
|
|
814
|
+
keys = [keys]
|
|
815
|
+
elif isinstance(keys, tuple):
|
|
816
|
+
keys = list(keys)
|
|
817
|
+
elif not keys:
|
|
818
|
+
keys = []
|
|
819
|
+
self._check_keys(keys)
|
|
820
|
+
rc = new_intp()
|
|
821
|
+
sym_iter_ptr = gmdAddRecordPy(self._database._gmd, self._sym_ptr, keys, rc)
|
|
822
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
823
|
+
cb_msg = (
|
|
824
|
+
lambda: "Record '"
|
|
825
|
+
+ self._concat_keys(keys)
|
|
826
|
+
+ "' aleady exists in symbol '"
|
|
827
|
+
+ self._name
|
|
828
|
+
+ "'"
|
|
829
|
+
)
|
|
830
|
+
return self._check_and_return_record(sym_iter_ptr, cb_msg)
|
|
831
|
+
|
|
832
|
+
def merge_record(self, keys=None):
|
|
833
|
+
"""
|
|
834
|
+
@brief Finds record in GamsSymbol if it exists, adds it if not
|
|
835
|
+
@param keys List of keys
|
|
836
|
+
@return Reference to found or added record
|
|
837
|
+
"""
|
|
838
|
+
if not (
|
|
839
|
+
isinstance(keys, str)
|
|
840
|
+
or isinstance(keys, list)
|
|
841
|
+
or isinstance(keys, tuple)
|
|
842
|
+
or keys == None
|
|
843
|
+
):
|
|
844
|
+
raise gams.control.workspace.GamsException(
|
|
845
|
+
"Wrong type of keys argument in merge_record. Valid types are 'str', 'list', 'tuple' and their subclasses"
|
|
846
|
+
)
|
|
847
|
+
if not keys:
|
|
848
|
+
keys = []
|
|
849
|
+
if isinstance(keys, str):
|
|
850
|
+
keys = [keys]
|
|
851
|
+
elif isinstance(keys, tuple):
|
|
852
|
+
keys = list(keys)
|
|
853
|
+
self._check_keys(keys)
|
|
854
|
+
rc = new_intp()
|
|
855
|
+
sym_iter_ptr = gmdFindRecordPy(self._database._gmd, self._sym_ptr, keys, rc)
|
|
856
|
+
delete_intp(rc)
|
|
857
|
+
# self._database._check_for_gmd_error(intp_value(rc))
|
|
858
|
+
if sym_iter_ptr != None:
|
|
859
|
+
cb_msg = (
|
|
860
|
+
lambda: "Cannot find record '"
|
|
861
|
+
+ self._concat_keys(keys)
|
|
862
|
+
+ "' in symbol '"
|
|
863
|
+
+ self._name
|
|
864
|
+
+ "'"
|
|
865
|
+
)
|
|
866
|
+
return self._check_and_return_record(sym_iter_ptr, cb_msg)
|
|
867
|
+
else:
|
|
868
|
+
if self._database._record_lock:
|
|
869
|
+
raise gams.control.workspace.GamsException(
|
|
870
|
+
"Cannot add data records to record-locked database"
|
|
871
|
+
)
|
|
872
|
+
rc = new_intp()
|
|
873
|
+
sym_iter_ptr = gmdAddRecordPy(self._database._gmd, self._sym_ptr, keys, rc)
|
|
874
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
875
|
+
cb_msg = (
|
|
876
|
+
lambda: "Record '"
|
|
877
|
+
+ self._concat_keys(keys)
|
|
878
|
+
+ "' could neither be found in nor added to symbol '"
|
|
879
|
+
+ self._name
|
|
880
|
+
+ "'"
|
|
881
|
+
)
|
|
882
|
+
return self._check_and_return_record(sym_iter_ptr, cb_msg)
|
|
883
|
+
|
|
884
|
+
def first_record(self, slice=None):
|
|
885
|
+
"""
|
|
886
|
+
@brief Retrieve first record in GamsSymbol
|
|
887
|
+
@param slice Define filter for elements whose record should be retrieved
|
|
888
|
+
@code{.py}
|
|
889
|
+
print("Transportation costs from Seattle")
|
|
890
|
+
record = job.out_db.get_parameter("c").first_record(["seattle", " "])
|
|
891
|
+
@endcode
|
|
892
|
+
@return Reference to record
|
|
893
|
+
"""
|
|
894
|
+
if not slice:
|
|
895
|
+
rc = new_intp()
|
|
896
|
+
sym_iter_ptr = gmdFindFirstRecordPy(self._database._gmd, self._sym_ptr, rc)
|
|
897
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
898
|
+
cb_msg = lambda: "Symbol '" + self._name + "' is empty"
|
|
899
|
+
else:
|
|
900
|
+
if not (
|
|
901
|
+
isinstance(slice, str)
|
|
902
|
+
or isinstance(slice, list)
|
|
903
|
+
or isinstance(slice, tuple)
|
|
904
|
+
or keys == None
|
|
905
|
+
):
|
|
906
|
+
raise gams.control.workspace.GamsException(
|
|
907
|
+
"Wrong type of slice argument in first_record. Valid types are 'str', 'list', 'tuple' and their subclasses"
|
|
908
|
+
)
|
|
909
|
+
if isinstance(slice, str):
|
|
910
|
+
slice = [slice]
|
|
911
|
+
elif isinstance(slice, tuple):
|
|
912
|
+
slice = list(slice)
|
|
913
|
+
if len(slice) != self._dim:
|
|
914
|
+
raise gams.control.workspace.GamsException(
|
|
915
|
+
"Different dimensions: "
|
|
916
|
+
+ str(len(slice))
|
|
917
|
+
+ " vs. "
|
|
918
|
+
+ str(self._dim)
|
|
919
|
+
)
|
|
920
|
+
rc = new_intp()
|
|
921
|
+
sym_iter_ptr = gmdFindFirstRecordSlicePy(
|
|
922
|
+
self._database._gmd, self._sym_ptr, slice, rc
|
|
923
|
+
)
|
|
924
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
925
|
+
cb_msg = (
|
|
926
|
+
lambda: "No record with slice '"
|
|
927
|
+
+ self._concat_keys(slice)
|
|
928
|
+
+ "' found in symbol '"
|
|
929
|
+
+ self._name
|
|
930
|
+
+ "'"
|
|
931
|
+
)
|
|
932
|
+
return self._check_and_return_record(sym_iter_ptr, cb_msg)
|
|
933
|
+
|
|
934
|
+
def last_record(self, slice=None):
|
|
935
|
+
if not slice:
|
|
936
|
+
rc = new_intp()
|
|
937
|
+
sym_iter_ptr = gmdFindLastRecordPy(self._database._gmd, self._sym_ptr, rc)
|
|
938
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
939
|
+
cb_msg = lambda: "Symbol '" + self._name + "' is empty"
|
|
940
|
+
else:
|
|
941
|
+
if not (
|
|
942
|
+
isinstance(slice, str)
|
|
943
|
+
or isinstance(slice, list)
|
|
944
|
+
or isinstance(slice, tuple)
|
|
945
|
+
or keys == None
|
|
946
|
+
):
|
|
947
|
+
raise gams.control.workspace.GamsException(
|
|
948
|
+
"Wrong type of slice argument in last_record. Valid types are 'str', 'list', 'tuple' and their subclasses"
|
|
949
|
+
)
|
|
950
|
+
if isinstance(slice, str):
|
|
951
|
+
slice = [slice]
|
|
952
|
+
elif isinstance(slice, tuple):
|
|
953
|
+
slice = list(slice)
|
|
954
|
+
if len(slice) != self._dim:
|
|
955
|
+
raise gams.control.workspace.GamsException(
|
|
956
|
+
"Different dimensions: "
|
|
957
|
+
+ str(len(slice))
|
|
958
|
+
+ " vs. "
|
|
959
|
+
+ str(self._dim)
|
|
960
|
+
)
|
|
961
|
+
rc = new_intp()
|
|
962
|
+
sym_iter_ptr = gmdFindLastRecordSlicePy(
|
|
963
|
+
self._database._gmd, self._sym_ptr, slice, rc
|
|
964
|
+
)
|
|
965
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
966
|
+
cb_msg = (
|
|
967
|
+
lambda: "No record with slice '"
|
|
968
|
+
+ self._concat_keys(slice)
|
|
969
|
+
+ "' found in symbol '"
|
|
970
|
+
+ self._name
|
|
971
|
+
+ "'"
|
|
972
|
+
)
|
|
973
|
+
return self._check_and_return_record(sym_iter_ptr, cb_msg)
|
|
974
|
+
|
|
975
|
+
def check_domains(self):
|
|
976
|
+
"""
|
|
977
|
+
@brief Check if all records are within the specified domain of the symbol
|
|
978
|
+
@return True: Everything is correct, False: There is a domain violation
|
|
979
|
+
"""
|
|
980
|
+
has_violation = new_intp()
|
|
981
|
+
rc = gmdCheckSymbolDV(self._database._gmd, self._sym_ptr, has_violation)
|
|
982
|
+
self._database._check_for_gmd_error(rc)
|
|
983
|
+
if _int_value_and_free(has_violation) == 1:
|
|
984
|
+
return False
|
|
985
|
+
else:
|
|
986
|
+
return True
|
|
987
|
+
|
|
988
|
+
def get_symbol_dvs(self, max_viol=0):
|
|
989
|
+
"""
|
|
990
|
+
@brief return all GamsSymbolDomainViolations
|
|
991
|
+
@param max_viol The maximum number of domain violations which should be stored (0 for no limit)
|
|
992
|
+
@return List containing GamsSymbolDomainViolation objects
|
|
993
|
+
"""
|
|
994
|
+
|
|
995
|
+
ret_list = []
|
|
996
|
+
rc = new_intp()
|
|
997
|
+
dv_handle = gmdGetFirstDVInSymbolPy(self._database._gmd, self._sym_ptr, rc)
|
|
998
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
999
|
+
has_next = False
|
|
1000
|
+
if dv_handle != None:
|
|
1001
|
+
has_next = True
|
|
1002
|
+
|
|
1003
|
+
while has_next and (len(ret_list) < max_viol or max_viol == 0):
|
|
1004
|
+
rc = new_intp()
|
|
1005
|
+
rec = gmdGetDVSymbolRecordPy(self._database._gmd, dv_handle, rc)
|
|
1006
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1007
|
+
|
|
1008
|
+
violation_idx = intArray(self._dim)
|
|
1009
|
+
rc = gmdGetDVIndicator(self._database._gmd, dv_handle, violation_idx)
|
|
1010
|
+
self._database._check_for_gmd_error(rc)
|
|
1011
|
+
|
|
1012
|
+
violation_idx_list = []
|
|
1013
|
+
for i in range(self._dim):
|
|
1014
|
+
violation_idx_list.append(bool(violation_idx[i]))
|
|
1015
|
+
|
|
1016
|
+
rc, type = gmdSymbolType(self._database._gmd, self._sym_ptr)
|
|
1017
|
+
self._database._check_for_gmd_error(rc)
|
|
1018
|
+
symbol_record = None
|
|
1019
|
+
|
|
1020
|
+
if type == dt_equ:
|
|
1021
|
+
symbol_record = GamsEquationRecord(self, rec)
|
|
1022
|
+
elif type == dt_var:
|
|
1023
|
+
symbol_record = GamsVariableRecord(self, rec)
|
|
1024
|
+
elif type == dt_par:
|
|
1025
|
+
symbol_record = GamsParameterRecord(self, rec)
|
|
1026
|
+
elif type == dt_set:
|
|
1027
|
+
symbol_record = GamsSetRecord(self, rec)
|
|
1028
|
+
|
|
1029
|
+
ret_list.append(
|
|
1030
|
+
GamsSymbolDomainViolation(violation_idx_list, symbol_record)
|
|
1031
|
+
)
|
|
1032
|
+
|
|
1033
|
+
has_next = new_intp()
|
|
1034
|
+
rc = gmdMoveNextDVInSymbol(self._database._gmd, dv_handle, has_next)
|
|
1035
|
+
self._database._check_for_gmd_error(rc)
|
|
1036
|
+
has_next = bool(_int_value_and_free(has_next))
|
|
1037
|
+
|
|
1038
|
+
rc = gmdDomainCheckDone(self._database._gmd)
|
|
1039
|
+
self._database._check_for_gmd_error(rc)
|
|
1040
|
+
rc = gmdFreeDVHandle(self._database._gmd, dv_handle)
|
|
1041
|
+
self._database._check_for_gmd_error(rc)
|
|
1042
|
+
return ret_list
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
class GamsVariable(_GamsSymbol):
|
|
1046
|
+
"""
|
|
1047
|
+
@brief This is the representation of a variable symbol in GAMS.
|
|
1048
|
+
@details It exists in a GamsDatabase and contains GamsVariableRecords which one can iterate through.
|
|
1049
|
+
"""
|
|
1050
|
+
|
|
1051
|
+
def get_vartype(self):
|
|
1052
|
+
return self._vartype
|
|
1053
|
+
|
|
1054
|
+
## @brief Retrieve subtype of variable (VarType.Binary, VarType.Integer, VarType.Positive, VarType.Negative, VarType.Free, VarType.SOS1, VarType.SOS2, VarType.SemiCont, VarType.SemiInt)
|
|
1055
|
+
vartype = property(get_vartype)
|
|
1056
|
+
|
|
1057
|
+
def __init__(
|
|
1058
|
+
self,
|
|
1059
|
+
database,
|
|
1060
|
+
identifier=None,
|
|
1061
|
+
dimension=None,
|
|
1062
|
+
vartype=None,
|
|
1063
|
+
explanatory_text="",
|
|
1064
|
+
sym_ptr=None,
|
|
1065
|
+
domains=None,
|
|
1066
|
+
):
|
|
1067
|
+
if identifier and (vartype != None) and (domains != None) and not dimension:
|
|
1068
|
+
super(GamsVariable, self).__init__(
|
|
1069
|
+
database, identifier, len(domains), explanatory_text, sym_ptr
|
|
1070
|
+
)
|
|
1071
|
+
else:
|
|
1072
|
+
super(GamsVariable, self).__init__(
|
|
1073
|
+
database, identifier, dimension, explanatory_text, sym_ptr
|
|
1074
|
+
)
|
|
1075
|
+
|
|
1076
|
+
# receive an already existing symbol from GMD
|
|
1077
|
+
if not (identifier or dimension or vartype or explanatory_text) and sym_ptr:
|
|
1078
|
+
rc, subtype, dval, sval = gmdSymbolInfo(
|
|
1079
|
+
self._database._gmd, self._sym_ptr, GMD_USERINFO
|
|
1080
|
+
)
|
|
1081
|
+
self._database._check_for_gmd_error(rc)
|
|
1082
|
+
self._vartype = subtype
|
|
1083
|
+
|
|
1084
|
+
# create new variable in GMD
|
|
1085
|
+
elif not sym_ptr and identifier and dimension != None and vartype != None:
|
|
1086
|
+
self._vartype = vartype
|
|
1087
|
+
rc = new_intp()
|
|
1088
|
+
self._sym_ptr = gmdAddSymbolPy(
|
|
1089
|
+
self._database._gmd,
|
|
1090
|
+
self._name,
|
|
1091
|
+
self._dim,
|
|
1092
|
+
dt_var,
|
|
1093
|
+
self._vartype,
|
|
1094
|
+
self._text,
|
|
1095
|
+
rc,
|
|
1096
|
+
)
|
|
1097
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1098
|
+
|
|
1099
|
+
# create new variable with domain information
|
|
1100
|
+
elif identifier and (vartype != None) and (domains != None) and not dimension:
|
|
1101
|
+
if not isinstance(domains, (list, tuple)):
|
|
1102
|
+
raise gams.control.workspace.GamsException(
|
|
1103
|
+
"Parameter domains has to be a list or a tuple"
|
|
1104
|
+
)
|
|
1105
|
+
|
|
1106
|
+
self._vartype = vartype
|
|
1107
|
+
if len(domains) == 0:
|
|
1108
|
+
rc = new_intp()
|
|
1109
|
+
self._sym_ptr = gmdAddSymbolPy(
|
|
1110
|
+
self._database._gmd,
|
|
1111
|
+
self._name,
|
|
1112
|
+
self._dim,
|
|
1113
|
+
dt_var,
|
|
1114
|
+
self._vartype,
|
|
1115
|
+
self._text,
|
|
1116
|
+
rc,
|
|
1117
|
+
)
|
|
1118
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1119
|
+
else:
|
|
1120
|
+
dom_ptr = [None] * self._dim
|
|
1121
|
+
rel_dom = [""] * self._dim
|
|
1122
|
+
|
|
1123
|
+
for i in range(self._dim):
|
|
1124
|
+
if isinstance(domains[i], GamsSet):
|
|
1125
|
+
dom_ptr[i] = domains[i]._sym_ptr
|
|
1126
|
+
elif isinstance(domains[i], str):
|
|
1127
|
+
rel_dom[i] = domains[i]
|
|
1128
|
+
else:
|
|
1129
|
+
raise gams.control.workspace.GamsException(
|
|
1130
|
+
"Domain must be GamsSet or string but saw "
|
|
1131
|
+
+ str(type(domains[i]))
|
|
1132
|
+
+ " on index "
|
|
1133
|
+
+ str(i)
|
|
1134
|
+
)
|
|
1135
|
+
rc = new_intp()
|
|
1136
|
+
self._sym_ptr = gmdAddSymbolXPy(
|
|
1137
|
+
self._database._gmd,
|
|
1138
|
+
self._name,
|
|
1139
|
+
self._dim,
|
|
1140
|
+
dt_var,
|
|
1141
|
+
self._vartype,
|
|
1142
|
+
self._text,
|
|
1143
|
+
dom_ptr,
|
|
1144
|
+
rel_dom,
|
|
1145
|
+
rc,
|
|
1146
|
+
)
|
|
1147
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1148
|
+
else:
|
|
1149
|
+
raise gams.control.workspace.GamsException(
|
|
1150
|
+
"Invalid combination of parameters"
|
|
1151
|
+
)
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
class GamsParameter(_GamsSymbol):
|
|
1155
|
+
"""
|
|
1156
|
+
@brief This is the representation of a parameter symbol in GAMS.
|
|
1157
|
+
@details It exists in a GamsDatabase and contains GamsParameterRecords which one can iterate through.
|
|
1158
|
+
"""
|
|
1159
|
+
|
|
1160
|
+
def __init__(
|
|
1161
|
+
self,
|
|
1162
|
+
database,
|
|
1163
|
+
identifier=None,
|
|
1164
|
+
dimension=None,
|
|
1165
|
+
explanatory_text="",
|
|
1166
|
+
sym_ptr=None,
|
|
1167
|
+
domains=None,
|
|
1168
|
+
):
|
|
1169
|
+
if identifier and (domains != None) and not dimension:
|
|
1170
|
+
super(GamsParameter, self).__init__(
|
|
1171
|
+
database, identifier, len(domains), explanatory_text, sym_ptr
|
|
1172
|
+
)
|
|
1173
|
+
else:
|
|
1174
|
+
super(GamsParameter, self).__init__(
|
|
1175
|
+
database, identifier, dimension, explanatory_text, sym_ptr
|
|
1176
|
+
)
|
|
1177
|
+
|
|
1178
|
+
# receive an already existing symbol from GMD - nothing to do
|
|
1179
|
+
if not (identifier or dimension or explanatory_text) and sym_ptr:
|
|
1180
|
+
pass
|
|
1181
|
+
|
|
1182
|
+
# create new parameter in GMD
|
|
1183
|
+
elif not sym_ptr and identifier and dimension != None:
|
|
1184
|
+
rc = new_intp()
|
|
1185
|
+
self._sym_ptr = gmdAddSymbolPy(
|
|
1186
|
+
self._database._gmd, self._name, self._dim, dt_par, 0, self._text, rc
|
|
1187
|
+
)
|
|
1188
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1189
|
+
if self._sym_ptr == None:
|
|
1190
|
+
raise gams.control.workspace.GamsException(
|
|
1191
|
+
"Cannot create parameter " + self._name
|
|
1192
|
+
)
|
|
1193
|
+
|
|
1194
|
+
# create new parameter with domain information
|
|
1195
|
+
elif identifier and (domains != None) and not dimension:
|
|
1196
|
+
if not isinstance(domains, (list, tuple)):
|
|
1197
|
+
raise gams.control.workspace.GamsException(
|
|
1198
|
+
"Parameter domains has to be a list or a tuple"
|
|
1199
|
+
)
|
|
1200
|
+
|
|
1201
|
+
if len(domains) == 0:
|
|
1202
|
+
rc = new_intp()
|
|
1203
|
+
self._sym_ptr = gmdAddSymbolPy(
|
|
1204
|
+
self._database._gmd,
|
|
1205
|
+
self._name,
|
|
1206
|
+
self._dim,
|
|
1207
|
+
dt_par,
|
|
1208
|
+
0,
|
|
1209
|
+
self._text,
|
|
1210
|
+
rc,
|
|
1211
|
+
)
|
|
1212
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1213
|
+
else:
|
|
1214
|
+
dom_ptr = [None] * self._dim
|
|
1215
|
+
rel_dom = [""] * self._dim
|
|
1216
|
+
|
|
1217
|
+
for i in range(self._dim):
|
|
1218
|
+
if isinstance(domains[i], GamsSet):
|
|
1219
|
+
dom_ptr[i] = domains[i]._sym_ptr
|
|
1220
|
+
elif isinstance(domains[i], str):
|
|
1221
|
+
rel_dom[i] = domains[i]
|
|
1222
|
+
else:
|
|
1223
|
+
raise gams.control.workspace.GamsException(
|
|
1224
|
+
"Domain must be GamsSet or string but saw "
|
|
1225
|
+
+ str(type(domains[i]))
|
|
1226
|
+
+ " on index "
|
|
1227
|
+
+ str(i)
|
|
1228
|
+
)
|
|
1229
|
+
rc = new_intp()
|
|
1230
|
+
self._sym_ptr = gmdAddSymbolXPy(
|
|
1231
|
+
self._database._gmd,
|
|
1232
|
+
self._name,
|
|
1233
|
+
self._dim,
|
|
1234
|
+
dt_par,
|
|
1235
|
+
0,
|
|
1236
|
+
self._text,
|
|
1237
|
+
dom_ptr,
|
|
1238
|
+
rel_dom,
|
|
1239
|
+
rc,
|
|
1240
|
+
)
|
|
1241
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1242
|
+
|
|
1243
|
+
else:
|
|
1244
|
+
raise gams.control.workspace.GamsException(
|
|
1245
|
+
"Invalid combination of parameters"
|
|
1246
|
+
)
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
class GamsSet(_GamsSymbol):
|
|
1250
|
+
"""
|
|
1251
|
+
@brief This is the representation of a set symbol in GAMS.
|
|
1252
|
+
@details It exists in a GamsDatabase and contains GamsSetRecords which one can iterate through.
|
|
1253
|
+
"""
|
|
1254
|
+
|
|
1255
|
+
def get_settype(self):
|
|
1256
|
+
return self._settype
|
|
1257
|
+
|
|
1258
|
+
## @brief Retrieve subtype of set (SetType.Multi, SetType.Singleton)
|
|
1259
|
+
settype = property(get_settype)
|
|
1260
|
+
|
|
1261
|
+
def __init__(
|
|
1262
|
+
self,
|
|
1263
|
+
database,
|
|
1264
|
+
identifier=None,
|
|
1265
|
+
dimension=None,
|
|
1266
|
+
explanatory_text="",
|
|
1267
|
+
sym_ptr=None,
|
|
1268
|
+
domains=None,
|
|
1269
|
+
settype=0,
|
|
1270
|
+
):
|
|
1271
|
+
if identifier and (domains != None) and not dimension:
|
|
1272
|
+
super(GamsSet, self).__init__(
|
|
1273
|
+
database, identifier, len(domains), explanatory_text, sym_ptr
|
|
1274
|
+
)
|
|
1275
|
+
else:
|
|
1276
|
+
super(GamsSet, self).__init__(
|
|
1277
|
+
database, identifier, dimension, explanatory_text, sym_ptr
|
|
1278
|
+
)
|
|
1279
|
+
|
|
1280
|
+
# receive an already existing symbol from GMD
|
|
1281
|
+
if not (identifier or dimension or explanatory_text) and sym_ptr:
|
|
1282
|
+
rc, subtype, dval, sval = gmdSymbolInfo(
|
|
1283
|
+
self._database._gmd, self._sym_ptr, GMD_USERINFO
|
|
1284
|
+
)
|
|
1285
|
+
self._database._check_for_gmd_error(rc)
|
|
1286
|
+
self._settype = subtype
|
|
1287
|
+
|
|
1288
|
+
# create new set in GMD
|
|
1289
|
+
elif not sym_ptr and identifier and dimension != None:
|
|
1290
|
+
self._settype = settype
|
|
1291
|
+
rc = new_intp()
|
|
1292
|
+
self._sym_ptr = gmdAddSymbolPy(
|
|
1293
|
+
self._database._gmd,
|
|
1294
|
+
self._name,
|
|
1295
|
+
self._dim,
|
|
1296
|
+
dt_set,
|
|
1297
|
+
self._settype,
|
|
1298
|
+
self._text,
|
|
1299
|
+
rc,
|
|
1300
|
+
)
|
|
1301
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1302
|
+
|
|
1303
|
+
# create new set with domain information
|
|
1304
|
+
elif identifier and (domains != None) and not dimension:
|
|
1305
|
+
if not isinstance(domains, (list, tuple)):
|
|
1306
|
+
raise gams.control.workspace.GamsException(
|
|
1307
|
+
"Parameter domains has to be a list or a tuple"
|
|
1308
|
+
)
|
|
1309
|
+
|
|
1310
|
+
self._settype = settype
|
|
1311
|
+
if len(domains) == 0:
|
|
1312
|
+
rc = new_intp()
|
|
1313
|
+
self._sym_ptr = gmdAddSymbolPy(
|
|
1314
|
+
self._database._gmd,
|
|
1315
|
+
self._name,
|
|
1316
|
+
self._dim,
|
|
1317
|
+
dt_set,
|
|
1318
|
+
self._settype,
|
|
1319
|
+
self._text,
|
|
1320
|
+
rc,
|
|
1321
|
+
)
|
|
1322
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1323
|
+
else:
|
|
1324
|
+
dom_ptr = [None] * self._dim
|
|
1325
|
+
rel_dom = [""] * self._dim
|
|
1326
|
+
|
|
1327
|
+
for i in range(self._dim):
|
|
1328
|
+
if isinstance(domains[i], GamsSet):
|
|
1329
|
+
dom_ptr[i] = domains[i]._sym_ptr
|
|
1330
|
+
elif isinstance(domains[i], str):
|
|
1331
|
+
rel_dom[i] = domains[i]
|
|
1332
|
+
else:
|
|
1333
|
+
raise gams.control.workspace.GamsException(
|
|
1334
|
+
"Domain must be GamsSet or string but saw "
|
|
1335
|
+
+ str(type(domains[i]))
|
|
1336
|
+
+ " on index "
|
|
1337
|
+
+ str(i)
|
|
1338
|
+
)
|
|
1339
|
+
rc = new_intp()
|
|
1340
|
+
self._sym_ptr = gmdAddSymbolXPy(
|
|
1341
|
+
self._database._gmd,
|
|
1342
|
+
self._name,
|
|
1343
|
+
self._dim,
|
|
1344
|
+
dt_set,
|
|
1345
|
+
self._settype,
|
|
1346
|
+
self._text,
|
|
1347
|
+
dom_ptr,
|
|
1348
|
+
rel_dom,
|
|
1349
|
+
rc,
|
|
1350
|
+
)
|
|
1351
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1352
|
+
|
|
1353
|
+
else:
|
|
1354
|
+
raise gams.control.workspace.GamsException(
|
|
1355
|
+
"Invalid combination of parameters"
|
|
1356
|
+
)
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
class GamsEquation(_GamsSymbol):
|
|
1360
|
+
"""
|
|
1361
|
+
@brief This is the representation of an equation symbol in GAMS.
|
|
1362
|
+
@details It exists in a GamsDatabase and contains GamsEquationRecords which one can iterate through.
|
|
1363
|
+
"""
|
|
1364
|
+
|
|
1365
|
+
def get_equtype(self):
|
|
1366
|
+
return self._equtype
|
|
1367
|
+
|
|
1368
|
+
## @brief Retrieve subtype of Equation (EquType.E: Equal, EquType.G: Greater, EquType.L: Less, EquType.N: No specification, EquType.X: External defined, EquType.C: Conic)
|
|
1369
|
+
equtype = property(get_equtype)
|
|
1370
|
+
|
|
1371
|
+
def __init__(
|
|
1372
|
+
self,
|
|
1373
|
+
database,
|
|
1374
|
+
identifier=None,
|
|
1375
|
+
dimension=None,
|
|
1376
|
+
equtype=None,
|
|
1377
|
+
explanatory_text="",
|
|
1378
|
+
sym_ptr=None,
|
|
1379
|
+
domains=None,
|
|
1380
|
+
):
|
|
1381
|
+
if identifier and (equtype != None) and (domains != None) and not dimension:
|
|
1382
|
+
super(GamsEquation, self).__init__(
|
|
1383
|
+
database, identifier, len(domains), explanatory_text, sym_ptr
|
|
1384
|
+
)
|
|
1385
|
+
else:
|
|
1386
|
+
super(GamsEquation, self).__init__(
|
|
1387
|
+
database, identifier, dimension, explanatory_text, sym_ptr
|
|
1388
|
+
)
|
|
1389
|
+
|
|
1390
|
+
# receive an already existing symbol from GMD
|
|
1391
|
+
if not (identifier or dimension or equtype or explanatory_text) and sym_ptr:
|
|
1392
|
+
rc, subtype, dval, sval = gmdSymbolInfo(
|
|
1393
|
+
self._database._gmd, self._sym_ptr, GMD_USERINFO
|
|
1394
|
+
)
|
|
1395
|
+
self._database._check_for_gmd_error(rc)
|
|
1396
|
+
self._equtype = subtype
|
|
1397
|
+
|
|
1398
|
+
# create new equation in GMD
|
|
1399
|
+
elif not sym_ptr and identifier and dimension != None and equtype != None:
|
|
1400
|
+
self._equtype = equtype
|
|
1401
|
+
rc = new_intp()
|
|
1402
|
+
self._sym_ptr = gmdAddSymbolPy(
|
|
1403
|
+
self._database._gmd,
|
|
1404
|
+
self._name,
|
|
1405
|
+
self._dim,
|
|
1406
|
+
dt_equ,
|
|
1407
|
+
self._equtype,
|
|
1408
|
+
self._text,
|
|
1409
|
+
rc,
|
|
1410
|
+
)
|
|
1411
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1412
|
+
|
|
1413
|
+
# create new equation with domain information
|
|
1414
|
+
elif identifier and (equtype != None) and (domains != None) and not dimension:
|
|
1415
|
+
if not isinstance(domains, (list, tuple)):
|
|
1416
|
+
raise gams.control.workspace.GamsException(
|
|
1417
|
+
"Parameter domains has to be a list or a tuple"
|
|
1418
|
+
)
|
|
1419
|
+
|
|
1420
|
+
self._equtype = equtype
|
|
1421
|
+
if len(domains) == 0:
|
|
1422
|
+
rc = new_intp()
|
|
1423
|
+
self._sym_ptr = gmdAddSymbolPy(
|
|
1424
|
+
self._database._gmd,
|
|
1425
|
+
self._name,
|
|
1426
|
+
self._dim,
|
|
1427
|
+
dt_equ,
|
|
1428
|
+
self._equtype,
|
|
1429
|
+
self._text,
|
|
1430
|
+
rc,
|
|
1431
|
+
)
|
|
1432
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1433
|
+
else:
|
|
1434
|
+
dom_ptr = [None] * self._dim
|
|
1435
|
+
rel_dom = [""] * self._dim
|
|
1436
|
+
|
|
1437
|
+
for i in range(self._dim):
|
|
1438
|
+
if isinstance(domains[i], GamsSet):
|
|
1439
|
+
dom_ptr[i] = domains[i]._sym_ptr
|
|
1440
|
+
elif isinstance(domains[i], str):
|
|
1441
|
+
rel_dom[i] = domains[i]
|
|
1442
|
+
else:
|
|
1443
|
+
raise gams.control.workspace.GamsException(
|
|
1444
|
+
"Domain must be GamsSet or string but saw "
|
|
1445
|
+
+ str(type(domains[i]))
|
|
1446
|
+
+ " on index "
|
|
1447
|
+
+ str(i)
|
|
1448
|
+
)
|
|
1449
|
+
rc = new_intp()
|
|
1450
|
+
self._sym_ptr = gmdAddSymbolXPy(
|
|
1451
|
+
self._database._gmd,
|
|
1452
|
+
self._name,
|
|
1453
|
+
self._dim,
|
|
1454
|
+
dt_equ,
|
|
1455
|
+
self._equtype,
|
|
1456
|
+
self._text,
|
|
1457
|
+
dom_ptr,
|
|
1458
|
+
rel_dom,
|
|
1459
|
+
rc,
|
|
1460
|
+
)
|
|
1461
|
+
self._database._check_for_gmd_error(_int_value_and_free(rc))
|
|
1462
|
+
|
|
1463
|
+
else:
|
|
1464
|
+
raise gams.control.workspace.GamsException(
|
|
1465
|
+
"Invalid combination of parameters"
|
|
1466
|
+
)
|
|
1467
|
+
|
|
1468
|
+
|
|
1469
|
+
class GamsDatabaseDomainViolation(object):
|
|
1470
|
+
"""
|
|
1471
|
+
@brief This class describes a domain violation of a GamsDatabase.
|
|
1472
|
+
"""
|
|
1473
|
+
|
|
1474
|
+
def __init__(self, symbol, dvs):
|
|
1475
|
+
self._symbol = symbol
|
|
1476
|
+
self._symbol_dvs = dvs
|
|
1477
|
+
|
|
1478
|
+
def _get_symbol(self):
|
|
1479
|
+
return self._symbol
|
|
1480
|
+
|
|
1481
|
+
## @brief GamsSymbol that has a domain violation
|
|
1482
|
+
symbol = property(_get_symbol)
|
|
1483
|
+
|
|
1484
|
+
def _get_symbol_dvs(self):
|
|
1485
|
+
return self._symbol_dvs
|
|
1486
|
+
|
|
1487
|
+
## @brief List of domain violations represented by objects of type GamsSymbolDomainViolation
|
|
1488
|
+
symbol_dvs = property(_get_symbol_dvs)
|
|
1489
|
+
|
|
1490
|
+
|
|
1491
|
+
class GamsSymbolDomainViolation(object):
|
|
1492
|
+
"""
|
|
1493
|
+
This class describes a domain violation of a GamsSymbol.
|
|
1494
|
+
"""
|
|
1495
|
+
|
|
1496
|
+
def __init__(self, violation_idx, symbol_record):
|
|
1497
|
+
self._violation_idx = violation_idx
|
|
1498
|
+
self._symbol_record = symbol_record
|
|
1499
|
+
|
|
1500
|
+
def _get_violation_idx(self):
|
|
1501
|
+
return self._violation_idx
|
|
1502
|
+
|
|
1503
|
+
## @brief Array indicating which positions of a record has a domain violation
|
|
1504
|
+
violation_idx = property(_get_violation_idx)
|
|
1505
|
+
|
|
1506
|
+
def _get_symbol_record(self):
|
|
1507
|
+
return self._symbol_record
|
|
1508
|
+
|
|
1509
|
+
## @brief GamsSymbolRecord that has a domain violation
|
|
1510
|
+
symbol_record = property(_get_symbol_record)
|
|
1511
|
+
|
|
1512
|
+
|
|
1513
|
+
class GamsDatabase(object):
|
|
1514
|
+
r"""
|
|
1515
|
+
@brief An instance of GamsDatabase communicates data between the Python world and the
|
|
1516
|
+
GAMS world.
|
|
1517
|
+
@details <p>A GamsDatabase consists of a collection of symbols (GamsDatabase
|
|
1518
|
+
implements \__iter__() and next() to allow iterating conveniently
|
|
1519
|
+
through the symbols in a GamsDatabase). The symbol types available for a
|
|
1520
|
+
GamsDatabase correspond to the symbol types known from the GAMS language: Set,
|
|
1521
|
+
Parameter, Variable, and Equation are represented in Python by a derived class
|
|
1522
|
+
(e.g. GamsSet, GamsParameter, etc). Besides the type, a GamsSymbol has a name
|
|
1523
|
+
(this has to match the name inside the GAMS model), a dimension (currently up to
|
|
1524
|
+
20 or GMS_MAX_INDEX_DIM) and some explanatory text.</p>
|
|
1525
|
+
<p>Variables and equations also have a subtype: e.g. VarType.Binary, VarType.Positive, etc. for
|
|
1526
|
+
variables and e.g. EquType.E, EquType.G etc. for equations</p>
|
|
1527
|
+
<p>GamsDatabases can be created empty, or initialized from existing GDX files or
|
|
1528
|
+
from another GamsDatabase (copy). Symbols can be added at any time (e.g.
|
|
1529
|
+
GamsDatabase.add_parameter), but once a symbol is part of a GamsDatabase, it
|
|
1530
|
+
cannot be removed. Only its associated data (GamsSymbolRecord) can be purged
|
|
1531
|
+
(see GamsSymbol.clear()) or individually removed (GamsSymbol.delete_record).
|
|
1532
|
+
Individual data elements are accessed record by record. A record is identified
|
|
1533
|
+
by the keys (a vector of strings). The record data varies by symbol type. For
|
|
1534
|
+
example, a parameter record has a value property, a variable has the properties
|
|
1535
|
+
level, lower, upper, marginal, and scale. Adding a record with keys that already
|
|
1536
|
+
exist results in an exception. Similar, the unsuccessful search for a record
|
|
1537
|
+
also results in an exception.</p>
|
|
1538
|
+
<p>GamsSymbol implements \__iter__() and next() to conveniently iterate through
|
|
1539
|
+
the records of a symbol. There are also sliced access methods to symbol records
|
|
1540
|
+
that allow to iterate through all records with a fixed index at some positions.
|
|
1541
|
+
GamsDatabases can be exported as GDX files for permanent storage.</p>
|
|
1542
|
+
<p>GamsJob.out_db and GamsModelInstance.sync_db provide instances of GamsDatabase
|
|
1543
|
+
to communicate results from a GAMS run or a solve. These databases should only
|
|
1544
|
+
be used in the context of the base object (GamsJob or GamsModelInstance). If a
|
|
1545
|
+
copy of such a database is required GamsWorkspace.add_database can be used to
|
|
1546
|
+
initialize a GamsDatabase from another database by specifying the optional parameter
|
|
1547
|
+
source_database (e.g. newdb = workspace.add_database(GamsJob.out_db)).</p>
|
|
1548
|
+
<p>GamsDatabases often provide the input data for a GamsJob. Such GamsDatabases are
|
|
1549
|
+
listed in the GamsJob.run method. Inside the GAMS model source the GamsDatabase
|
|
1550
|
+
is accessible through a GDX file. The GAMS model source requires a particular
|
|
1551
|
+
file name to connect to the proper GDX file (e.g. $GDXIN filename). A
|
|
1552
|
+
GamsDatabase can be created with a given name which can be then used inside the
|
|
1553
|
+
model (e.g. db = workspace.add_database(database_name="SupplyData"))
|
|
1554
|
+
and then inside the GAMS model source: $GDXIN SupplyData) or an automatically
|
|
1555
|
+
generated name can be used. This name can be passed down to the GAMS model by
|
|
1556
|
+
using the defines dictionary of a GamsOptions instance:</p>
|
|
1557
|
+
@code{.py}
|
|
1558
|
+
db = workspace.add_database()
|
|
1559
|
+
opt = workspace.add_options()
|
|
1560
|
+
opt.defines["SupplyDataFileName"] = db.name
|
|
1561
|
+
...
|
|
1562
|
+
gamsjob.run(gams_options=opt, databases=db)
|
|
1563
|
+
@endcode
|
|
1564
|
+
<p>Inside the GAMS model source the name is accessed as follows:</p>
|
|
1565
|
+
@code{.gms}
|
|
1566
|
+
$GDXIN %SupplyDataFileName%
|
|
1567
|
+
@endcode
|
|
1568
|
+
<p>One has to act with some caution when it comes to ordered sets which e.g.
|
|
1569
|
+
allow lag and lead. By not enforcing the "domain checking" for the GamsDatabase
|
|
1570
|
+
class we have aggravated the potential problems for ordered sets.
|
|
1571
|
+
For GAMS, the labels of set elements are just strings, so the order of a set is
|
|
1572
|
+
determined by the appearance of its elements. For example, if one has 'set k
|
|
1573
|
+
/ 2,3,4,1,5 /', the order of k is exactly given by this sequence. So the lag (k-1)
|
|
1574
|
+
of k=4 is 3 and the lead (k+1) of k=4 is 1.</p>
|
|
1575
|
+
<p>GAMS performs arithmetic with an extended number range. GAMS has special values
|
|
1576
|
+
for infinity (+INF, -INF), epsilon (EPS), not available (NA), and undefined (UNDEF).
|
|
1577
|
+
When GAMS evaluates expressions with these special values, the calculating engine
|
|
1578
|
+
ensures the correctness of the result (e.g. 5*eps=eps or 5+eps=5). The GAMS model
|
|
1579
|
+
CRAZY in the GAMS Model Library documents the results of the arithmetic operations
|
|
1580
|
+
with respect to special values.</p>
|
|
1581
|
+
<p>In the GAMS Python API we map the IEEE standard values for +/-infinity (float('inf')/float('-inf')) and NA (float('nan'))
|
|
1582
|
+
to the corresponding GAMS values. The
|
|
1583
|
+
special value for UNDEF gets unfiltered through the GAMS Python API. The internal
|
|
1584
|
+
double value of UNDEF is 1.0E300 (or better use the constant SV_UNDEF).</p>
|
|
1585
|
+
<p>Special attention needs to be given to the value of 0. Since GAMS is a sparse system
|
|
1586
|
+
it does not store (parameter) records with a true 0. If a record with numerical value of
|
|
1587
|
+
0 is needed, EPS(SV_EPS) can help. For example:</p>
|
|
1588
|
+
@code{.gms}
|
|
1589
|
+
set j /1*10 /; parameter b(j); b(j) = 1; b('5') = 0;
|
|
1590
|
+
scalar s,c; s = sum(j, b(j)); c = card(b); display s,c;
|
|
1591
|
+
@endcode
|
|
1592
|
+
<p>will result in</p>
|
|
1593
|
+
@code{.gms}
|
|
1594
|
+
---- 3 PARAMETER s = 9.000
|
|
1595
|
+
PARAMETER c = 9.000
|
|
1596
|
+
@endcode
|
|
1597
|
+
<p>but</p>
|
|
1598
|
+
@code{.gms}
|
|
1599
|
+
b(j) = 1; b('5') = EPS;
|
|
1600
|
+
@endcode
|
|
1601
|
+
<p>will result in</p>
|
|
1602
|
+
@code{.gms}
|
|
1603
|
+
---- 3 PARAMETER s = 9.000
|
|
1604
|
+
PARAMETER c = 10.000
|
|
1605
|
+
@endcode
|
|
1606
|
+
<p>What are the consequences for the GAMS Python API? If we read parameter b in case of b('5')=0,
|
|
1607
|
+
the GAMSDatabase will not have a record for b('5'). In case of b('5')=EPS, the GamsDatabase will
|
|
1608
|
+
have a record with value EPS. Unlike the IEEE values (e.g. float("inf")),
|
|
1609
|
+
arithmetic operations in Python will modify EPS (e.g. 5*float("inf")==float("inf")
|
|
1610
|
+
but 5*EPS!=EPS). The same rules apply for preparing input data for GAMS
|
|
1611
|
+
in a GamsDatabase. If a value of EPS is written, GAMS will see the special value EPS.
|
|
1612
|
+
All other small values (including 0) will be communicated unfiltered to GAMS. As mentioned before,
|
|
1613
|
+
zeros will not be entered as data records in GAMS. The compiler control $on/offEPS can help to
|
|
1614
|
+
automatically map zeros to EPS.</p>
|
|
1615
|
+
<p>There is one oddity concerning values smaller than 1e-250 on GAMS input. Consider the following example:</p>
|
|
1616
|
+
@code{.py}
|
|
1617
|
+
b = db.add_parameter("b",1)
|
|
1618
|
+
for i in range(1,11):
|
|
1619
|
+
b.add_record(str(i)).value = 1
|
|
1620
|
+
b.find_record("5").value = 1E-251
|
|
1621
|
+
job.run(db)
|
|
1622
|
+
@endcode
|
|
1623
|
+
@code{.gms}
|
|
1624
|
+
$load j b
|
|
1625
|
+
scalar card_b; card_b = card(b); display card_b;
|
|
1626
|
+
b(j) = 2*b(j); card_b = card(b); display card_b;
|
|
1627
|
+
@endcode
|
|
1628
|
+
<p>A record with values smaller than 1e-250 exists on input in GAMS, but as soon as the record gets
|
|
1629
|
+
updated by GAMS and is still smaller than 1e-250, the record gets removed.</p>
|
|
1630
|
+
<p>The ordering of a set in GAMS can be non-intuitive: Consider "set i /5/, j /1*5/;".
|
|
1631
|
+
Elements '5' gets internal number 1, '1' get 2, '2' gets 3 and so on. The last element
|
|
1632
|
+
of j '5' has already the internal number 1. The sequence of internal numbers in j is
|
|
1633
|
+
not ascending and hence GAMS considers set j as not sorted, i.e. one can't use the
|
|
1634
|
+
ord() function nor the lag or lead (-,--,+,++) operators. If 'j' would have been defined
|
|
1635
|
+
before 'i' in this example, the "set not ordered" problem would have been avoided.</p>
|
|
1636
|
+
<p>Please note that the GamsDatabase actually does not implement a relational model for
|
|
1637
|
+
database management. It should be seen as a data storage or data container.</p>
|
|
1638
|
+
"""
|
|
1639
|
+
|
|
1640
|
+
# properties
|
|
1641
|
+
|
|
1642
|
+
def get_nr_symbols(self):
|
|
1643
|
+
ret = gmdInfo(self._gmd, GMD_NRSYMBOLS)
|
|
1644
|
+
self._check_for_gmd_error(ret[0])
|
|
1645
|
+
return ret[1]
|
|
1646
|
+
|
|
1647
|
+
## @brief Retrieve the number of symbols in the GamsDatabase
|
|
1648
|
+
# @note This is the same as calling len(database)
|
|
1649
|
+
number_symbols = property(get_nr_symbols)
|
|
1650
|
+
|
|
1651
|
+
def get_workspace(self):
|
|
1652
|
+
return self._workspace
|
|
1653
|
+
|
|
1654
|
+
## @brief Get GamsWorkspace containing GamsDatabase
|
|
1655
|
+
workspace = property(get_workspace)
|
|
1656
|
+
|
|
1657
|
+
def get_name(self):
|
|
1658
|
+
return self._database_name
|
|
1659
|
+
|
|
1660
|
+
## @brief Get GamsDatabase name
|
|
1661
|
+
name = property(get_name)
|
|
1662
|
+
|
|
1663
|
+
def get_suppress_auto_domain_checking(self):
|
|
1664
|
+
return self._suppress_auto_domain_checking
|
|
1665
|
+
|
|
1666
|
+
def set_suppress_auto_domain_checking(self, value):
|
|
1667
|
+
self._suppress_auto_domain_checking = value
|
|
1668
|
+
|
|
1669
|
+
## @brief Controls whether domain checking is called in GamsDatabase export
|
|
1670
|
+
suppress_auto_domain_checking = property(
|
|
1671
|
+
get_suppress_auto_domain_checking, set_suppress_auto_domain_checking
|
|
1672
|
+
)
|
|
1673
|
+
|
|
1674
|
+
## @brief Retrieve the number of symbols in the GamsDatabase
|
|
1675
|
+
def __len__(self):
|
|
1676
|
+
return self.get_nr_symbols()
|
|
1677
|
+
|
|
1678
|
+
def _check_for_gmd_error(self, rc, workspace=None):
|
|
1679
|
+
if not rc:
|
|
1680
|
+
msg = gmdGetLastError(self._gmd)[1]
|
|
1681
|
+
raise gams.control.workspace.GamsException(msg, workspace)
|
|
1682
|
+
|
|
1683
|
+
def __init__(
|
|
1684
|
+
self,
|
|
1685
|
+
ws,
|
|
1686
|
+
database_name=None,
|
|
1687
|
+
gdx_file_name=None,
|
|
1688
|
+
source_database=None,
|
|
1689
|
+
in_model_name=None,
|
|
1690
|
+
force_name=False,
|
|
1691
|
+
gmd_handle=None,
|
|
1692
|
+
):
|
|
1693
|
+
|
|
1694
|
+
ws._debug_out("---- Entering GamsDatabase constructor ----", 0)
|
|
1695
|
+
self._workspace = ws
|
|
1696
|
+
self._database_name = None
|
|
1697
|
+
if gmd_handle:
|
|
1698
|
+
self._gmd = gmd_handle
|
|
1699
|
+
self._from_gmd = True
|
|
1700
|
+
else:
|
|
1701
|
+
self._gmd = new_gmdHandle_tp()
|
|
1702
|
+
self._from_gmd = False
|
|
1703
|
+
self._record_lock = False
|
|
1704
|
+
self._symbol_lock = False
|
|
1705
|
+
self._suppress_auto_domain_checking = False
|
|
1706
|
+
self._in_model_name = in_model_name
|
|
1707
|
+
|
|
1708
|
+
if not database_name:
|
|
1709
|
+
self._database_name = self._workspace._database_add()
|
|
1710
|
+
else:
|
|
1711
|
+
self._database_name = os.path.splitext(database_name)[0]
|
|
1712
|
+
if (
|
|
1713
|
+
not self._workspace._database_add(self._database_name)
|
|
1714
|
+
and not force_name
|
|
1715
|
+
):
|
|
1716
|
+
raise gams.control.workspace.GamsException(
|
|
1717
|
+
"Database with name " + self._database_name + " already exists"
|
|
1718
|
+
)
|
|
1719
|
+
if not self._from_gmd:
|
|
1720
|
+
ret = gmdCreateD(self._gmd, self._workspace._system_directory, GMS_SSSIZE)
|
|
1721
|
+
if not ret[0]:
|
|
1722
|
+
raise gams.control.workspace.GamsException(ret[1])
|
|
1723
|
+
# we need to add the gmd handle to ws in order to free it from the workspace
|
|
1724
|
+
ws._gmdHandles.append(self._gmd)
|
|
1725
|
+
# set debug mode
|
|
1726
|
+
if self._workspace._debug == gams.control.workspace.DebugLevel.Verbose:
|
|
1727
|
+
rc = gmdSetDebug(self._gmd, 10)
|
|
1728
|
+
self._check_for_gmd_error(rc)
|
|
1729
|
+
|
|
1730
|
+
# we have to register our special values first
|
|
1731
|
+
if not self._from_gmd:
|
|
1732
|
+
if self._workspace._eps != None:
|
|
1733
|
+
tmp_spec_values = doubleArray(5)
|
|
1734
|
+
tmp_spec_values[0] = _spec_values[0]
|
|
1735
|
+
tmp_spec_values[1] = _spec_values[1]
|
|
1736
|
+
tmp_spec_values[2] = _spec_values[2]
|
|
1737
|
+
tmp_spec_values[3] = _spec_values[3]
|
|
1738
|
+
tmp_spec_values[4] = self._workspace._eps
|
|
1739
|
+
rc = gmdSetSpecialValues(self._gmd, tmp_spec_values)
|
|
1740
|
+
else:
|
|
1741
|
+
rc = gmdSetSpecialValues(self._gmd, _spec_values)
|
|
1742
|
+
self._check_for_gmd_error(rc)
|
|
1743
|
+
|
|
1744
|
+
# in C# this is separated and is located in another constructor
|
|
1745
|
+
if gdx_file_name:
|
|
1746
|
+
if (
|
|
1747
|
+
str.lower(self._database_name)
|
|
1748
|
+
== str.lower(os.path.splitext(gdx_file_name)[0])
|
|
1749
|
+
and not force_name
|
|
1750
|
+
):
|
|
1751
|
+
raise gams.control.workspace.GamsException(
|
|
1752
|
+
"GAMSDatabase name and gdx file name for initialization must be different (saw "
|
|
1753
|
+
+ self._database_name
|
|
1754
|
+
+ " for both)"
|
|
1755
|
+
)
|
|
1756
|
+
|
|
1757
|
+
if os.path.isabs(gdx_file_name):
|
|
1758
|
+
rc = gmdInitFromGDX(self._gmd, gdx_file_name)
|
|
1759
|
+
self._check_for_gmd_error(rc)
|
|
1760
|
+
else:
|
|
1761
|
+
rc = gmdInitFromGDX(
|
|
1762
|
+
self._gmd,
|
|
1763
|
+
os.path.join(self._workspace._working_directory, gdx_file_name),
|
|
1764
|
+
)
|
|
1765
|
+
self._check_for_gmd_error(rc)
|
|
1766
|
+
|
|
1767
|
+
# in C# this is separated and is located in another constructor
|
|
1768
|
+
if source_database:
|
|
1769
|
+
rc = gmdInitFromDB(self._gmd, gmdHandleToPtr(source_database._gmd))
|
|
1770
|
+
self._check_for_gmd_error(rc)
|
|
1771
|
+
|
|
1772
|
+
## @brief Use this to explicitly free unmanaged resources associated with this GamsDatabase
|
|
1773
|
+
def __del__(self):
|
|
1774
|
+
self._workspace._debug_out("---- Entering GamsDatabase destructor ----", 0)
|
|
1775
|
+
if not self._from_gmd:
|
|
1776
|
+
try:
|
|
1777
|
+
if self._gmd != None:
|
|
1778
|
+
if gmdHandleToPtr(self._gmd) != None:
|
|
1779
|
+
gmdFree(self._gmd)
|
|
1780
|
+
except:
|
|
1781
|
+
pass
|
|
1782
|
+
|
|
1783
|
+
def __getitem__(self, symbol_identifier):
|
|
1784
|
+
return self.get_symbol(symbol_identifier)
|
|
1785
|
+
|
|
1786
|
+
def __iter__(self):
|
|
1787
|
+
self._position = -1
|
|
1788
|
+
return self
|
|
1789
|
+
|
|
1790
|
+
def next(self):
|
|
1791
|
+
self._position += 1
|
|
1792
|
+
rc, nr_symbols, dval, sval = gmdInfo(self._gmd, GMD_NRSYMBOLS)
|
|
1793
|
+
if not rc:
|
|
1794
|
+
raise StopIteration
|
|
1795
|
+
if self._position >= nr_symbols:
|
|
1796
|
+
raise StopIteration
|
|
1797
|
+
|
|
1798
|
+
rc = new_intp()
|
|
1799
|
+
sym_ptr = gmdGetSymbolByIndexPy(self._gmd, self._position + 1, rc)
|
|
1800
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
1801
|
+
rc, type = gmdSymbolType(self._gmd, sym_ptr)
|
|
1802
|
+
self._check_for_gmd_error(rc)
|
|
1803
|
+
|
|
1804
|
+
if type < 0:
|
|
1805
|
+
raise gams.control.workspace.GamsException("Cannot retrieve type of symbol")
|
|
1806
|
+
if dt_var == type:
|
|
1807
|
+
return GamsVariable(self, sym_ptr=sym_ptr)
|
|
1808
|
+
if dt_equ == type:
|
|
1809
|
+
return GamsEquation(self, sym_ptr=sym_ptr)
|
|
1810
|
+
if dt_par == type:
|
|
1811
|
+
return GamsParameter(self, sym_ptr=sym_ptr)
|
|
1812
|
+
if dt_set == type or dt_alias == type:
|
|
1813
|
+
return GamsSet(self, sym_ptr=sym_ptr)
|
|
1814
|
+
raise gams.control.workspace.GamsException("Unknown symbol type " + str(type))
|
|
1815
|
+
|
|
1816
|
+
def __next__(self):
|
|
1817
|
+
return self.next()
|
|
1818
|
+
|
|
1819
|
+
def get_symbol(self, symbol_identifier):
|
|
1820
|
+
"""
|
|
1821
|
+
@brief Get GamsSymbol by name
|
|
1822
|
+
@details
|
|
1823
|
+
@code{.py}
|
|
1824
|
+
symbol = database.get_symbol("a")
|
|
1825
|
+
if isinstance(symbol, GamsParameter):
|
|
1826
|
+
print("symbol is a GamsParameter")
|
|
1827
|
+
if isinstance(symbol, GamsSet):
|
|
1828
|
+
print("symbol is a GamsSet")
|
|
1829
|
+
if isinstance(symbol, GamsVariable):
|
|
1830
|
+
print("symbol is a GamsVariable")
|
|
1831
|
+
if isinstance(symbol, GamsEquation):
|
|
1832
|
+
print("symbol is a GamsEquation")
|
|
1833
|
+
@endcode
|
|
1834
|
+
@param symbol_identifier Name of the symbol to retrieve
|
|
1835
|
+
@return Instance of _GamsSymbol
|
|
1836
|
+
@see get_parameter(), get_set(). get_variable(), get_equation()
|
|
1837
|
+
"""
|
|
1838
|
+
rc = new_intp()
|
|
1839
|
+
sym_ptr = gmdFindSymbolPy(self._gmd, symbol_identifier, rc)
|
|
1840
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
1841
|
+
rc, type = gmdSymbolType(self._gmd, sym_ptr)
|
|
1842
|
+
self._check_for_gmd_error(rc)
|
|
1843
|
+
|
|
1844
|
+
# implement this as a dictionary to provide switch-like behavior like in C#
|
|
1845
|
+
if type == dt_equ:
|
|
1846
|
+
return self.get_equation(symbol_identifier)
|
|
1847
|
+
elif type == dt_var:
|
|
1848
|
+
return self.get_variable(symbol_identifier)
|
|
1849
|
+
elif type == dt_par:
|
|
1850
|
+
return self.get_parameter(symbol_identifier)
|
|
1851
|
+
elif type == dt_set:
|
|
1852
|
+
return self.get_set(symbol_identifier)
|
|
1853
|
+
elif type == dt_alias:
|
|
1854
|
+
return self.get_set(symbol_identifier)
|
|
1855
|
+
else:
|
|
1856
|
+
raise gams.control.workspace.GamsException(
|
|
1857
|
+
"Unknown symbol type " + str(type)
|
|
1858
|
+
)
|
|
1859
|
+
|
|
1860
|
+
def get_equation(self, equation_identifier):
|
|
1861
|
+
"""
|
|
1862
|
+
@brief Get GamsEquation by name
|
|
1863
|
+
@param equation_identifier Name of the equation to retrieve
|
|
1864
|
+
@return Instance of GamsEquation
|
|
1865
|
+
@see get_symbol(), get_parameter(), get_set(), get_variable()
|
|
1866
|
+
"""
|
|
1867
|
+
rc = new_intp()
|
|
1868
|
+
sym_ptr = gmdFindSymbolPy(self._gmd, equation_identifier, rc)
|
|
1869
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
1870
|
+
rc, type = gmdSymbolType(self._gmd, sym_ptr)
|
|
1871
|
+
self._check_for_gmd_error(rc)
|
|
1872
|
+
if type != dt_equ:
|
|
1873
|
+
raise gams.control.workspace.GamsException(
|
|
1874
|
+
"GamsDatabase: Symbol " + equation_identifier + " is not an equation"
|
|
1875
|
+
)
|
|
1876
|
+
return GamsEquation(self, sym_ptr=sym_ptr)
|
|
1877
|
+
|
|
1878
|
+
def get_parameter(self, parameter_identifier):
|
|
1879
|
+
"""
|
|
1880
|
+
@brief Get GamsParameter by name
|
|
1881
|
+
@param parameter_identifier Name of the parameter to retrieve
|
|
1882
|
+
@return Instance of GamsParameter
|
|
1883
|
+
@see get_symbol(), get_set(), get_variable(), get_equation()
|
|
1884
|
+
"""
|
|
1885
|
+
rc = new_intp()
|
|
1886
|
+
sym_ptr = gmdFindSymbolPy(self._gmd, parameter_identifier, rc)
|
|
1887
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
1888
|
+
rc, type = gmdSymbolType(self._gmd, sym_ptr)
|
|
1889
|
+
self._check_for_gmd_error(rc)
|
|
1890
|
+
if type != dt_par:
|
|
1891
|
+
raise gams.control.workspace.GamsException(
|
|
1892
|
+
"GamsDatabase: Symbol " + parameter_identifier + " is not a parameter"
|
|
1893
|
+
)
|
|
1894
|
+
return GamsParameter(self, sym_ptr=sym_ptr)
|
|
1895
|
+
|
|
1896
|
+
def get_variable(self, variable_identifier):
|
|
1897
|
+
"""
|
|
1898
|
+
@brief Get GamsVariable by name
|
|
1899
|
+
@param variable_identifier Name of the variable to retrieve
|
|
1900
|
+
@return Instance of GamsVariable
|
|
1901
|
+
@see get_symbol(), get_parameter(), get_set(), get_equation()
|
|
1902
|
+
"""
|
|
1903
|
+
rc = new_intp()
|
|
1904
|
+
sym_ptr = gmdFindSymbolPy(self._gmd, variable_identifier, rc)
|
|
1905
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
1906
|
+
rc, type = gmdSymbolType(self._gmd, sym_ptr)
|
|
1907
|
+
self._check_for_gmd_error(rc)
|
|
1908
|
+
if type != dt_var:
|
|
1909
|
+
raise gams.control.workspace.GamsException(
|
|
1910
|
+
"GamsDatabase: Symbol " + variable_identifier + " is not a variable"
|
|
1911
|
+
)
|
|
1912
|
+
return GamsVariable(self, sym_ptr=sym_ptr)
|
|
1913
|
+
|
|
1914
|
+
def get_set(self, set_identifier):
|
|
1915
|
+
"""
|
|
1916
|
+
@brief Get GamsSet by name
|
|
1917
|
+
@param set_identifier Name of the set to retrieve
|
|
1918
|
+
@return Instance of GamsSet
|
|
1919
|
+
@see get_symbol(), get_parameter(), get_variable(), get_equation()
|
|
1920
|
+
"""
|
|
1921
|
+
rc = new_intp()
|
|
1922
|
+
sym_ptr = gmdFindSymbolPy(self._gmd, set_identifier, rc)
|
|
1923
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
1924
|
+
rc, type = gmdSymbolType(self._gmd, sym_ptr)
|
|
1925
|
+
if type != dt_set and type != dt_alias:
|
|
1926
|
+
raise gams.control.workspace.GamsException(
|
|
1927
|
+
"GamsDatabase: Symbol " + set_identifier + " is not a set"
|
|
1928
|
+
)
|
|
1929
|
+
return GamsSet(self, sym_ptr=sym_ptr)
|
|
1930
|
+
|
|
1931
|
+
def add_equation(self, identifier, dimension, equtype, explanatory_text=""):
|
|
1932
|
+
"""
|
|
1933
|
+
@brief Add equation symbol to database
|
|
1934
|
+
@param identifier Equation name
|
|
1935
|
+
@param dimension Equation dimension
|
|
1936
|
+
@param equtype Equation subtype (EquType.E: Equal, EquType.G: Greater, EquType.L: Less, EquType.N: No specification, EquType.X: External defined, EquType.C: Conic)
|
|
1937
|
+
@param explanatory_text Explanatory text of equation
|
|
1938
|
+
@return Instance of GamsEquation
|
|
1939
|
+
@see add_parameter(), add_set(), add_variable()
|
|
1940
|
+
"""
|
|
1941
|
+
if self._symbol_lock:
|
|
1942
|
+
raise gams.control.workspace.GamsException(
|
|
1943
|
+
"Cannot add symbols to symbol-locked database"
|
|
1944
|
+
)
|
|
1945
|
+
return GamsEquation(self, identifier, dimension, equtype, explanatory_text)
|
|
1946
|
+
|
|
1947
|
+
def add_equation_dc(self, identifier, equtype, domains, explanatory_text=""):
|
|
1948
|
+
"""
|
|
1949
|
+
@brief Add equation symbol to database using domain information
|
|
1950
|
+
@param identifier Equation name
|
|
1951
|
+
@param equtype Equation subtype (EquType.E: Equal, EquType.G: Greater, EquType.L: Less, EquType.N: No specification, EquType.X: External defined, EquType.C: Conic)
|
|
1952
|
+
@param domains A list containing GamsSet objects and strings for domain information. The length of the list specifies the dimension.
|
|
1953
|
+
@param explanatory_text Explanatory text of equation
|
|
1954
|
+
@return Instance of GamsEquation
|
|
1955
|
+
@see add_parameter_dc(), add_set_dc(), add_variable_dc()
|
|
1956
|
+
"""
|
|
1957
|
+
if self._symbol_lock:
|
|
1958
|
+
raise gams.control.workspace.GamsException(
|
|
1959
|
+
"Cannot add symbols to symbol-locked database"
|
|
1960
|
+
)
|
|
1961
|
+
if domains == None:
|
|
1962
|
+
domains = []
|
|
1963
|
+
return GamsEquation(
|
|
1964
|
+
self, identifier, None, equtype, explanatory_text, domains=domains
|
|
1965
|
+
)
|
|
1966
|
+
|
|
1967
|
+
def add_variable(self, identifier, dimension, vartype, explanatory_text=""):
|
|
1968
|
+
"""
|
|
1969
|
+
@brief Add variable symbol to database
|
|
1970
|
+
@param identifier Variable name
|
|
1971
|
+
@param dimension Variable dimension
|
|
1972
|
+
@param vartype Variable subtype (VarType.Binary, VarType.Integer, VarType.Positive, VarType.Negative, VarType.Free, VarType.SOS1, VarType.SOS2, VarType.SemiCont, VarType.SemiInt)
|
|
1973
|
+
@param explanatory_text Explanatory text to variable
|
|
1974
|
+
@return Instance of GamsVariable
|
|
1975
|
+
@see add_equation(), add_parameter(), add_set()
|
|
1976
|
+
"""
|
|
1977
|
+
if self._symbol_lock:
|
|
1978
|
+
raise gams.control.workspace.GamsException(
|
|
1979
|
+
"Cannot add symbols to symbol-locked database"
|
|
1980
|
+
)
|
|
1981
|
+
return GamsVariable(self, identifier, dimension, vartype, explanatory_text)
|
|
1982
|
+
|
|
1983
|
+
def add_variable_dc(self, identifier, vartype, domains, explanatory_text=""):
|
|
1984
|
+
"""
|
|
1985
|
+
@brief Add variable symbol to database using domain information
|
|
1986
|
+
@param identifier Variable name
|
|
1987
|
+
@param vartype Variable subtype (VarType.Binary, VarType.Integer, VarType.Positive, VarType.Negative, VarType.Free, VarType.SOS1, VarType.SOS2, VarType.SemiCont, VarType.SemiInt)
|
|
1988
|
+
@param domains A list containing GamsSet objects and strings for domain information. The length of the list specifies the dimension.
|
|
1989
|
+
@param explanatory_text Explanatory text to variable
|
|
1990
|
+
@return Instance of GamsVariable
|
|
1991
|
+
@see add_equation_dc(), add_parameter_dc(), add_set_dc()
|
|
1992
|
+
"""
|
|
1993
|
+
if self._symbol_lock:
|
|
1994
|
+
raise gams.control.workspace.GamsException(
|
|
1995
|
+
"Cannot add symbols to symbol-locked database"
|
|
1996
|
+
)
|
|
1997
|
+
if domains == None:
|
|
1998
|
+
domains = []
|
|
1999
|
+
return GamsVariable(
|
|
2000
|
+
self, identifier, None, vartype, explanatory_text, domains=domains
|
|
2001
|
+
)
|
|
2002
|
+
|
|
2003
|
+
def add_set(self, identifier, dimension, explanatory_text="", settype=0):
|
|
2004
|
+
"""
|
|
2005
|
+
@brief Add set symbol to database
|
|
2006
|
+
@param identifier Set name
|
|
2007
|
+
@param dimension Set dimension
|
|
2008
|
+
@param explanatory_text Explanatory text of set
|
|
2009
|
+
@param settype Set subtype (SetType.Multi, SetType.Singleton)
|
|
2010
|
+
@return Instance of GamsSet
|
|
2011
|
+
@see add_equation(), add_parameter(), add_variable()
|
|
2012
|
+
"""
|
|
2013
|
+
if self._symbol_lock:
|
|
2014
|
+
raise gams.control.workspace.GamsException(
|
|
2015
|
+
"Cannot add symbols to symbol-locked database"
|
|
2016
|
+
)
|
|
2017
|
+
return GamsSet(self, identifier, dimension, explanatory_text, settype=settype)
|
|
2018
|
+
|
|
2019
|
+
def add_set_dc(self, identifier, domains, explanatory_text="", settype=0):
|
|
2020
|
+
"""
|
|
2021
|
+
@brief Add set symbol to database using domain information
|
|
2022
|
+
@param identifier Set name
|
|
2023
|
+
@param domains A list containing GamsSet objects and strings for domain information. The length of the list specifies the dimension.
|
|
2024
|
+
@param explanatory_text Explanatory text of set
|
|
2025
|
+
@param settype Set subtype (SetType.Multi, SetType.Singleton)
|
|
2026
|
+
@return Instance of GamsSet
|
|
2027
|
+
@see add_equation_dc(), add_parameter_dc(), add_variable_dc()
|
|
2028
|
+
"""
|
|
2029
|
+
if self._symbol_lock:
|
|
2030
|
+
raise gams.control.workspace.GamsException(
|
|
2031
|
+
"Cannot add symbols to symbol-locked database"
|
|
2032
|
+
)
|
|
2033
|
+
if domains == None or len(domains) == 0:
|
|
2034
|
+
domains = ["*"]
|
|
2035
|
+
return GamsSet(
|
|
2036
|
+
self, identifier, None, explanatory_text, domains=domains, settype=settype
|
|
2037
|
+
)
|
|
2038
|
+
|
|
2039
|
+
def add_parameter(self, identifier, dimension, explanatory_text=""):
|
|
2040
|
+
"""
|
|
2041
|
+
@brief Add parameter symbol to database
|
|
2042
|
+
@param identifier Parameter name
|
|
2043
|
+
@param dimension Parameter dimension
|
|
2044
|
+
@param explanatory_text Explanatory text of parameter
|
|
2045
|
+
@return Instance of GamsParameter
|
|
2046
|
+
@see add_equation(), add_set(), add_variable()
|
|
2047
|
+
"""
|
|
2048
|
+
if self._symbol_lock:
|
|
2049
|
+
raise gams.control.workspace.GamsException(
|
|
2050
|
+
"Cannot add symbols to symbol-locked database"
|
|
2051
|
+
)
|
|
2052
|
+
return GamsParameter(self, identifier, dimension, explanatory_text)
|
|
2053
|
+
|
|
2054
|
+
def add_parameter_dc(self, identifier, domains, explanatory_text=""):
|
|
2055
|
+
"""
|
|
2056
|
+
@brief Add parameter symbol to database using domain information
|
|
2057
|
+
@param identifier Parameter name
|
|
2058
|
+
@param domains A list containing GamsSet objects and strings for domain information. The length of the list specifies the dimension.
|
|
2059
|
+
@param explanatory_text Explanatory text of parameter
|
|
2060
|
+
@return Instance of GamsParameter
|
|
2061
|
+
@see add_equation_dc(), add_set_dc(), add_variable_dc()
|
|
2062
|
+
"""
|
|
2063
|
+
if self._symbol_lock:
|
|
2064
|
+
raise gams.control.workspace.GamsException(
|
|
2065
|
+
"Cannot add symbols to symbol-locked database"
|
|
2066
|
+
)
|
|
2067
|
+
if domains == None:
|
|
2068
|
+
domains = []
|
|
2069
|
+
return GamsParameter(self, identifier, None, explanatory_text, domains=domains)
|
|
2070
|
+
|
|
2071
|
+
def export(self, file_path=None):
|
|
2072
|
+
"""
|
|
2073
|
+
@brief Write database into a GDX file
|
|
2074
|
+
@param file_path The path used to write the GDX file.
|
|
2075
|
+
A relative path is relative to the GAMS working directory.
|
|
2076
|
+
If not present, the file is written to the working directory using the name of the database.
|
|
2077
|
+
"""
|
|
2078
|
+
if not self._suppress_auto_domain_checking:
|
|
2079
|
+
if not self.check_domains():
|
|
2080
|
+
raise gams.control.workspace.GamsException(
|
|
2081
|
+
"Domain violations in GamsDatabase " + self._database_name
|
|
2082
|
+
)
|
|
2083
|
+
|
|
2084
|
+
if not file_path:
|
|
2085
|
+
rc = gmdWriteGDX(
|
|
2086
|
+
self._gmd,
|
|
2087
|
+
os.path.join(
|
|
2088
|
+
self._workspace._working_directory, self._database_name + ".gdx"
|
|
2089
|
+
),
|
|
2090
|
+
self._suppress_auto_domain_checking,
|
|
2091
|
+
)
|
|
2092
|
+
self._check_for_gmd_error(rc)
|
|
2093
|
+
else:
|
|
2094
|
+
file_path = os.path.splitext(file_path)[0] + ".gdx"
|
|
2095
|
+
if os.path.isabs(file_path):
|
|
2096
|
+
rc = gmdWriteGDX(
|
|
2097
|
+
self._gmd, file_path, self._suppress_auto_domain_checking
|
|
2098
|
+
)
|
|
2099
|
+
else:
|
|
2100
|
+
rc = gmdWriteGDX(
|
|
2101
|
+
self._gmd,
|
|
2102
|
+
os.path.join(self._workspace._working_directory, file_path),
|
|
2103
|
+
self._suppress_auto_domain_checking,
|
|
2104
|
+
)
|
|
2105
|
+
self._check_for_gmd_error(rc)
|
|
2106
|
+
|
|
2107
|
+
def clear(self):
|
|
2108
|
+
"""
|
|
2109
|
+
@brief Clear all symbols in GamsDatabase
|
|
2110
|
+
"""
|
|
2111
|
+
for symbol in self:
|
|
2112
|
+
if not symbol.clear():
|
|
2113
|
+
raise gams.control.workspace.GamsException(
|
|
2114
|
+
"Cannot clear symbol " + symbol._name
|
|
2115
|
+
)
|
|
2116
|
+
|
|
2117
|
+
def compact(self):
|
|
2118
|
+
"""
|
|
2119
|
+
@brief This function is obsolete and has no effect anymore. It will be removed in the future
|
|
2120
|
+
"""
|
|
2121
|
+
# gmdFreeAllSymbolIterators(self._gmd)
|
|
2122
|
+
|
|
2123
|
+
def check_domains(self):
|
|
2124
|
+
"""
|
|
2125
|
+
@brief Check for all symbols if all records are within the specified domain of the symbol
|
|
2126
|
+
@return True: Everything is correct, False: There is a domain violation
|
|
2127
|
+
"""
|
|
2128
|
+
has_violation = new_intp()
|
|
2129
|
+
rc = gmdCheckDBDV(self._gmd, has_violation)
|
|
2130
|
+
self._check_for_gmd_error(rc)
|
|
2131
|
+
if _int_value_and_free(has_violation) == 1:
|
|
2132
|
+
return False
|
|
2133
|
+
else:
|
|
2134
|
+
return True
|
|
2135
|
+
|
|
2136
|
+
def get_database_dvs(self, max_viol=0, max_viol_per_symbol=0):
|
|
2137
|
+
"""
|
|
2138
|
+
@brief return all GamsDatabaseDomainViolations
|
|
2139
|
+
@param max_viol The maximum number of domain violations which should be stored (0 for no limit)
|
|
2140
|
+
@param max_viol_per_symbol The maximum number of domain violations which should be stored per Symbol (0 for no limit)
|
|
2141
|
+
@return List containing GamsDatabaseDomainViolation objects
|
|
2142
|
+
"""
|
|
2143
|
+
rc = new_intp()
|
|
2144
|
+
ret_list = []
|
|
2145
|
+
nr_viols = 0
|
|
2146
|
+
dv_handle = gmdGetFirstDBDVPy(self._gmd, rc)
|
|
2147
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
2148
|
+
|
|
2149
|
+
has_next_db = False
|
|
2150
|
+
if dv_handle != None:
|
|
2151
|
+
has_next = True
|
|
2152
|
+
has_next_db = True
|
|
2153
|
+
|
|
2154
|
+
while has_next_db and (nr_viols < max_viol or max_viol == 0):
|
|
2155
|
+
current_symbol_dvs = []
|
|
2156
|
+
rc = new_intp()
|
|
2157
|
+
current_symbol_ptr = gmdGetDVSymbolPy(self._gmd, dv_handle, rc)
|
|
2158
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
2159
|
+
|
|
2160
|
+
ret = gmdSymbolInfo(self._gmd, current_symbol_ptr, GMD_DIM)
|
|
2161
|
+
self._check_for_gmd_error(ret[0])
|
|
2162
|
+
dim = ret[1]
|
|
2163
|
+
rc, type = gmdSymbolType(self._gmd, current_symbol_ptr)
|
|
2164
|
+
self._check_for_gmd_error(rc)
|
|
2165
|
+
current_symbol = None
|
|
2166
|
+
if type == dt_equ:
|
|
2167
|
+
current_symbol = GamsEquation(self, sym_ptr=current_symbol_ptr)
|
|
2168
|
+
elif type == dt_var:
|
|
2169
|
+
current_symbol = GamsVariable(self, sym_ptr=current_symbol_ptr)
|
|
2170
|
+
elif type == dt_par:
|
|
2171
|
+
current_symbol = GamsParameter(self, sym_ptr=current_symbol_ptr)
|
|
2172
|
+
elif type == dt_set:
|
|
2173
|
+
current_symbol = GamsSet(self, sym_ptr=current_symbol_ptr)
|
|
2174
|
+
|
|
2175
|
+
while (
|
|
2176
|
+
has_next
|
|
2177
|
+
and (
|
|
2178
|
+
len(current_symbol_dvs) < max_viol_per_symbol
|
|
2179
|
+
or max_viol_per_symbol == 0
|
|
2180
|
+
)
|
|
2181
|
+
and (nr_viols < max_viol or max_viol == 0)
|
|
2182
|
+
):
|
|
2183
|
+
rc = new_intp()
|
|
2184
|
+
rec = gmdGetDVSymbolRecordPy(self._gmd, dv_handle, rc)
|
|
2185
|
+
self._check_for_gmd_error(_int_value_and_free(rc))
|
|
2186
|
+
|
|
2187
|
+
violation_idx = intArray(dim)
|
|
2188
|
+
rc = gmdGetDVIndicator(self._gmd, dv_handle, violation_idx)
|
|
2189
|
+
self._check_for_gmd_error(rc)
|
|
2190
|
+
|
|
2191
|
+
violation_idx_list = []
|
|
2192
|
+
for i in range(dim):
|
|
2193
|
+
violation_idx_list.append(bool(violation_idx[i]))
|
|
2194
|
+
|
|
2195
|
+
rc, type = gmdSymbolType(self._gmd, current_symbol_ptr)
|
|
2196
|
+
self._check_for_gmd_error(rc)
|
|
2197
|
+
symbol_record = None
|
|
2198
|
+
if type == dt_equ:
|
|
2199
|
+
symbol_record = GamsEquationRecord(current_symbol, rec)
|
|
2200
|
+
elif type == dt_var:
|
|
2201
|
+
symbol_record = GamsVariableRecord(current_symbol, rec)
|
|
2202
|
+
elif type == dt_par:
|
|
2203
|
+
symbol_record = GamsParameterRecord(current_symbol, rec)
|
|
2204
|
+
elif type == dt_set:
|
|
2205
|
+
symbol_record = GamsSetRecord(current_symbol, rec)
|
|
2206
|
+
|
|
2207
|
+
current_symbol_dvs.append(
|
|
2208
|
+
GamsSymbolDomainViolation(violation_idx_list, symbol_record)
|
|
2209
|
+
)
|
|
2210
|
+
nr_viols += 1
|
|
2211
|
+
has_next = new_intp()
|
|
2212
|
+
rc = gmdMoveNextDVInSymbol(self._gmd, dv_handle, has_next)
|
|
2213
|
+
self._check_for_gmd_error(rc)
|
|
2214
|
+
has_next = bool(_int_value_and_free(has_next))
|
|
2215
|
+
|
|
2216
|
+
has_next_db = new_intp()
|
|
2217
|
+
rc = gmdGetFirstDVInNextSymbol(self._gmd, dv_handle, has_next_db)
|
|
2218
|
+
self._check_for_gmd_error(rc)
|
|
2219
|
+
has_next_db = bool(_int_value_and_free(has_next_db))
|
|
2220
|
+
has_next = has_next_db
|
|
2221
|
+
|
|
2222
|
+
ret_list.append(
|
|
2223
|
+
GamsDatabaseDomainViolation(current_symbol, current_symbol_dvs)
|
|
2224
|
+
)
|
|
2225
|
+
|
|
2226
|
+
rc = gmdDomainCheckDone(self._gmd)
|
|
2227
|
+
self._check_for_gmd_error(rc)
|
|
2228
|
+
rc = gmdFreeDVHandle(self._gmd, dv_handle)
|
|
2229
|
+
self._check_for_gmd_error(rc)
|
|
2230
|
+
|
|
2231
|
+
return ret_list
|