gamsapi 52.5.0__cp312-cp312-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gams/__init__.py +27 -0
- gams/_version.py +1 -0
- gams/connect/__init__.py +28 -0
- gams/connect/agents/__init__.py +24 -0
- gams/connect/agents/_excel/__init__.py +32 -0
- gams/connect/agents/_excel/excelagent.py +312 -0
- gams/connect/agents/_excel/workbook.py +155 -0
- gams/connect/agents/_sqlconnectors/__init__.py +42 -0
- gams/connect/agents/_sqlconnectors/_accesshandler.py +211 -0
- gams/connect/agents/_sqlconnectors/_databasehandler.py +250 -0
- gams/connect/agents/_sqlconnectors/_mysqlhandler.py +168 -0
- gams/connect/agents/_sqlconnectors/_postgreshandler.py +131 -0
- gams/connect/agents/_sqlconnectors/_pyodbchandler.py +112 -0
- gams/connect/agents/_sqlconnectors/_sqlalchemyhandler.py +74 -0
- gams/connect/agents/_sqlconnectors/_sqlitehandler.py +262 -0
- gams/connect/agents/_sqlconnectors/_sqlserverhandler.py +179 -0
- gams/connect/agents/concatenate.py +440 -0
- gams/connect/agents/connectagent.py +743 -0
- gams/connect/agents/csvreader.py +675 -0
- gams/connect/agents/csvwriter.py +151 -0
- gams/connect/agents/domainwriter.py +143 -0
- gams/connect/agents/excelreader.py +756 -0
- gams/connect/agents/excelwriter.py +467 -0
- gams/connect/agents/filter.py +223 -0
- gams/connect/agents/gamsreader.py +112 -0
- gams/connect/agents/gamswriter.py +239 -0
- gams/connect/agents/gdxreader.py +109 -0
- gams/connect/agents/gdxwriter.py +146 -0
- gams/connect/agents/labelmanipulator.py +303 -0
- gams/connect/agents/projection.py +539 -0
- gams/connect/agents/pythoncode.py +71 -0
- gams/connect/agents/rawcsvreader.py +248 -0
- gams/connect/agents/rawexcelreader.py +312 -0
- gams/connect/agents/schema/CSVReader.yaml +92 -0
- gams/connect/agents/schema/CSVWriter.yaml +44 -0
- gams/connect/agents/schema/Concatenate.yaml +52 -0
- gams/connect/agents/schema/DomainWriter.yaml +25 -0
- gams/connect/agents/schema/ExcelReader.yaml +121 -0
- gams/connect/agents/schema/ExcelWriter.yaml +78 -0
- gams/connect/agents/schema/Filter.yaml +74 -0
- gams/connect/agents/schema/GAMSReader.yaml +20 -0
- gams/connect/agents/schema/GAMSWriter.yaml +47 -0
- gams/connect/agents/schema/GDXReader.yaml +23 -0
- gams/connect/agents/schema/GDXWriter.yaml +32 -0
- gams/connect/agents/schema/LabelManipulator.yaml +99 -0
- gams/connect/agents/schema/Projection.yaml +24 -0
- gams/connect/agents/schema/PythonCode.yaml +6 -0
- gams/connect/agents/schema/RawCSVReader.yaml +34 -0
- gams/connect/agents/schema/RawExcelReader.yaml +42 -0
- gams/connect/agents/schema/SQLReader.yaml +75 -0
- gams/connect/agents/schema/SQLWriter.yaml +103 -0
- gams/connect/agents/sqlreader.py +301 -0
- gams/connect/agents/sqlwriter.py +276 -0
- gams/connect/connectdatabase.py +275 -0
- gams/connect/connectvalidator.py +93 -0
- gams/connect/errors.py +34 -0
- gams/control/__init__.py +136 -0
- gams/control/database.py +2231 -0
- gams/control/execution.py +1900 -0
- gams/control/options.py +2792 -0
- gams/control/workspace.py +1198 -0
- gams/core/__init__.py +24 -0
- gams/core/cfg/__init__.py +26 -0
- gams/core/cfg/_cfgmcc.cp312-win_amd64.pyd +0 -0
- gams/core/cfg/cfgmcc.py +519 -0
- gams/core/dct/__init__.py +26 -0
- gams/core/dct/_dctmcc.cp312-win_amd64.pyd +0 -0
- gams/core/dct/dctmcc.py +574 -0
- gams/core/embedded/__init__.py +26 -0
- gams/core/embedded/gamsemb.py +1024 -0
- gams/core/emp/__init__.py +24 -0
- gams/core/emp/emplexer.py +89 -0
- gams/core/emp/empyacc.py +281 -0
- gams/core/gdx/__init__.py +26 -0
- gams/core/gdx/_gdxcc.cp312-win_amd64.pyd +0 -0
- gams/core/gdx/gdxcc.py +866 -0
- gams/core/gev/__init__.py +26 -0
- gams/core/gev/_gevmcc.cp312-win_amd64.pyd +0 -0
- gams/core/gev/gevmcc.py +855 -0
- gams/core/gmd/__init__.py +26 -0
- gams/core/gmd/_gmdcc.cp312-win_amd64.pyd +0 -0
- gams/core/gmd/gmdcc.py +917 -0
- gams/core/gmo/__init__.py +26 -0
- gams/core/gmo/_gmomcc.cp312-win_amd64.pyd +0 -0
- gams/core/gmo/gmomcc.py +2046 -0
- gams/core/idx/__init__.py +26 -0
- gams/core/idx/_idxcc.cp312-win_amd64.pyd +0 -0
- gams/core/idx/idxcc.py +510 -0
- gams/core/numpy/__init__.py +29 -0
- gams/core/numpy/_gams2numpy.cp312-win_amd64.pyd +0 -0
- gams/core/numpy/gams2numpy.py +1048 -0
- gams/core/opt/__init__.py +26 -0
- gams/core/opt/_optcc.cp312-win_amd64.pyd +0 -0
- gams/core/opt/optcc.py +840 -0
- gams/engine/__init__.py +204 -0
- gams/engine/api/__init__.py +13 -0
- gams/engine/api/auth_api.py +7653 -0
- gams/engine/api/cleanup_api.py +751 -0
- gams/engine/api/default_api.py +887 -0
- gams/engine/api/hypercube_api.py +2629 -0
- gams/engine/api/jobs_api.py +5229 -0
- gams/engine/api/licenses_api.py +2220 -0
- gams/engine/api/namespaces_api.py +7783 -0
- gams/engine/api/usage_api.py +5627 -0
- gams/engine/api/users_api.py +5931 -0
- gams/engine/api_client.py +804 -0
- gams/engine/api_response.py +21 -0
- gams/engine/configuration.py +601 -0
- gams/engine/exceptions.py +216 -0
- gams/engine/models/__init__.py +86 -0
- gams/engine/models/bad_input.py +89 -0
- gams/engine/models/cleanable_job_result.py +104 -0
- gams/engine/models/cleanable_job_result_page.py +113 -0
- gams/engine/models/engine_license.py +107 -0
- gams/engine/models/files_not_found.py +93 -0
- gams/engine/models/forwarded_token_response.py +112 -0
- gams/engine/models/generic_key_value_pair.py +89 -0
- gams/engine/models/hypercube.py +160 -0
- gams/engine/models/hypercube_page.py +111 -0
- gams/engine/models/hypercube_summary.py +91 -0
- gams/engine/models/hypercube_token.py +97 -0
- gams/engine/models/identity_provider.py +107 -0
- gams/engine/models/identity_provider_ldap.py +121 -0
- gams/engine/models/identity_provider_oauth2.py +146 -0
- gams/engine/models/identity_provider_oauth2_scope.py +89 -0
- gams/engine/models/identity_provider_oauth2_with_secret.py +152 -0
- gams/engine/models/identity_provider_oidc.py +133 -0
- gams/engine/models/identity_provider_oidc_with_secret.py +143 -0
- gams/engine/models/inex.py +91 -0
- gams/engine/models/invitation.py +136 -0
- gams/engine/models/invitation_quota.py +106 -0
- gams/engine/models/invitation_token.py +87 -0
- gams/engine/models/job.py +165 -0
- gams/engine/models/job_no_text_entry.py +138 -0
- gams/engine/models/job_no_text_entry_page.py +111 -0
- gams/engine/models/license.py +91 -0
- gams/engine/models/log_piece.py +96 -0
- gams/engine/models/message.py +87 -0
- gams/engine/models/message_and_token.py +99 -0
- gams/engine/models/message_with_webhook_id.py +89 -0
- gams/engine/models/model_auth_token.py +87 -0
- gams/engine/models/model_configuration.py +125 -0
- gams/engine/models/model_default_instance.py +99 -0
- gams/engine/models/model_default_user_instance.py +98 -0
- gams/engine/models/model_hypercube_job.py +106 -0
- gams/engine/models/model_hypercube_usage.py +130 -0
- gams/engine/models/model_instance_info.py +116 -0
- gams/engine/models/model_instance_info_full.py +123 -0
- gams/engine/models/model_instance_pool_info.py +112 -0
- gams/engine/models/model_job_labels.py +179 -0
- gams/engine/models/model_job_usage.py +133 -0
- gams/engine/models/model_pool_usage.py +124 -0
- gams/engine/models/model_usage.py +115 -0
- gams/engine/models/model_user.py +96 -0
- gams/engine/models/model_userinstance_info.py +119 -0
- gams/engine/models/model_userinstancepool_info.py +95 -0
- gams/engine/models/model_version.py +91 -0
- gams/engine/models/models.py +120 -0
- gams/engine/models/namespace.py +104 -0
- gams/engine/models/namespace_quota.py +96 -0
- gams/engine/models/namespace_with_permission.py +96 -0
- gams/engine/models/not_found.py +91 -0
- gams/engine/models/password_policy.py +97 -0
- gams/engine/models/perm_and_username.py +89 -0
- gams/engine/models/quota.py +117 -0
- gams/engine/models/quota_exceeded.py +97 -0
- gams/engine/models/status_code_meaning.py +89 -0
- gams/engine/models/stream_entry.py +89 -0
- gams/engine/models/system_wide_license.py +92 -0
- gams/engine/models/text_entries.py +87 -0
- gams/engine/models/text_entry.py +101 -0
- gams/engine/models/time_span.py +95 -0
- gams/engine/models/time_span_pool_worker.py +99 -0
- gams/engine/models/token_forward_error.py +87 -0
- gams/engine/models/user.py +127 -0
- gams/engine/models/user_group_member.py +96 -0
- gams/engine/models/user_groups.py +108 -0
- gams/engine/models/vapid_info.py +87 -0
- gams/engine/models/webhook.py +138 -0
- gams/engine/models/webhook_parameterized_event.py +99 -0
- gams/engine/py.typed +0 -0
- gams/engine/rest.py +258 -0
- gams/magic/__init__.py +32 -0
- gams/magic/gams_magic.py +142 -0
- gams/magic/interactive.py +402 -0
- gams/tools/__init__.py +30 -0
- gams/tools/errors.py +34 -0
- gams/tools/toolcollection/__init__.py +24 -0
- gams/tools/toolcollection/alg/__init__.py +24 -0
- gams/tools/toolcollection/alg/rank.py +51 -0
- gams/tools/toolcollection/data/__init__.py +24 -0
- gams/tools/toolcollection/data/csvread.py +444 -0
- gams/tools/toolcollection/data/csvwrite.py +311 -0
- gams/tools/toolcollection/data/exceldump.py +47 -0
- gams/tools/toolcollection/data/sqlitewrite.py +276 -0
- gams/tools/toolcollection/gdxservice/__init__.py +24 -0
- gams/tools/toolcollection/gdxservice/gdxencoding.py +104 -0
- gams/tools/toolcollection/gdxservice/gdxrename.py +94 -0
- gams/tools/toolcollection/linalg/__init__.py +24 -0
- gams/tools/toolcollection/linalg/cholesky.py +57 -0
- gams/tools/toolcollection/linalg/eigenvalue.py +56 -0
- gams/tools/toolcollection/linalg/eigenvector.py +58 -0
- gams/tools/toolcollection/linalg/invert.py +55 -0
- gams/tools/toolcollection/linalg/ols.py +138 -0
- gams/tools/toolcollection/tooltemplate.py +321 -0
- gams/tools/toolcollection/win32/__init__.py +24 -0
- gams/tools/toolcollection/win32/excelmerge.py +93 -0
- gams/tools/toolcollection/win32/exceltalk.py +76 -0
- gams/tools/toolcollection/win32/msappavail.py +49 -0
- gams/tools/toolcollection/win32/shellexecute.py +54 -0
- gams/tools/tools.py +116 -0
- gams/transfer/__init__.py +35 -0
- gams/transfer/_abcs/__init__.py +37 -0
- gams/transfer/_abcs/container_abcs.py +433 -0
- gams/transfer/_internals/__init__.py +63 -0
- gams/transfer/_internals/algorithms.py +436 -0
- gams/transfer/_internals/casepreservingdict.py +124 -0
- gams/transfer/_internals/constants.py +270 -0
- gams/transfer/_internals/domainviolation.py +103 -0
- gams/transfer/_internals/specialvalues.py +172 -0
- gams/transfer/containers/__init__.py +26 -0
- gams/transfer/containers/_container.py +1794 -0
- gams/transfer/containers/_io/__init__.py +28 -0
- gams/transfer/containers/_io/containers.py +164 -0
- gams/transfer/containers/_io/gdx.py +1029 -0
- gams/transfer/containers/_io/gmd.py +872 -0
- gams/transfer/containers/_mixins/__init__.py +26 -0
- gams/transfer/containers/_mixins/ccc.py +1274 -0
- gams/transfer/syms/__init__.py +33 -0
- gams/transfer/syms/_methods/__init__.py +24 -0
- gams/transfer/syms/_methods/tables.py +120 -0
- gams/transfer/syms/_methods/toDict.py +115 -0
- gams/transfer/syms/_methods/toList.py +83 -0
- gams/transfer/syms/_methods/toValue.py +60 -0
- gams/transfer/syms/_mixins/__init__.py +32 -0
- gams/transfer/syms/_mixins/equals.py +626 -0
- gams/transfer/syms/_mixins/generateRecords.py +499 -0
- gams/transfer/syms/_mixins/pivot.py +313 -0
- gams/transfer/syms/_mixins/pve.py +627 -0
- gams/transfer/syms/_mixins/sa.py +27 -0
- gams/transfer/syms/_mixins/sapve.py +27 -0
- gams/transfer/syms/_mixins/saua.py +27 -0
- gams/transfer/syms/_mixins/sauapve.py +199 -0
- gams/transfer/syms/_mixins/spve.py +1528 -0
- gams/transfer/syms/_mixins/ve.py +936 -0
- gams/transfer/syms/container_syms/__init__.py +31 -0
- gams/transfer/syms/container_syms/_alias.py +984 -0
- gams/transfer/syms/container_syms/_equation.py +333 -0
- gams/transfer/syms/container_syms/_parameter.py +973 -0
- gams/transfer/syms/container_syms/_set.py +604 -0
- gams/transfer/syms/container_syms/_universe_alias.py +461 -0
- gams/transfer/syms/container_syms/_variable.py +321 -0
- gamsapi-52.5.0.dist-info/METADATA +150 -0
- gamsapi-52.5.0.dist-info/RECORD +257 -0
- gamsapi-52.5.0.dist-info/WHEEL +5 -0
- gamsapi-52.5.0.dist-info/licenses/LICENSE +22 -0
- gamsapi-52.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1198 @@
|
|
|
1
|
+
#
|
|
2
|
+
# GAMS - General Algebraic Modeling System Python API
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2017-2026 GAMS Development Corp. <support@gams.com>
|
|
5
|
+
# Copyright (c) 2017-2026 GAMS Software GmbH <support@gams.com>
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
# furnished to do so, subject to the following conditions:
|
|
13
|
+
#
|
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
# copies or substantial portions of the Software.
|
|
16
|
+
#
|
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
# SOFTWARE.
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
import filecmp
|
|
27
|
+
import tempfile
|
|
28
|
+
import os
|
|
29
|
+
import shutil
|
|
30
|
+
from subprocess import Popen
|
|
31
|
+
import threading
|
|
32
|
+
from warnings import warn
|
|
33
|
+
from gams import __version__
|
|
34
|
+
from gams.control.database import *
|
|
35
|
+
from gams.control.execution import *
|
|
36
|
+
from gams.control.options import *
|
|
37
|
+
|
|
38
|
+
import sys
|
|
39
|
+
|
|
40
|
+
_is_win = _is_linux = _is_osx = False
|
|
41
|
+
if sys.platform == "win32":
|
|
42
|
+
_is_win = True
|
|
43
|
+
elif sys.platform.startswith("linux"):
|
|
44
|
+
_is_linux = True
|
|
45
|
+
elif sys.platform == "darwin":
|
|
46
|
+
_is_osx = True
|
|
47
|
+
else:
|
|
48
|
+
raise Exception("Unknown operating system")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
## @brief Exception class thrown for GAMS exceptions
|
|
52
|
+
class GamsException(Exception):
|
|
53
|
+
def __init__(self, value, workspace=None):
|
|
54
|
+
Exception.__init__(self, value)
|
|
55
|
+
self.value = value
|
|
56
|
+
if workspace is not None:
|
|
57
|
+
workspace._has_error = True
|
|
58
|
+
|
|
59
|
+
def __str__(self):
|
|
60
|
+
return self.value
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## @brief Exception class thrown for GAMS execution exceptions
|
|
64
|
+
class GamsExceptionExecution(GamsException):
|
|
65
|
+
def __init__(self, value, exit_code, workspace=None):
|
|
66
|
+
self.value = value
|
|
67
|
+
self._rc = exit_code
|
|
68
|
+
if workspace is not None:
|
|
69
|
+
workspace._has_error = True
|
|
70
|
+
|
|
71
|
+
## brief GAMS return code
|
|
72
|
+
def get_rc(self):
|
|
73
|
+
return self._rc
|
|
74
|
+
|
|
75
|
+
rc = property(get_rc)
|
|
76
|
+
|
|
77
|
+
def __str__(self):
|
|
78
|
+
return self.value
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## @brief GAMS exit code
|
|
82
|
+
class GamsExitCode(object):
|
|
83
|
+
## @brief Normal Return
|
|
84
|
+
NormalReturn = 0
|
|
85
|
+
## @brief Solver is to be called, the system should never return this number
|
|
86
|
+
SolverToBeCalled = 1
|
|
87
|
+
## @brief There was a compilation error
|
|
88
|
+
CompilationError = 2
|
|
89
|
+
## @brief There was an execution error
|
|
90
|
+
ExecutionError = 3
|
|
91
|
+
## @brief System limits were reached
|
|
92
|
+
SystemLimitsReached = 4
|
|
93
|
+
## @brief There was a file error
|
|
94
|
+
FileError = 5
|
|
95
|
+
## @brief There was a parameter error
|
|
96
|
+
ParameterError = 6
|
|
97
|
+
## @brief There was a licensing error
|
|
98
|
+
LicensingError = 7
|
|
99
|
+
## @brief There was a GAMS system error
|
|
100
|
+
GAMSSystemError = 8
|
|
101
|
+
## @brief GAMS cold not be started
|
|
102
|
+
GAMSCouldNotBeStarted = 9
|
|
103
|
+
## @brief Out of memory
|
|
104
|
+
OutOfMemory = 10
|
|
105
|
+
## @brief Out of of disk
|
|
106
|
+
OutOfDisk = 11
|
|
107
|
+
## @brief Could not create process/scratch directory
|
|
108
|
+
CouldNotCreateScratchDir = 109
|
|
109
|
+
## @brief Too many process/scratch directorie
|
|
110
|
+
TooManyScratchDirs = 110
|
|
111
|
+
## @brief Could not delete the process/scratch directory
|
|
112
|
+
CouldNotDeleteScratchDir = 112
|
|
113
|
+
## @brief Could not write "gamsnext" script
|
|
114
|
+
CouldNotWriteGamsNext = 113
|
|
115
|
+
## @brief Could not write "parameter" file
|
|
116
|
+
CouldNotWriteParamFile = 114
|
|
117
|
+
## @brief Could not read environment variable
|
|
118
|
+
CouldNotReadEnvVar = 115
|
|
119
|
+
## @brief Could not spawn the GAMS language compiler (gamscmex)
|
|
120
|
+
CouldNotSpawnGAMScmex = 400
|
|
121
|
+
## @brief Current directory (curdir) does not exist
|
|
122
|
+
CurDirNotFound = 401
|
|
123
|
+
## @brief Cannot set current directory (curdir)
|
|
124
|
+
CurDirNotSet = 402
|
|
125
|
+
## @brief Blank in system directory (UNIX only)
|
|
126
|
+
BlankInSysDir = 404
|
|
127
|
+
## @brief Blank in current directory (UNIX only)
|
|
128
|
+
BlankInCurDir = 405
|
|
129
|
+
## @brief Blank in scratch extension (scrext)
|
|
130
|
+
BlankInScrExt = 406
|
|
131
|
+
## @brief Unexpected cmexRC
|
|
132
|
+
UnexpectedCmexRC = 407
|
|
133
|
+
## @brief Could not find the process directory (procdir)
|
|
134
|
+
ProcDirNotFound = 408
|
|
135
|
+
## @brief CMEX library not found (experimental)
|
|
136
|
+
CmexLibNotFound = 409
|
|
137
|
+
## @brief Entry point in CMEX library not found (experimental)
|
|
138
|
+
CmexLibEPNotFound = 410
|
|
139
|
+
## @brief Cannot add path / Unknown UNIX environment / Cannot set environment variable
|
|
140
|
+
CannotAddPath = 909
|
|
141
|
+
## @brief Driver error: Missing command line parameter for gams.exe
|
|
142
|
+
MissingCommandLineParameter = 1000
|
|
143
|
+
## @brief Driver error: Internal error: Cannot install interrupt handler
|
|
144
|
+
CannotInstallInterrupt = 2000
|
|
145
|
+
## @brief Driver error: Problems getting current directory (sometimes caused by specifying the current directory in Microsoft UNC format)
|
|
146
|
+
CouldNotGetCurrentDir = 3000
|
|
147
|
+
## @brief Driver error: Internal error: GAMS compile and execute module not found
|
|
148
|
+
CmexNotFound = 4000
|
|
149
|
+
## @brief Driver error: Internal error: Cannot load option handling library
|
|
150
|
+
OptNotFound = 5000
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
# TODO: move this to __init__.py to be loaded with the module
|
|
154
|
+
## @brief Equation subtype
|
|
155
|
+
class EquType(object):
|
|
156
|
+
## @brief Equality - =E=
|
|
157
|
+
E = 0
|
|
158
|
+
## @brief Greater or equal than inequality - =G=
|
|
159
|
+
G = 1
|
|
160
|
+
## @brief Less or equal than inequality - =L=
|
|
161
|
+
L = 2
|
|
162
|
+
## @brief Non-binding equation - =N=
|
|
163
|
+
N = 3
|
|
164
|
+
## @brief External equation - =X=
|
|
165
|
+
X = 4
|
|
166
|
+
## @brief Cone equation - =C=
|
|
167
|
+
C = 5
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# TODO: move this to __init__.py to be loaded with the module
|
|
171
|
+
## @brief Variable subtype
|
|
172
|
+
class VarType(object):
|
|
173
|
+
## @brief Unknown variable type
|
|
174
|
+
Unknown = 0
|
|
175
|
+
## @brief Binary variable
|
|
176
|
+
Binary = 1
|
|
177
|
+
## @brief Integer Variable
|
|
178
|
+
Integer = 2
|
|
179
|
+
## @brief Positive variable
|
|
180
|
+
Positive = 3
|
|
181
|
+
## @brief Negative variable
|
|
182
|
+
Negative = 4
|
|
183
|
+
## @brief Free variable
|
|
184
|
+
Free = 5
|
|
185
|
+
## @brief Special Ordered Set 1
|
|
186
|
+
SOS1 = 6
|
|
187
|
+
## @brief Special Ordered Set 2
|
|
188
|
+
SOS2 = 7
|
|
189
|
+
## @brief Semi-continuous variable
|
|
190
|
+
SemiCont = 8
|
|
191
|
+
## @brief Semi-integer variable
|
|
192
|
+
SemiInt = 9
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
## @brief Set subtype
|
|
196
|
+
class SetType(object):
|
|
197
|
+
## @brief Multi Set - The Default
|
|
198
|
+
Multi = 0
|
|
199
|
+
## @brief Singleton Set - Zero or one element
|
|
200
|
+
Singleton = 1
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# TODO: move this to __init__.py to be loaded with the module
|
|
204
|
+
## @brief Solver termination condition
|
|
205
|
+
class SolveStat(object):
|
|
206
|
+
## @brief Normal termination
|
|
207
|
+
Normal = 1
|
|
208
|
+
## @brief Solver ran out of iterations
|
|
209
|
+
Iteration = 2
|
|
210
|
+
## @brief Solver exceeded time limit
|
|
211
|
+
Resource = 3
|
|
212
|
+
## @brief Solver quit with a problem
|
|
213
|
+
Solver = 4
|
|
214
|
+
## @brief Solver quit with nonlinear term evaluation errors
|
|
215
|
+
EvalError = 5
|
|
216
|
+
## @brief Solver terminated because the model is beyond the solvers capabilities
|
|
217
|
+
Capability = 6
|
|
218
|
+
## @brief Solver terminated with a license error
|
|
219
|
+
License = 7
|
|
220
|
+
## @brief Solver terminated on users request (e.g. Ctrl-C)
|
|
221
|
+
User = 8
|
|
222
|
+
## @brief Solver terminated on setup error
|
|
223
|
+
SetupErr = 9
|
|
224
|
+
## @brief Solver terminated with error
|
|
225
|
+
SolverErr = 10
|
|
226
|
+
## @brief Solver terminated with error
|
|
227
|
+
InternalErr = 11
|
|
228
|
+
## @brief Solve skipped
|
|
229
|
+
Skipped = 12
|
|
230
|
+
## @brief Other error
|
|
231
|
+
SystemErr = 13
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# TODO: move this to __init__.py to be loaded with the module
|
|
235
|
+
## @brief Model Solution Status
|
|
236
|
+
class ModelStat(object):
|
|
237
|
+
## @brief Optimal solution achieved
|
|
238
|
+
OptimalGlobal = 1
|
|
239
|
+
## @brief Local optimal solution achieved
|
|
240
|
+
OptimalLocal = 2
|
|
241
|
+
## @brief Unbounded model found
|
|
242
|
+
Unbounded = 3
|
|
243
|
+
## @brief Infeasible model found
|
|
244
|
+
InfeasibleGlobal = 4
|
|
245
|
+
## @brief Locally infeasible model found
|
|
246
|
+
InfeasibleLocal = 5
|
|
247
|
+
## @brief Solver terminated early and model was still infeasible
|
|
248
|
+
InfeasibleIntermed = 6
|
|
249
|
+
## @brief Solver terminated early and model was feasible but not yet optimal
|
|
250
|
+
Feasible = 7
|
|
251
|
+
## @brief Integer solution found
|
|
252
|
+
Integer = 8
|
|
253
|
+
## @brief Solver terminated early with a non integer solution found
|
|
254
|
+
NonIntegerIntermed = 9
|
|
255
|
+
## @brief No feasible integer solution could be found
|
|
256
|
+
IntegerInfeasible = 10
|
|
257
|
+
## @brief Licensing problem
|
|
258
|
+
LicenseError = 11
|
|
259
|
+
## @brief Error - No cause known
|
|
260
|
+
ErrorUnknown = 12
|
|
261
|
+
## @brief Error - No solution attained
|
|
262
|
+
ErrorNoSolution = 13
|
|
263
|
+
## @brief No solution returned
|
|
264
|
+
NoSolutionReturned = 14
|
|
265
|
+
## @brief Unique solution in a CNS models
|
|
266
|
+
SolvedUnique = 15
|
|
267
|
+
## @brief Feasible solution in a CNS models
|
|
268
|
+
Solved = 16
|
|
269
|
+
## @brief Singular in a CNS models
|
|
270
|
+
SolvedSingular = 17
|
|
271
|
+
## @brief Unbounded - no solution
|
|
272
|
+
UnboundedNoSolution = 18
|
|
273
|
+
## @brief Infeasible - no solution
|
|
274
|
+
InfeasibleNoSolution = 19
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
## @brief GAMS Debug Level
|
|
278
|
+
class DebugLevel(object):
|
|
279
|
+
## @brief No debug
|
|
280
|
+
Off = 0
|
|
281
|
+
## @brief Keep temporary files only if GamsException/GamsExceptionExecution was raised in GamsJob.run(), GamsJob.run_engine(), or GamsModelInstance.solve()
|
|
282
|
+
KeepFilesOnError = 1
|
|
283
|
+
## @brief Keep temporary files
|
|
284
|
+
KeepFiles = 2
|
|
285
|
+
## @brief Send GAMS log to stdout and keep temporary files
|
|
286
|
+
ShowLog = 3
|
|
287
|
+
## @brief Send highly technical info and GAMS log to stdout and keep temporary files
|
|
288
|
+
Verbose = 4
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class GamsWorkspace(object):
|
|
292
|
+
"""
|
|
293
|
+
@brief The GamsWorkspace is the base class of the gams.control API.
|
|
294
|
+
@details <p>Most objects of the
|
|
295
|
+
control API (e.g. GamsDatabase and GamsJob) should be created by an "add"
|
|
296
|
+
method of GamsWorkspace instead of using the constructors. </p>
|
|
297
|
+
<p>Unless a GAMS system directory is specified during construction of
|
|
298
|
+
GamsWorkspace, GamsWorkspace determines the location of the GAMS installation
|
|
299
|
+
automatically. This is a source of potential problems if more than one GAMS
|
|
300
|
+
installation exist on the machine. </p>
|
|
301
|
+
<p>Furthermore, a working directory (the anchor into the file system) can be
|
|
302
|
+
provided when constructing the GamsWorkspace instance. All file based
|
|
303
|
+
operation inside a GAMS model should be relative to this location (e.g. $GDXIN
|
|
304
|
+
and $include). There are options to add input search paths (e.g. IDir) and
|
|
305
|
+
output path (e.g. PutDir) to specify other file system locations. If no working
|
|
306
|
+
directory is supplied, GamsWorkspace creates a temporary folder and on
|
|
307
|
+
instance destruction removes this temporary folder. </p>
|
|
308
|
+
<p>In a typical Python application a single instance of GamsWorkspace will
|
|
309
|
+
suffice, since the class is thread-safe. </p>
|
|
310
|
+
<h5>Working with different GAMS Versions on one Machine</h5>
|
|
311
|
+
<p>When creating a new instance of GamsWorkspace, one way of defining the GAMS system
|
|
312
|
+
directory is setting the system_directory parameter of the constructor accordingly. If it
|
|
313
|
+
is not set, it is tried to be defined automatically (see \ref API_PY_CONTROL for details). However, this can be tricky if there
|
|
314
|
+
is more than one version of GAMS installed on a machine and especially if there are
|
|
315
|
+
different applications running with different GAMS versions.</p>
|
|
316
|
+
<p>On Windows, the automatic identification relies on information left in the Windows registry by the
|
|
317
|
+
GAMS installer. Hence the system directory of the last GAMS installation will be found in
|
|
318
|
+
this automatic identification step. One way of resetting the information in the registry
|
|
319
|
+
is running the executable "findthisgams.exe" from the directory that should be detected
|
|
320
|
+
automatically. While this can be done from the outside of the application it is not much
|
|
321
|
+
more convenient than the system_directory argument in the GamsWorkspace constructor.</p>
|
|
322
|
+
<p>If one has a very structured way of organizing the GAMS installations (e.g. following
|
|
323
|
+
the GAMS default installation location) one can use GamsWorkspace.api_version to point to
|
|
324
|
+
the best matching GAMS system directory:</p>
|
|
325
|
+
@code{.py}
|
|
326
|
+
sysdir = "C:\\GAMS\\" + GamsWorkspace.api_version[:2]
|
|
327
|
+
ws = GamsWorkspace(system_directory=sysdir)
|
|
328
|
+
@endcode
|
|
329
|
+
<p>This avoids the automatic identification of the GAMS system directory but might be the
|
|
330
|
+
most convenient solution for systems running multiple applications using different versions
|
|
331
|
+
of the GAMS Python API together with different versions of GAMS.</p>
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
def set_eps(self, value):
|
|
335
|
+
self._eps = value
|
|
336
|
+
|
|
337
|
+
## @brief Reset value to be stored in and read from GamsDatabase for Epsilon
|
|
338
|
+
def get_eps(self):
|
|
339
|
+
return self._eps
|
|
340
|
+
|
|
341
|
+
## @brief Get value to be stored in and read from GamsDatabase for Epsilon
|
|
342
|
+
my_eps = property(get_eps, set_eps)
|
|
343
|
+
|
|
344
|
+
def get_working_directory(self):
|
|
345
|
+
return self._working_directory
|
|
346
|
+
|
|
347
|
+
## @brief GAMS working directory, anchor for all file-based operations
|
|
348
|
+
working_directory = property(get_working_directory)
|
|
349
|
+
|
|
350
|
+
def get_system_directory(self):
|
|
351
|
+
return self._system_directory
|
|
352
|
+
|
|
353
|
+
## @brief GAMS system directory
|
|
354
|
+
system_directory = property(get_system_directory)
|
|
355
|
+
|
|
356
|
+
def get_version(self):
|
|
357
|
+
return self._version
|
|
358
|
+
|
|
359
|
+
## @brief GAMS Version used
|
|
360
|
+
version = property(get_version)
|
|
361
|
+
|
|
362
|
+
def get_major_rel_number(self):
|
|
363
|
+
return self._major_rel_number
|
|
364
|
+
|
|
365
|
+
## @brief GAMS Major Release Number
|
|
366
|
+
major_rel_number = property(get_major_rel_number)
|
|
367
|
+
|
|
368
|
+
def get_minor_rel_number(self):
|
|
369
|
+
return self._minor_rel_number
|
|
370
|
+
|
|
371
|
+
## @brief GAMS Minor Release Number
|
|
372
|
+
minor_rel_number = property(get_minor_rel_number)
|
|
373
|
+
|
|
374
|
+
def get_gold_rel_number(self):
|
|
375
|
+
return self._gold_rel_number
|
|
376
|
+
|
|
377
|
+
## @brief GAMS GOLD Release Number
|
|
378
|
+
gold_rel_number = property(get_gold_rel_number)
|
|
379
|
+
|
|
380
|
+
## @brief GAMS API version
|
|
381
|
+
api_version = __version__
|
|
382
|
+
|
|
383
|
+
## @brief GAMS API Major Release Number
|
|
384
|
+
api_major_rel_number = int(__version__.split(".")[0])
|
|
385
|
+
|
|
386
|
+
## @brief GAMS API Minor Release Number
|
|
387
|
+
api_minor_rel_number = int(__version__.split(".")[1])
|
|
388
|
+
|
|
389
|
+
## @brief GAMS API GOLD Release Number
|
|
390
|
+
api_gold_rel_number = int(__version__.split(".")[2])
|
|
391
|
+
|
|
392
|
+
@staticmethod
|
|
393
|
+
def _find_gams_win():
|
|
394
|
+
gams_dir = ""
|
|
395
|
+
if sys.version_info[0] >= 3:
|
|
396
|
+
import winreg as wreg
|
|
397
|
+
else:
|
|
398
|
+
import _winreg as wreg
|
|
399
|
+
|
|
400
|
+
try:
|
|
401
|
+
gams_dir = wreg.QueryValue(
|
|
402
|
+
wreg.HKEY_CURRENT_USER, r"Software\Classes\gams.location"
|
|
403
|
+
)
|
|
404
|
+
except:
|
|
405
|
+
try:
|
|
406
|
+
gams_dir = wreg.QueryValue(
|
|
407
|
+
wreg.HKEY_LOCAL_MACHINE, r"Software\Classes\gams.location"
|
|
408
|
+
)
|
|
409
|
+
except:
|
|
410
|
+
pass
|
|
411
|
+
return gams_dir
|
|
412
|
+
|
|
413
|
+
@staticmethod
|
|
414
|
+
def _sysdir_from_envvar(ld_string):
|
|
415
|
+
gams_dir = ""
|
|
416
|
+
try:
|
|
417
|
+
if ld_string in os.environ:
|
|
418
|
+
paths = os.environ[ld_string].split(":")
|
|
419
|
+
for p in paths:
|
|
420
|
+
if os.path.exists(
|
|
421
|
+
os.path.join(p, "gamsstmp.txt")
|
|
422
|
+
) and not os.path.exists(
|
|
423
|
+
os.path.join(p, "gams.exe")
|
|
424
|
+
): # prevent finding Windows installation under WSL
|
|
425
|
+
gams_dir = p
|
|
426
|
+
break
|
|
427
|
+
except:
|
|
428
|
+
pass
|
|
429
|
+
return gams_dir
|
|
430
|
+
|
|
431
|
+
@staticmethod
|
|
432
|
+
def is_same_system_directory(first, second):
|
|
433
|
+
if os.path.exists(os.path.join(first, "gamsstmp.txt")) and os.path.exists(
|
|
434
|
+
os.path.join(second, "gamsstmp.txt")
|
|
435
|
+
):
|
|
436
|
+
if filecmp.cmp(
|
|
437
|
+
os.path.join(first, "gamsstmp.txt"),
|
|
438
|
+
os.path.join(second, "gamsstmp.txt"),
|
|
439
|
+
):
|
|
440
|
+
return True
|
|
441
|
+
else:
|
|
442
|
+
return False
|
|
443
|
+
else:
|
|
444
|
+
return False
|
|
445
|
+
|
|
446
|
+
def _run_gams_audit(self):
|
|
447
|
+
if _is_win:
|
|
448
|
+
si = subprocess.STARTUPINFO()
|
|
449
|
+
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
|
450
|
+
si.wShowWindow = subprocess.SW_HIDE
|
|
451
|
+
try:
|
|
452
|
+
self._p = subprocess.Popen(
|
|
453
|
+
self._system_directory + os.sep + "gams.exe audit lo=3",
|
|
454
|
+
stdout=subprocess.PIPE,
|
|
455
|
+
cwd=self._working_directory,
|
|
456
|
+
startupinfo=si,
|
|
457
|
+
creationflags=subprocess.CREATE_NEW_CONSOLE,
|
|
458
|
+
)
|
|
459
|
+
except:
|
|
460
|
+
raise GamsException("Error retrieving audit info")
|
|
461
|
+
else:
|
|
462
|
+
try:
|
|
463
|
+
self._p = subprocess.Popen(
|
|
464
|
+
[self._system_directory + os.sep + "gams", "audit", "lo=3"],
|
|
465
|
+
stdout=subprocess.PIPE,
|
|
466
|
+
cwd=self._working_directory,
|
|
467
|
+
)
|
|
468
|
+
except:
|
|
469
|
+
raise GamsException("Error retrieving audit info")
|
|
470
|
+
|
|
471
|
+
version_string = ""
|
|
472
|
+
new_data = ""
|
|
473
|
+
while True:
|
|
474
|
+
# we don't want to get an exception when interrupting with ctrl-c
|
|
475
|
+
try:
|
|
476
|
+
new_data = self._p.stdout.readline()
|
|
477
|
+
if sys.version_info[0] >= 3:
|
|
478
|
+
new_data = new_data.decode()
|
|
479
|
+
version_string += new_data
|
|
480
|
+
except KeyboardInterrupt:
|
|
481
|
+
pass
|
|
482
|
+
if new_data == "" and self._p.poll() != None:
|
|
483
|
+
break
|
|
484
|
+
exitcode = self._p.wait()
|
|
485
|
+
if exitcode != 0:
|
|
486
|
+
raise GamsException("Error retrieving audit info")
|
|
487
|
+
self._p.stdout.close()
|
|
488
|
+
self._p = None
|
|
489
|
+
return version_string
|
|
490
|
+
|
|
491
|
+
def _parse_gams_version(self, version_string):
|
|
492
|
+
major, minor, patch = self._version.split(".")
|
|
493
|
+
self._major_rel_number = int(major)
|
|
494
|
+
self._minor_rel_number = int(minor)
|
|
495
|
+
self._gold_rel_number = int(patch)
|
|
496
|
+
|
|
497
|
+
def _init_gams_version(self):
|
|
498
|
+
# read version from gamsstmp.txt (fast)
|
|
499
|
+
try:
|
|
500
|
+
with open(os.path.join(self._system_directory, "gamsstmp.txt"), "r") as f:
|
|
501
|
+
self._version = f.read()
|
|
502
|
+
# wei 48.1.0 (Oct 12, 2024): Sat 12 Oct 11:24:04 AM EST 2024
|
|
503
|
+
self._version = self._version.split()[1].strip()
|
|
504
|
+
self._parse_gams_version(self._version)
|
|
505
|
+
except: # we could not derive the version from gamsstmp.txt, try 'gams audit' instead (slow)
|
|
506
|
+
if self._debug >= DebugLevel.Verbose:
|
|
507
|
+
warn(
|
|
508
|
+
f"Unable to read version information from gamsstmp.txt. Switching to 'gams audit' which might result in decreased performance.",
|
|
509
|
+
stacklevel=2,
|
|
510
|
+
)
|
|
511
|
+
self._version = self._run_gams_audit()
|
|
512
|
+
try:
|
|
513
|
+
# GAMSX 24.1.0 r38765 ALFA Released 1Mar13 VS8 x86/MS Windows
|
|
514
|
+
self._version = self._version.split()[1].strip()
|
|
515
|
+
self._parse_gams_version(self._version)
|
|
516
|
+
# for compatibility with GAMS version before 24.1
|
|
517
|
+
except:
|
|
518
|
+
# e.g. GAMSX Feb 14, 2013 24.0.2 WIN 38380.38394 VS8 x86/MS Windows
|
|
519
|
+
self._version = self._version.split()[4].strip()
|
|
520
|
+
self._parse_gams_version(self._version)
|
|
521
|
+
|
|
522
|
+
def __init__(
|
|
523
|
+
self,
|
|
524
|
+
working_directory=None,
|
|
525
|
+
system_directory=None,
|
|
526
|
+
debug=DebugLevel.KeepFilesOnError,
|
|
527
|
+
):
|
|
528
|
+
"""
|
|
529
|
+
@brief constructor
|
|
530
|
+
@param working_directory GAMS working directory, anchor for all file-based operations (determined automatically if omitted, in user's temporary folder)
|
|
531
|
+
@param system_directory GAMS system directory (determined automatically if omitted)
|
|
532
|
+
@param debug Debug Flag (default: DebugLevel.KeepFilesOnError)
|
|
533
|
+
"""
|
|
534
|
+
|
|
535
|
+
self._debug = debug
|
|
536
|
+
self._has_error = False
|
|
537
|
+
|
|
538
|
+
# Allow to overwrite Debug setting with environment variable
|
|
539
|
+
if "GAMSOOAPIDEBUG" in os.environ:
|
|
540
|
+
env_debug = os.environ["GAMSOOAPIDEBUG"].lower()
|
|
541
|
+
if env_debug == "off":
|
|
542
|
+
self._debug = DebugLevel.Off
|
|
543
|
+
elif env_debug == "keepfilesonerror":
|
|
544
|
+
self._debug = DebugLevel.KeepFilesOnError
|
|
545
|
+
elif env_debug == "keepfiles":
|
|
546
|
+
self._debug = DebugLevel.KeepFiles
|
|
547
|
+
elif env_debug == "showlog":
|
|
548
|
+
self._debug = DebugLevel.ShowLog
|
|
549
|
+
elif env_debug == "verbose":
|
|
550
|
+
self._debug = DebugLevel.Verbose
|
|
551
|
+
|
|
552
|
+
self._checkpoint_lock = threading.Lock()
|
|
553
|
+
self._database_lock = threading.Lock()
|
|
554
|
+
self._job_lock = threading.Lock()
|
|
555
|
+
self._modelinstance_lock = threading.Lock()
|
|
556
|
+
self._debug_lock = threading.Lock()
|
|
557
|
+
|
|
558
|
+
self._debug_out("---- Entering GamsWorkspace constructor ----", 0)
|
|
559
|
+
|
|
560
|
+
self._system_directory = None
|
|
561
|
+
self._working_directory = None
|
|
562
|
+
self._using_tmp_working_dir = None
|
|
563
|
+
|
|
564
|
+
self._eps = None
|
|
565
|
+
|
|
566
|
+
self._gmdHandles = []
|
|
567
|
+
self._gevHandles = []
|
|
568
|
+
|
|
569
|
+
## @brief A string used to prefix automatically generated files
|
|
570
|
+
self.scratch_file_prefix = "_gams_py_"
|
|
571
|
+
|
|
572
|
+
# TODO: can we use lists instead of dictionaries?
|
|
573
|
+
self._gams_checkpoints = {}
|
|
574
|
+
self._gams_databases = {}
|
|
575
|
+
self._gams_jobs = {}
|
|
576
|
+
self._gams_modelinstances = {}
|
|
577
|
+
|
|
578
|
+
self._def_job_name_cnt = 0
|
|
579
|
+
self._def_job_name_stem = "gjo"
|
|
580
|
+
|
|
581
|
+
self._def_database_name_cnt = 0
|
|
582
|
+
self._def_database_name_stem = "gdb"
|
|
583
|
+
|
|
584
|
+
self._def_checkpoint_name_cnt = 0
|
|
585
|
+
self._def_checkpoint_name_stem = "gcp"
|
|
586
|
+
|
|
587
|
+
self._def_modelinstance_name_cnt = 0
|
|
588
|
+
self._def_modelinstance_name_stem = "gmi"
|
|
589
|
+
|
|
590
|
+
if working_directory is None:
|
|
591
|
+
self._using_tmp_working_dir = True
|
|
592
|
+
self._working_directory = tempfile.mkdtemp()
|
|
593
|
+
else:
|
|
594
|
+
if working_directory == "":
|
|
595
|
+
raise GamsException("Empty string is not allowd as working directory")
|
|
596
|
+
self._working_directory = os.path.abspath(working_directory)
|
|
597
|
+
# if the directory doesn't exist, create it
|
|
598
|
+
if not os.path.exists(self._working_directory):
|
|
599
|
+
os.mkdir(self._working_directory)
|
|
600
|
+
|
|
601
|
+
if _is_win:
|
|
602
|
+
if system_directory is None:
|
|
603
|
+
self._system_directory = GamsWorkspace._find_gams_win()
|
|
604
|
+
if not self._system_directory or not os.path.exists(
|
|
605
|
+
os.path.join(os.path.abspath(self._system_directory), "optgams.def")
|
|
606
|
+
):
|
|
607
|
+
raise GamsException(
|
|
608
|
+
"GAMS System directory "
|
|
609
|
+
+ self._system_directory
|
|
610
|
+
+ " not found or invalid. Either specify a valid system directory by passing it to the GamsWorkspace constructor or run findthisgams.exe in the GAMS system directory you want to use."
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
else:
|
|
614
|
+
if system_directory == "":
|
|
615
|
+
raise GamsException(
|
|
616
|
+
"Empty string is not allowd as system directory"
|
|
617
|
+
)
|
|
618
|
+
self._system_directory = os.path.abspath(system_directory)
|
|
619
|
+
if not os.path.exists(
|
|
620
|
+
os.path.join(self._system_directory, "optgams.def")
|
|
621
|
+
):
|
|
622
|
+
raise GamsException(
|
|
623
|
+
"Invalid GAMS system directory: " + self._system_directory
|
|
624
|
+
)
|
|
625
|
+
else:
|
|
626
|
+
if system_directory is None:
|
|
627
|
+
if _is_linux:
|
|
628
|
+
ld_string = "LD_LIBRARY_PATH"
|
|
629
|
+
elif _is_osx:
|
|
630
|
+
ld_string = "DYLD_LIBRARY_PATH"
|
|
631
|
+
path = GamsWorkspace._sysdir_from_envvar("PATH")
|
|
632
|
+
ld_library_path = GamsWorkspace._sysdir_from_envvar(ld_string)
|
|
633
|
+
|
|
634
|
+
if path and os.path.exists(
|
|
635
|
+
os.path.join(os.path.abspath(path), "optgams.def")
|
|
636
|
+
):
|
|
637
|
+
self._system_directory = path
|
|
638
|
+
elif ld_library_path and os.path.exists(
|
|
639
|
+
os.path.join(os.path.abspath(ld_library_path), "optgams.def")
|
|
640
|
+
):
|
|
641
|
+
self._system_directory = ld_library_path
|
|
642
|
+
else:
|
|
643
|
+
raise GamsException(
|
|
644
|
+
"GAMS System directory not found or invalid. You need to set either PATH or "
|
|
645
|
+
+ ld_string
|
|
646
|
+
+ " to a valid GAMS system directory or to specify one in the GamsWorkspace constructor."
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
if self._debug > DebugLevel.KeepFilesOnError:
|
|
650
|
+
if not GamsWorkspace.is_same_system_directory(
|
|
651
|
+
os.path.abspath(path), os.path.abspath(ld_library_path)
|
|
652
|
+
):
|
|
653
|
+
warn(
|
|
654
|
+
f"Found different GAMS system directories in PATH and {ld_string}. Using the one from PATH",
|
|
655
|
+
stacklevel=2,
|
|
656
|
+
)
|
|
657
|
+
else:
|
|
658
|
+
if system_directory == "":
|
|
659
|
+
raise GamsException(
|
|
660
|
+
"Empty string is not allowd as system directory"
|
|
661
|
+
)
|
|
662
|
+
self._system_directory = os.path.abspath(system_directory)
|
|
663
|
+
if not os.path.exists(
|
|
664
|
+
os.path.join(self._system_directory, "optgams.def")
|
|
665
|
+
) or os.path.exists(
|
|
666
|
+
os.path.join(
|
|
667
|
+
self._system_directory, "gams.exe"
|
|
668
|
+
) # prevent using Windows installation under WSL
|
|
669
|
+
):
|
|
670
|
+
raise GamsException(
|
|
671
|
+
"Invalid GAMS system directory: " + self._system_directory
|
|
672
|
+
)
|
|
673
|
+
self._system_directory = os.path.realpath(
|
|
674
|
+
os.path.abspath(self._system_directory)
|
|
675
|
+
)
|
|
676
|
+
|
|
677
|
+
prefix = ""
|
|
678
|
+
suffix = ".dll"
|
|
679
|
+
if _is_linux:
|
|
680
|
+
prefix = "lib"
|
|
681
|
+
suffix = ".so"
|
|
682
|
+
elif _is_osx:
|
|
683
|
+
prefix = "lib"
|
|
684
|
+
suffix = ".dylib"
|
|
685
|
+
|
|
686
|
+
# Check that none of the required GAMS libraries can be found in the working directory
|
|
687
|
+
if os.path.normcase(self._system_directory) != os.path.normcase(
|
|
688
|
+
self._working_directory
|
|
689
|
+
):
|
|
690
|
+
libstems = ["gdxcc", "gdxdc", "gmdcc", "joatdc", "optdc"]
|
|
691
|
+
for stem in libstems:
|
|
692
|
+
lib_name = prefix + stem + "lib64" + suffix
|
|
693
|
+
if os.path.exists(os.path.join(self._working_directory, lib_name)):
|
|
694
|
+
warn(
|
|
695
|
+
f"Found library {lib_name} "
|
|
696
|
+
+ f"in the Working Directory ({self._working_directory}). "
|
|
697
|
+
+ f"This could cause a problem when it is a different version than the one in the System Directory ({self._system_directory}).",
|
|
698
|
+
stacklevel=2,
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
# need to set the path for windows
|
|
702
|
+
if _is_win:
|
|
703
|
+
# GamsJob.run_engine() requires urllib3 which loads libssl-1_1-x64.dll. We need to import urllib3
|
|
704
|
+
# before we prepend the GAMS system directory to the PATH in order to prevent loading an incompatible version
|
|
705
|
+
# of libssl-1_1-x64.dll from the GAMS system directory.
|
|
706
|
+
try:
|
|
707
|
+
import urllib3
|
|
708
|
+
except:
|
|
709
|
+
pass
|
|
710
|
+
env_var = "PATH"
|
|
711
|
+
if env_var in os.environ:
|
|
712
|
+
if not os.environ[env_var].startswith(
|
|
713
|
+
self._system_directory + os.pathsep
|
|
714
|
+
):
|
|
715
|
+
os.environ[env_var] = (
|
|
716
|
+
self._system_directory + os.pathsep + os.environ[env_var]
|
|
717
|
+
)
|
|
718
|
+
else:
|
|
719
|
+
os.environ[env_var] = self._system_directory
|
|
720
|
+
|
|
721
|
+
self._init_gams_version()
|
|
722
|
+
if self._version != __version__:
|
|
723
|
+
warn(
|
|
724
|
+
f"The GAMS version ({self.version}) differs from the API version ({__version__}).",
|
|
725
|
+
stacklevel=2,
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
def _debug_out(self, msg, lvl):
|
|
729
|
+
self._debug_lock.acquire()
|
|
730
|
+
if self._debug >= DebugLevel.Verbose:
|
|
731
|
+
for i in range(lvl):
|
|
732
|
+
print(" ", end="")
|
|
733
|
+
print(msg)
|
|
734
|
+
sys.stdout.flush()
|
|
735
|
+
self._debug_lock.release()
|
|
736
|
+
|
|
737
|
+
def closedown(self):
|
|
738
|
+
"""
|
|
739
|
+
@brief Closes down all network sessions of all GamsModelInstances belonging to the current GamsWorkspace
|
|
740
|
+
"""
|
|
741
|
+
import gc
|
|
742
|
+
model_instances = []
|
|
743
|
+
for obj in gc.get_objects():
|
|
744
|
+
try:
|
|
745
|
+
if isinstance(obj, GamsModelInstance) and obj.sync_db.workspace is self:
|
|
746
|
+
model_instances.append(obj)
|
|
747
|
+
except ReferenceError: # silently skip objects that cause a ReferenceError in isinstance(), e.g. weakref
|
|
748
|
+
pass
|
|
749
|
+
for mi in model_instances:
|
|
750
|
+
mi.cleanup()
|
|
751
|
+
|
|
752
|
+
def __del__(self):
|
|
753
|
+
self._debug_out("---- Entering GamsWorkspace destructor ----", 0)
|
|
754
|
+
for g in self._gmdHandles:
|
|
755
|
+
if gmdHandleToPtr(g) != None:
|
|
756
|
+
gmdFree(g)
|
|
757
|
+
for g in self._gevHandles:
|
|
758
|
+
if gevHandleToPtr(g) != None:
|
|
759
|
+
gevFree(g)
|
|
760
|
+
try:
|
|
761
|
+
if self._using_tmp_working_dir and (
|
|
762
|
+
self._debug == DebugLevel.Off
|
|
763
|
+
or (self._debug == DebugLevel.KeepFilesOnError and not self._has_error)
|
|
764
|
+
):
|
|
765
|
+
shutil.rmtree(self._working_directory)
|
|
766
|
+
except:
|
|
767
|
+
pass
|
|
768
|
+
|
|
769
|
+
def _xxxlib(self, libname, model):
|
|
770
|
+
if _is_win:
|
|
771
|
+
p = Popen(
|
|
772
|
+
self._system_directory + os.sep + libname + "lib.exe " + model,
|
|
773
|
+
cwd=self._working_directory,
|
|
774
|
+
)
|
|
775
|
+
else:
|
|
776
|
+
p = Popen(
|
|
777
|
+
[self._system_directory + os.sep + libname + "lib", model],
|
|
778
|
+
cwd=self._working_directory,
|
|
779
|
+
)
|
|
780
|
+
exitcode = p.wait()
|
|
781
|
+
if exitcode != 0:
|
|
782
|
+
raise GamsException(
|
|
783
|
+
libname + "lib return code not 0 (" + str(exitcode) + ")"
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
def gamslib(self, model):
|
|
787
|
+
"""
|
|
788
|
+
@brief Retrieves model from GAMS Model Library
|
|
789
|
+
@param model Model name
|
|
790
|
+
"""
|
|
791
|
+
self._xxxlib("gams", model)
|
|
792
|
+
|
|
793
|
+
def testlib(self, model):
|
|
794
|
+
"""
|
|
795
|
+
@brief Retrieves model from GAMS Test Library
|
|
796
|
+
@param model Model name
|
|
797
|
+
"""
|
|
798
|
+
self._xxxlib("test", model)
|
|
799
|
+
|
|
800
|
+
def emplib(self, model):
|
|
801
|
+
"""
|
|
802
|
+
@brief Retrieves model from Extended Math Programming Library
|
|
803
|
+
@param model Model name
|
|
804
|
+
"""
|
|
805
|
+
self._xxxlib("emp", model)
|
|
806
|
+
|
|
807
|
+
def datalib(self, model):
|
|
808
|
+
"""
|
|
809
|
+
@brief Retrieves model from GAMS Data Utilities Library
|
|
810
|
+
@param model Model name
|
|
811
|
+
"""
|
|
812
|
+
self._xxxlib("data", model)
|
|
813
|
+
|
|
814
|
+
def finlib(self, model):
|
|
815
|
+
"""
|
|
816
|
+
@brief Retrieves model from Practical Financial Optimization Library
|
|
817
|
+
@param model Model name
|
|
818
|
+
"""
|
|
819
|
+
self._xxxlib("fin", model)
|
|
820
|
+
|
|
821
|
+
def noalib(self, model):
|
|
822
|
+
"""
|
|
823
|
+
@brief Retrieves model from Nonlinear Optimization Applications Using the GAMS Technology Library
|
|
824
|
+
@param model Model name
|
|
825
|
+
"""
|
|
826
|
+
self._xxxlib("noa", model)
|
|
827
|
+
|
|
828
|
+
def psoptlib(self, model):
|
|
829
|
+
"""
|
|
830
|
+
@brief Retrieves model from Power System Optimization Modelling Library
|
|
831
|
+
@param model Model name
|
|
832
|
+
"""
|
|
833
|
+
self._xxxlib("psopt", model)
|
|
834
|
+
|
|
835
|
+
def apilib(self, model):
|
|
836
|
+
"""
|
|
837
|
+
@brief Retrieves model from GAMS API Library
|
|
838
|
+
@param model Model name
|
|
839
|
+
"""
|
|
840
|
+
self._xxxlib("api", model)
|
|
841
|
+
|
|
842
|
+
def add_database(
|
|
843
|
+
self, database_name=None, source_database=None, in_model_name=None
|
|
844
|
+
):
|
|
845
|
+
"""
|
|
846
|
+
@brief Database creation
|
|
847
|
+
@param database_name Identifier of GamsDatabase (determined automatically if omitted)
|
|
848
|
+
@param source_database Source GamsDatabase to initialize Database from (empty Database if omitted)
|
|
849
|
+
@param in_model_name GAMS string constant that is used to access this database
|
|
850
|
+
@return Instance of type GamsDatabase
|
|
851
|
+
"""
|
|
852
|
+
return GamsDatabase(self, database_name, None, source_database, in_model_name)
|
|
853
|
+
|
|
854
|
+
def add_database_from_gdx(
|
|
855
|
+
self, gdx_file_name, database_name=None, in_model_name=None
|
|
856
|
+
):
|
|
857
|
+
"""
|
|
858
|
+
@brief Database creation from an existing GDX file
|
|
859
|
+
@param gdx_file_name GDX File to initialize Database from
|
|
860
|
+
@param database_name Identifier of GamsDatabase (determined automatically if omitted)
|
|
861
|
+
@param in_model_name GAMS string constant that is used to access this database
|
|
862
|
+
@return Instance of type GamsDatabase
|
|
863
|
+
"""
|
|
864
|
+
if gdx_file_name == None or len(gdx_file_name) == 0:
|
|
865
|
+
raise GamsException(
|
|
866
|
+
"Could not create GamsDatabase instance with gdx_file_name being None or empty string"
|
|
867
|
+
)
|
|
868
|
+
return GamsDatabase(self, database_name, gdx_file_name, None, in_model_name)
|
|
869
|
+
|
|
870
|
+
def _add_database_from_gmd(
|
|
871
|
+
self, gmd_handle, database_name=None, in_model_name=None
|
|
872
|
+
):
|
|
873
|
+
"""
|
|
874
|
+
@brief Database creation from an existing GMD handle. This will alter setting for special values and debug settings using the functions: gmdSetDebug and gmdSetSpecialValues. Meant for internal use only
|
|
875
|
+
@param gmd_handle The already created and initialised GMD handle
|
|
876
|
+
@param database_name Identifier of GamsDatabase (determined automatically if omitted)
|
|
877
|
+
@param in_model_name GAMS string constant that is used to access this database
|
|
878
|
+
@return Instance of type GamsDatabase
|
|
879
|
+
"""
|
|
880
|
+
return GamsDatabase(
|
|
881
|
+
self, database_name, None, None, in_model_name, False, gmd_handle
|
|
882
|
+
)
|
|
883
|
+
|
|
884
|
+
def add_job_from_string(self, gams_source, checkpoint=None, job_name=None):
|
|
885
|
+
"""
|
|
886
|
+
@brief Create GamsJob from string model source
|
|
887
|
+
@param gams_source GAMS model as string
|
|
888
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
889
|
+
@param job_name Job name (determined automatically if omitted)
|
|
890
|
+
@return GamsJob instance
|
|
891
|
+
"""
|
|
892
|
+
return GamsJob(
|
|
893
|
+
self, source=gams_source, checkpoint=checkpoint, job_name=job_name
|
|
894
|
+
)
|
|
895
|
+
|
|
896
|
+
def add_job_from_file(self, file_name, checkpoint=None, job_name=None):
|
|
897
|
+
"""
|
|
898
|
+
@brief Create GamsJob from model file
|
|
899
|
+
@param file_name GAMS source file name
|
|
900
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
901
|
+
@param job_name Job name (determined automatically if omitted)
|
|
902
|
+
@return GamsJob instance
|
|
903
|
+
"""
|
|
904
|
+
return GamsJob(
|
|
905
|
+
self, file_name=file_name, checkpoint=checkpoint, job_name=job_name
|
|
906
|
+
)
|
|
907
|
+
|
|
908
|
+
def add_job_from_gamslib(self, model, checkpoint=None, job_name=None):
|
|
909
|
+
"""
|
|
910
|
+
@brief Create GamsJob from model from GAMS Model Library
|
|
911
|
+
@param model model name
|
|
912
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
913
|
+
@param job_name Job name (determined automatically if omitted)
|
|
914
|
+
@return GamsJob instance
|
|
915
|
+
"""
|
|
916
|
+
self.gamslib(model)
|
|
917
|
+
return GamsJob(
|
|
918
|
+
self, file_name=model + ".gms", checkpoint=checkpoint, job_name=job_name
|
|
919
|
+
)
|
|
920
|
+
|
|
921
|
+
def add_job_from_testlib(self, model, checkpoint=None, job_name=None):
|
|
922
|
+
"""
|
|
923
|
+
@brief Create GamsJob from model from GAMS Test Library
|
|
924
|
+
@param model model name
|
|
925
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
926
|
+
@param job_name Job name (determined automatically if omitted)
|
|
927
|
+
@return GamsJob instance
|
|
928
|
+
"""
|
|
929
|
+
self.testlib(model)
|
|
930
|
+
return GamsJob(
|
|
931
|
+
self, file_name=model + ".gms", checkpoint=checkpoint, job_name=job_name
|
|
932
|
+
)
|
|
933
|
+
|
|
934
|
+
def add_job_from_apilib(self, model, checkpoint=None, job_name=None):
|
|
935
|
+
"""
|
|
936
|
+
@brief Create GamsJob from model from GAMS API Library
|
|
937
|
+
@param model model name
|
|
938
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
939
|
+
@param job_name Job name (determined automatically if omitted)
|
|
940
|
+
@return GamsJob instance
|
|
941
|
+
"""
|
|
942
|
+
self.apilib(model)
|
|
943
|
+
return GamsJob(
|
|
944
|
+
self, file_name=model + ".gms", checkpoint=checkpoint, job_name=job_name
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
def add_job_from_emplib(self, model, checkpoint=None, job_name=None):
|
|
948
|
+
"""
|
|
949
|
+
@brief Create GamsJob from model from GAMS Extended Math Programming Library
|
|
950
|
+
@param model model name
|
|
951
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
952
|
+
@param job_name Job name (determined automatically if omitted)
|
|
953
|
+
@return GamsJob instance
|
|
954
|
+
"""
|
|
955
|
+
self.emplib(model)
|
|
956
|
+
return GamsJob(
|
|
957
|
+
self, file_name=model + ".gms", checkpoint=checkpoint, job_name=job_name
|
|
958
|
+
)
|
|
959
|
+
|
|
960
|
+
def add_job_from_datalib(self, model, checkpoint=None, job_name=None):
|
|
961
|
+
"""
|
|
962
|
+
@brief Create GamsJob from model from GAMS Data Utilities Library
|
|
963
|
+
@param model model name
|
|
964
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
965
|
+
@param job_name Job name (determined automatically if omitted)
|
|
966
|
+
@return GamsJob instance
|
|
967
|
+
"""
|
|
968
|
+
self.datalib(model)
|
|
969
|
+
return GamsJob(
|
|
970
|
+
self, file_name=model + ".gms", checkpoint=checkpoint, job_name=job_name
|
|
971
|
+
)
|
|
972
|
+
|
|
973
|
+
def add_job_from_finlib(self, model, checkpoint=None, job_name=None):
|
|
974
|
+
"""
|
|
975
|
+
@brief Create GamsJob from model from Practical Financial Optimization Library
|
|
976
|
+
@param model model name
|
|
977
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
978
|
+
@param job_name Job name (determined automatically if omitted)
|
|
979
|
+
@return GamsJob instance
|
|
980
|
+
"""
|
|
981
|
+
self.finlib(model)
|
|
982
|
+
return GamsJob(
|
|
983
|
+
self, file_name=model + ".gms", checkpoint=checkpoint, job_name=job_name
|
|
984
|
+
)
|
|
985
|
+
|
|
986
|
+
def add_job_from_noalib(self, model, checkpoint=None, job_name=None):
|
|
987
|
+
"""
|
|
988
|
+
@brief Create GamsJob from model from GAMS Non-linear Optimization Applications Library
|
|
989
|
+
@param model model name
|
|
990
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
991
|
+
@param job_name Job name (determined automatically if omitted)
|
|
992
|
+
@return GamsJob instance
|
|
993
|
+
"""
|
|
994
|
+
self.noalib(model)
|
|
995
|
+
return GamsJob(
|
|
996
|
+
self, file_name=model + ".gms", checkpoint=checkpoint, job_name=job_name
|
|
997
|
+
)
|
|
998
|
+
|
|
999
|
+
def add_job_from_psoptlib(self, model, checkpoint=None, job_name=None):
|
|
1000
|
+
"""
|
|
1001
|
+
@brief Create GamsJob from model from Power System Optimization Modelling Library
|
|
1002
|
+
@param model model name
|
|
1003
|
+
@param checkpoint GamsCheckpoint to initialize GamsJob from
|
|
1004
|
+
@param job_name Job name (determined automatically if omitted)
|
|
1005
|
+
@return GamsJob instance
|
|
1006
|
+
"""
|
|
1007
|
+
self.psoptlib(model)
|
|
1008
|
+
return GamsJob(
|
|
1009
|
+
self, file_name=model + ".gms", checkpoint=checkpoint, job_name=job_name
|
|
1010
|
+
)
|
|
1011
|
+
|
|
1012
|
+
def add_options(self, gams_options_from=None, opt_file=None):
|
|
1013
|
+
"""
|
|
1014
|
+
@brief Create GamsOptions
|
|
1015
|
+
@param gams_options_from GamsOptions used to initialize the new object
|
|
1016
|
+
@param opt_file Parameter file used to initialize the new object
|
|
1017
|
+
@return GamsOptions instance
|
|
1018
|
+
"""
|
|
1019
|
+
if gams_options_from and opt_file:
|
|
1020
|
+
raise GamsException(
|
|
1021
|
+
"Specify either gams_options_from or opt_file but not both"
|
|
1022
|
+
)
|
|
1023
|
+
return GamsOptions(self, gams_options_from, opt_file)
|
|
1024
|
+
|
|
1025
|
+
def add_checkpoint(self, checkpoint_name=None):
|
|
1026
|
+
"""
|
|
1027
|
+
@brief Create GamsCheckpoint
|
|
1028
|
+
@param checkpoint_name checkpoint_name Identifier of GamsCheckpoint or filename for existing checkpoint (determined automatically if omitted)
|
|
1029
|
+
@return GamsCheckpoint instance
|
|
1030
|
+
"""
|
|
1031
|
+
return GamsCheckpoint(self, checkpoint_name)
|
|
1032
|
+
|
|
1033
|
+
def _job_add(self, job_name=None):
|
|
1034
|
+
if not job_name:
|
|
1035
|
+
self._job_lock.acquire()
|
|
1036
|
+
name = (
|
|
1037
|
+
self.scratch_file_prefix
|
|
1038
|
+
+ self._def_job_name_stem
|
|
1039
|
+
+ str(self._def_job_name_cnt)
|
|
1040
|
+
)
|
|
1041
|
+
while name in self._gams_jobs:
|
|
1042
|
+
self._def_job_name_cnt += 1
|
|
1043
|
+
name = (
|
|
1044
|
+
self.scratch_file_prefix
|
|
1045
|
+
+ self._def_job_name_stem
|
|
1046
|
+
+ (self._def_job_name_cnt)
|
|
1047
|
+
)
|
|
1048
|
+
self._def_job_name_cnt += 1
|
|
1049
|
+
|
|
1050
|
+
self._gams_jobs[name] = self._def_job_name_cnt - 1
|
|
1051
|
+
self._job_lock.release()
|
|
1052
|
+
return name
|
|
1053
|
+
else:
|
|
1054
|
+
self._job_lock.acquire()
|
|
1055
|
+
if job_name in self._gams_jobs:
|
|
1056
|
+
self._job_lock.release()
|
|
1057
|
+
return False
|
|
1058
|
+
else:
|
|
1059
|
+
self._gams_jobs[job_name] = 0
|
|
1060
|
+
self._job_lock.release()
|
|
1061
|
+
return True
|
|
1062
|
+
|
|
1063
|
+
def _database_add(self, database_name=None):
|
|
1064
|
+
if not database_name:
|
|
1065
|
+
self._database_lock.acquire()
|
|
1066
|
+
name = (
|
|
1067
|
+
self.scratch_file_prefix
|
|
1068
|
+
+ self._def_database_name_stem
|
|
1069
|
+
+ str(self._def_database_name_cnt)
|
|
1070
|
+
)
|
|
1071
|
+
while name in self._gams_databases:
|
|
1072
|
+
self._def_database_name_cnt += 1
|
|
1073
|
+
name = (
|
|
1074
|
+
self.scratch_file_prefix
|
|
1075
|
+
+ self._def_database_name_stem
|
|
1076
|
+
+ (self._def_database_name_cnt)
|
|
1077
|
+
)
|
|
1078
|
+
self._def_database_name_cnt += 1
|
|
1079
|
+
|
|
1080
|
+
self._gams_databases[name] = self._def_database_name_cnt - 1
|
|
1081
|
+
self._database_lock.release()
|
|
1082
|
+
return name
|
|
1083
|
+
else:
|
|
1084
|
+
self._database_lock.acquire()
|
|
1085
|
+
if database_name in self._gams_databases:
|
|
1086
|
+
self._database_lock.release()
|
|
1087
|
+
return False
|
|
1088
|
+
else:
|
|
1089
|
+
self._gams_databases[database_name] = 0
|
|
1090
|
+
self._database_lock.release()
|
|
1091
|
+
return True
|
|
1092
|
+
|
|
1093
|
+
def _checkpoint_add(self, checkpoint_name=None):
|
|
1094
|
+
if not checkpoint_name:
|
|
1095
|
+
self._checkpoint_lock.acquire()
|
|
1096
|
+
name = (
|
|
1097
|
+
self.scratch_file_prefix
|
|
1098
|
+
+ self._def_checkpoint_name_stem
|
|
1099
|
+
+ str(self._def_checkpoint_name_cnt)
|
|
1100
|
+
)
|
|
1101
|
+
while name in self._gams_checkpoints:
|
|
1102
|
+
self._def_checkpoint_name_cnt += 1
|
|
1103
|
+
name = (
|
|
1104
|
+
self.scratch_file_prefix
|
|
1105
|
+
+ self._def_checkpoint_name_stem
|
|
1106
|
+
+ (self._def_checkpoint_name_cnt)
|
|
1107
|
+
)
|
|
1108
|
+
self._def_checkpoint_name_cnt += 1
|
|
1109
|
+
|
|
1110
|
+
self._gams_checkpoints[name] = self._def_checkpoint_name_cnt - 1
|
|
1111
|
+
self._checkpoint_lock.release()
|
|
1112
|
+
return name
|
|
1113
|
+
else:
|
|
1114
|
+
self._checkpoint_lock.acquire()
|
|
1115
|
+
if checkpoint_name in self._gams_checkpoints:
|
|
1116
|
+
self._checkpoint_lock.release()
|
|
1117
|
+
return False
|
|
1118
|
+
else:
|
|
1119
|
+
self._gams_checkpoints[checkpoint_name] = 0
|
|
1120
|
+
self._checkpoint_lock.release()
|
|
1121
|
+
return True
|
|
1122
|
+
|
|
1123
|
+
def _modelinstance_add(self, modelinstance_name=None):
|
|
1124
|
+
if not modelinstance_name:
|
|
1125
|
+
self._modelinstance_lock.acquire()
|
|
1126
|
+
name = (
|
|
1127
|
+
self.scratch_file_prefix
|
|
1128
|
+
+ self._def_modelinstance_name_stem
|
|
1129
|
+
+ str(self._def_modelinstance_name_cnt)
|
|
1130
|
+
)
|
|
1131
|
+
while name in self._gams_modelinstances:
|
|
1132
|
+
self._def_modelinstance_name_cnt += 1
|
|
1133
|
+
name = (
|
|
1134
|
+
self.scratch_file_prefix
|
|
1135
|
+
+ self._def_modelinstance_name_stem
|
|
1136
|
+
+ (self._def_modelinstance_name_cnt)
|
|
1137
|
+
)
|
|
1138
|
+
self._def_modelinstance_name_cnt += 1
|
|
1139
|
+
|
|
1140
|
+
self._gams_modelinstances[name] = self._def_modelinstance_name_cnt - 1
|
|
1141
|
+
self._modelinstance_lock.release()
|
|
1142
|
+
return name
|
|
1143
|
+
else:
|
|
1144
|
+
self._modelinstance_lock.acquire()
|
|
1145
|
+
if modelinstance_name in self._gams_modelinstances:
|
|
1146
|
+
self._modelinstance_lock.release()
|
|
1147
|
+
return False
|
|
1148
|
+
else:
|
|
1149
|
+
self._gams_modelinstances[modelinstance_name] = 0
|
|
1150
|
+
self._modelinstance_lock.release()
|
|
1151
|
+
return True
|
|
1152
|
+
|
|
1153
|
+
def _job_delete(self, job_name):
|
|
1154
|
+
self._job_lock.acquire()
|
|
1155
|
+
try:
|
|
1156
|
+
del self._gams_jobs[job_name]
|
|
1157
|
+
return True
|
|
1158
|
+
except KeyError:
|
|
1159
|
+
return False
|
|
1160
|
+
|
|
1161
|
+
def _database_delete(self, database_name):
|
|
1162
|
+
self._database_lock.acquire()
|
|
1163
|
+
try:
|
|
1164
|
+
del self._gams_databases[database_name]
|
|
1165
|
+
return True
|
|
1166
|
+
except KeyError:
|
|
1167
|
+
return False
|
|
1168
|
+
|
|
1169
|
+
def _checkpoint_delete(self, checkpoint_name):
|
|
1170
|
+
self._checkpoint_lock.acquire()
|
|
1171
|
+
try:
|
|
1172
|
+
del self._gams_checkpoints[checkpoint_name]
|
|
1173
|
+
return True
|
|
1174
|
+
except KeyError:
|
|
1175
|
+
return False
|
|
1176
|
+
|
|
1177
|
+
def _modelinstance_delete(self, modelinstance_name):
|
|
1178
|
+
self._modelinstance_lock.acquire()
|
|
1179
|
+
try:
|
|
1180
|
+
del self._gams_modelinstances[modelinstance_name]
|
|
1181
|
+
return True
|
|
1182
|
+
except KeyError:
|
|
1183
|
+
return False
|
|
1184
|
+
|
|
1185
|
+
def _opt_file_extension(self, optfile):
|
|
1186
|
+
if optfile < 2:
|
|
1187
|
+
return "opt"
|
|
1188
|
+
elif optfile < 10:
|
|
1189
|
+
return "op" + str(optfile)
|
|
1190
|
+
elif optfile < 100:
|
|
1191
|
+
return "o" + str(optfile)
|
|
1192
|
+
elif optfile <= 999:
|
|
1193
|
+
return "" + str(optfile)
|
|
1194
|
+
else:
|
|
1195
|
+
raise GamsException(
|
|
1196
|
+
"Index Out of Bounds when writing opt file, must be between 1 and 999, saw "
|
|
1197
|
+
+ str(optfile)
|
|
1198
|
+
)
|