gamspy-base 50.4.1__py3-none-win_amd64.whl → 50.5.0__py3-none-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.
Files changed (43) hide show
  1. gamspy_base/__init__.py +4 -4
  2. gamspy_base/co4cclib64.dll +0 -0
  3. gamspy_base/conopt464.dll +0 -0
  4. gamspy_base/cpxcclib64.dll +0 -0
  5. gamspy_base/cvdcclib64.dll +0 -0
  6. gamspy_base/dctmdclib64.dll +0 -0
  7. gamspy_base/gams.exe +0 -0
  8. gamspy_base/gamscmex.exe +0 -0
  9. gamspy_base/gamsgetkey.exe +0 -0
  10. gamspy_base/gamslice.txt +7 -4
  11. gamspy_base/gamsprobe.exe +0 -0
  12. gamspy_base/gdxcclib64.dll +0 -0
  13. gamspy_base/gdxdiff.exe +0 -0
  14. gamspy_base/gdxdump.exe +0 -0
  15. gamspy_base/gmdcclib64.dll +0 -0
  16. gamspy_base/gmscmpNT.txt +10 -21
  17. gamspy_base/gmscvnnx.exe +0 -0
  18. gamspy_base/gmsgennx.exe +0 -0
  19. gamspy_base/gmssb_nt.cmd +3 -0
  20. gamspy_base/gmssb_nx.exe +0 -0
  21. gamspy_base/gmszlib164.dll +0 -0
  22. gamspy_base/gsscclib64.dll +0 -0
  23. gamspy_base/guccclib64.dll +0 -0
  24. gamspy_base/joatdclib64.dll +0 -0
  25. gamspy_base/libcrypto-3-x64.dll +0 -0
  26. gamspy_base/optdclib64.dll +0 -0
  27. gamspy_base/optsbb.def +94 -0
  28. gamspy_base/path52.dll +0 -0
  29. gamspy_base/ptccclib64.dll +0 -0
  30. gamspy_base/version.py +1 -1
  31. {gamspy_base-50.4.1.dist-info → gamspy_base-50.5.0.dist-info}/METADATA +1 -1
  32. gamspy_base-50.5.0.dist-info/RECORD +57 -0
  33. gamspy_base/gmske_nx.py +0 -933
  34. gamspy_base/gurobi120.dll +0 -0
  35. gamspy_base/ipocclib64.dll +0 -0
  36. gamspy_base/ipopt.dll +0 -0
  37. gamspy_base/mkl_gams.dll +0 -0
  38. gamspy_base/optipopt.def +0 -521
  39. gamspy_base/pthreads.dll +0 -0
  40. gamspy_base/shtcclib64.dll +0 -0
  41. gamspy_base-50.4.1.dist-info/RECORD +0 -62
  42. {gamspy_base-50.4.1.dist-info → gamspy_base-50.5.0.dist-info}/WHEEL +0 -0
  43. {gamspy_base-50.4.1.dist-info → gamspy_base-50.5.0.dist-info}/top_level.txt +0 -0
gamspy_base/gmske_nx.py DELETED
@@ -1,933 +0,0 @@
1
- #
2
- #MIT License
3
- #
4
- #Copyright (c) 2020 NEOS-Server
5
- #
6
- #Permission is hereby granted, free of charge, to any person obtaining a copy
7
- #of this software and associated documentation files (the "Software"), to deal
8
- #in the Software without restriction, including without limitation the rights
9
- #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- #copies of the Software, and to permit persons to whom the Software is
11
- #furnished to do so, subject to the following conditions:
12
- #
13
- #The above copyright notice and this permission notice shall be included in all
14
- #copies or substantial portions of the Software.
15
- #
16
- #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
- #SOFTWARE.
23
- #
24
-
25
- import os
26
- import linecache
27
- try:
28
- import zipextimporter
29
- except:
30
- pass
31
- import re
32
- import xmlrpc.client
33
- import sys
34
- import time
35
- import socket
36
- import base64
37
- import gzip
38
- import io
39
- import xml.dom.minidom
40
- import string
41
- import pathlib
42
- import ssl
43
- import certifi
44
-
45
- solverMap = {}
46
- solverMap[ 1] = 'cbc' # lp
47
- solverMap[ 2] = 'cbc' # mip
48
- solverMap[ 3] = 'cbc' # rmip
49
- solverMap[ 4] = 'ipopt' # nlp
50
- solverMap[ 5] = 'path' # mcp
51
- solverMap[ 6] = 'nlpec' # mpec
52
- solverMap[ 7] = 'nlpec' # rmpec
53
- solverMap[ 8] = 'path' # cns
54
- solverMap[ 9] = 'ipopt' # dnlp
55
- solverMap[10] = 'ipopt' # rminlp
56
- solverMap[11] = 'shot' # minlp
57
- solverMap[12] = 'ipopt' # qcp
58
- solverMap[13] = 'shot' # miqcp
59
- solverMap[14] = 'ipopt' # rmiqcp
60
- solverMap[15] = 'jams' # emp
61
-
62
- class KestrelException(Exception):
63
- def __init__(self,msg):
64
- Exception.__init__(self)
65
- self.msg = msg
66
-
67
- def __str__(self):
68
- return repr(self.msg)
69
-
70
- class KestrelSolverException(KestrelException):
71
- def __init__(self,msg,solverlist):
72
- KestrelException.__init__(self,msg)
73
- self.msg += "\nCreate options file and include the following lines:\n\tkestrel_solver <solvername>\n"
74
- self.msg += "\tneos_server <hostname>[:<port>]\n\n"
75
- self.msg += "The following solvers are available on NEOS:\n"
76
- for solver in solverlist:
77
- self.msg += solver.upper() +"\n"
78
-
79
- class KestrelGamsClient:
80
- def __init__(self,argv):
81
- self.argv=argv
82
- self.serverProtocol="https"
83
- self.serverHost="neos-server.org"
84
- self.serverPort=3333
85
- self.solverName=None
86
- self.jobNumber=None
87
- self.password=None
88
- self.priority="long"
89
- self.socket_timeout=0
90
- self.authUsername=None
91
- self.authUserPassword=None
92
-
93
- # action-parameter is outdated
94
- '''
95
- if len(self.argv) >= 3:
96
- self.cntrfile = self.argv[2]
97
- self.action = self.argv[1].lower()
98
- if self.action not in ['kill','retrieve','submit','solve']:
99
- self.Usage()
100
- else:
101
- self.Usage()
102
- '''
103
-
104
- if len(self.argv) >= 2:
105
- self.cntrfile = self.argv[1]
106
- self.action = 'solve'
107
- else:
108
- self.Usage()
109
-
110
- def Usage(self):
111
- sys.stderr.write("\n--- Kestrel fatal error: usage\n")
112
- sys.stderr.write(" gamske_ux.out <cntrfile>\n")
113
- sys.exit(1)
114
-
115
- def Fatal(self, str):
116
- sys.stderr.write("\n--- Kestrel fatal error: %s\n\n" % str)
117
- sys.exit(1)
118
-
119
- def Error(self, str):
120
- if self.logopt in [1,3,4]:
121
- # Write the message to standard output
122
- sys.stdout.write("\n--- Kestrel error: %s\n\n" % str)
123
-
124
- if self.logopt in [2,4]:
125
- # Append the error message to the logfile indicated
126
- try:
127
- f = open(self.logfilename,'a')
128
- f.write("\n--- Kestrel error: %s\n\n" % str)
129
- f.close()
130
- except IOError as e:
131
- self.Fatal("Could not append to log file %s" % self.logfilename)
132
-
133
- try:
134
- f = open(self.statfilename,'a')
135
- f.write("=1\n\n--- Kestrel error: %s\n\n=2\n" % str)
136
- f.close()
137
- except IOError as e:
138
- self.Fatal("Could not append to status file %s\n" % self.statfilename)
139
-
140
- sys.exit(0)
141
-
142
- def getDefaultEmail(self):
143
- if 'NEOS_EMAIL' in os.environ:
144
- return os.environ['NEOS_EMAIL']
145
- return None
146
-
147
- def parseControlFile(self):
148
- """
149
- This function does the following with the cntr file
150
- line 13:
151
- extract isAscii, useOptions
152
-
153
- line 18:
154
- matrix file, save and change to gamsmatr.scr
155
-
156
- line 19:
157
- instruction file; save and change to gamsinst.scr
158
-
159
- line 20:
160
- set options file to 'kestrel.opt'
161
-
162
- line 21:
163
- status file; save and change to gamsstat.scr
164
-
165
- line 22:
166
- solution file; save and change to gamssolu.scr
167
-
168
- line 23:
169
- log file; save and remove absolute path
170
-
171
- line 24:
172
- dictionary file; save and change to gamsdict.scr
173
-
174
- line 25:
175
- set to '2' to write to log file
176
-
177
- line 28-30:
178
- set working,system,scratch directories to '.'
179
-
180
- line 33,34,35:
181
- remove license
182
-
183
- line 37:
184
- set parameter file
185
-
186
- line 38:
187
- read #models #solvers
188
- ignore next #models + 2*#solvers with (SOLVER # # 0 ..) +
189
- 3*#solvers with (SOLVER # # 1 ...) lines
190
-
191
- next two lines are more license (remove them)
192
-
193
- set directories of remaining paths to current directory
194
- (.scr, .so, sbbinfo.)
195
-
196
- change the scratch file extension to 'scr'
197
- """
198
-
199
- try:
200
- f = open(self.cntrfile,'r')
201
- lines = f.readlines()
202
- f.close()
203
- except IOError as e:
204
- self.Fatal("Could not open control file %s" % self.cntrfile)
205
-
206
- # extract control version number
207
- self.cntver = 0
208
- m = re.match(r'(\d+)',lines[0])
209
- if m and m.groups():
210
- self.cntver = int(m.groups()[0])
211
-
212
- self.modeltype = int(lines[1].split()[0])
213
-
214
- #if self.cntver != 41 and self.cntver != 42:
215
- # self.Fatal("GAMS 22.x required")
216
-
217
- if self.cntver not in [41, 42, 44, 46, 47, 48, 49, 50, 51, 52, 53]:
218
- self.Fatal("GAMS cntr-file version 41, 42, 44, 46, 47, 48, 49, 50, 51, 52, 53 required")
219
-
220
- # extract isAscii, useOptions
221
- m = re.match(r'(\d+)\s+(\d+)',lines[12])
222
- if m and m.groups():
223
- self.isAscii=m.groups()[0]
224
- self.useOptions = int(m.groups()[1])
225
- else:
226
- self.Fatal("Line 13 of the control file is incorrect")
227
-
228
- # is this is an MPSGE model?
229
- self.isMPSGE = int(lines[15].split()[0])
230
-
231
- # get the matrix and instruction scratch files and patch
232
- self.matrfilename = lines[17].strip()
233
- lines[17] = "gamsmatr.scr\n"
234
-
235
- self.instfilename = lines[18].strip()
236
- lines[18] = "gamsinst.scr\n"
237
-
238
- # patch option file name; always use kestrel.opt
239
- self.optfilename = ""
240
- m = re.match(r'(.*)kestrel.*\.(.*)',lines[19])
241
- if m and m.groups():
242
- self.optfilename = m.groups()[0] + "kestrel." + m.groups()[1]
243
- lines[19] = "kestrel.opt\n"
244
-
245
- # get the status and solution scratch files and patch
246
- self.statfilename = lines[20].strip()
247
- lines[20] = "gamsstat.scr\n"
248
-
249
- self.solufilename = lines[21].strip()
250
- lines[21] = "gamssolu.scr\n"
251
-
252
- # get the log filename and patch
253
- self.logfilename = lines[22].strip()
254
- lines[22] = "gamslog.scr\n"
255
-
256
- # get the dictionary filename and patch
257
- self.dictfilename = lines[23].strip()
258
- lines[23] = "gamsdict.scr\n"
259
-
260
- # get the logfile option, then make output written to logfile
261
- m = re.match(r'(\d+)',lines[24])
262
- if m and m.groups():
263
- self.logopt = int(m.groups()[0])
264
- lines[24]="2\n"
265
-
266
- # set working, system, and scratch directories
267
- self.scrdir = lines[29].strip()
268
- lines[27] = lines[28] = lines[29] = '.\n'
269
-
270
- # remove first part of license
271
- lines[32] = lines[33] = lines[34] = "\n"
272
-
273
- # patch parameter file
274
- lines[36] = "gmsprmun.scr"
275
-
276
- # downgrade the cntr-file version 53 to 52
277
- if self.cntver == 53:
278
- lines[0] = "52\n"
279
- # remove seventh and eigth license line, license gets replaced anyway
280
- del lines[-18]
281
- del lines[-18]
282
- self.cntver = 52
283
-
284
- # downgrade the cntr-file version 52 to 51
285
- if self.cntver == 52:
286
- # We do not yet handle models with more than INT_MAX NNZ in Kestrel
287
- lines[0] = "51\n"
288
- # remove final line of CF (u+15, rvec[ 28] rvec[ 29]
289
- lines = lines[:-1]
290
- self.cntver = 51
291
-
292
- # downgrade the cntr-file version 51 to 50
293
- if self.cntver == 51:
294
- # remove last number (savepoint) of this line
295
- lines[13] = lines[13].rpartition(' ')[0] + "\n"
296
- # 51 -> 50
297
- lines[0] = "50\n"
298
- self.cntver = 50
299
-
300
- # downgrade the cntr-file version 50 to 49 // No change required since this was in the license section which does not get copied
301
- if self.cntver == 50:
302
- # 50 -> 49
303
- lines[0] = "49\n"
304
- self.cntver = 49
305
-
306
- # downgrade the cntr-file version 49 to 48 // No change required since this was in the license section which does not get copied
307
- if self.cntver == 49:
308
- # 49 -> 48
309
- lines[0] = "48\n"
310
- self.cntver = 48
311
-
312
- # downgrade the cntr-file version 48 to 47
313
- if self.cntver == 48:
314
- # 48 -> 47
315
- lines[0] = "47\n"
316
- self.cntver = 47
317
- # remove last two numbers of this line
318
- lines[13] = lines[13].rpartition(' ')[0] + "\n"
319
- lines[13] = lines[13].rpartition(' ')[0] + "\n"
320
-
321
- # downgrade the cntr-file version 47 to 46
322
- if self.cntver == 47:
323
- # 47 -> 46
324
- lines[0] = "46\n"
325
- self.cntver = 46
326
- # remove line with file name
327
- lines = lines[:-2]
328
- lines.append("")
329
-
330
- # downgrade the cntr-file version 46 to 42
331
- # no support for threads, external funclib and guss
332
- if self.cntver == 46:
333
- # 46 -> 42
334
- lines[0] = "42\n"
335
-
336
- # remove last number of this line
337
- lines[2] = lines[2].rpartition(' ')[0] + "\n"
338
-
339
- # remove threads-option
340
- lines[13] = lines[13].rpartition(' ')[0] + "\n"
341
-
342
- # remove last two lines
343
- lines = lines[:-2]
344
-
345
- # treat the cntr-file now like a version 42 one
346
- self.cntver = 42
347
-
348
- # downgrade the cntr-file version 44 to 42
349
- elif self.cntver == 44:
350
- # 44 -> 42
351
- lines[0] = "42\n"
352
-
353
- # remove threads-option
354
- lines[13] = lines[13].rpartition(' ')[0] + "\n"
355
-
356
- # remove last line
357
- lines = lines[:-1]
358
-
359
- # treat the cntr-file now like a version 42 one
360
- self.cntver = 42
361
-
362
- # ignore solver section and patch rest based on version number
363
- if self.cntver == 41:
364
- # remove second part of license
365
- lines[-11] = lines[-10] = "\n"
366
-
367
- # make everything in local directory
368
- lines[-9] = 'model.scr\n'
369
- lines[-4] = 'model.so\n'
370
- lines[-3] = 'sbbinfo.scr\n'
371
- lines[-2] = 'gamscntr.scr\n'
372
- lines[-1] = './\n'
373
-
374
- # set scratch file extension
375
- self.scrext = "scr"
376
-
377
- # get the entire control file name
378
- self.cntr = "".join(lines[:37]) + "".join(lines[-11:])
379
-
380
- elif self.cntver == 42:
381
- # remove second part of license
382
- lines[-13] = lines[-12] = "\n"
383
-
384
- # make everything in local directory
385
- lines[-11] = 'model.scr\n'
386
- lines[-6] = 'model.so\n'
387
- lines[-5] = 'sbbinfo.scr\n'
388
- lines[-4] = 'gamscntr.scr\n'
389
- lines[-3] = './\n'
390
-
391
- # patch scratch file extension
392
- self.scrext = lines[-2].strip()
393
- lines[-2] = 'scr\n'
394
-
395
- # get the entire control file name
396
- self.cntr = "".join(lines[:37]) + "".join(lines[-13:])
397
-
398
- def writeErrorOutputFiles(self):
399
- """
400
- This writes solution and status files returned when an error occurs.
401
- """
402
-
403
- try:
404
- f = open(self.statfilename,"w")
405
- f.write("""=0 Kestrel\n""")
406
- f.close()
407
- except IOError as e:
408
- self.Error("Could not initialize status file %s\n" % self.statfilename)
409
-
410
- try:
411
- f = open(self.solufilename,"w")
412
- f.write(""" 1 6.0000000000000000E+00
413
- 2 1.3000000000000000E+01
414
- 3 0.0000000000000000E+00
415
- 4 0.0
416
- 5 0.0000000000000000E+00
417
- 6 0.0
418
- 7 0.0
419
- 8 0.0
420
- 0 0.0\n""")
421
- f.close()
422
-
423
- except IOError as e:
424
- self.Error("Could not open solution file %s\n" % self.solufilename)
425
-
426
- def writeLog(self, text):
427
- if self.logopt in [1,3,4]:
428
- sys.stdout.write(text)
429
- if self.logopt in [2,4]:
430
- try:
431
- f = open(self.logfilename,'a')
432
- f.write(text)
433
- f.close()
434
- except IOError as e:
435
- self.Fatal("Could not append to log file %s" % self.logfilename)
436
-
437
- def parseOptionsFile(self):
438
- if (self.useOptions == 0):
439
- # raise KestrelSolverException("No options file indicated\n",self.kestrelGamsSolvers)
440
- self.solverName = solverMap[self.modeltype]
441
- elif os.access(self.optfilename,os.R_OK):
442
- optfile = open(self.optfilename,'r')
443
- self.writeLog("Reading parameter(s) from \"" + self.optfilename + "\"\n")
444
- for line in optfile:
445
- m = re.match(r'neos_user_password[\s=]+(\S+)',line)
446
- if m:
447
- self.writeLog(">> neos_user_password ******")
448
- else:
449
- self.writeLog(">> " + line)
450
-
451
- m = re.match(r'kestrel_priority[\s=]+(\S+)',line)
452
- if m:
453
- value = m.groups()[0]
454
- if value.lower()=="short":
455
- self.priority = "short"
456
-
457
- m = re.match(r'kestrel_solver[\s=]+(\S+)',line)
458
- if m:
459
- self.solverName = m.groups()[0]
460
-
461
- m = re.match(r'neos_server[\s=]+(\S+)://(\S+):(\d+)',line)
462
- if m:
463
- self.serverProtocol = m.groups()[0]
464
- self.serverHost = m.groups()[1]
465
- self.serverPort = m.groups()[2]
466
-
467
- m = re.match(r'neos_username[\s=]+(\S+)',line)
468
- if m:
469
- self.authUsername = m.groups()[0]
470
-
471
- m = re.match(r'neos_user_password[\s=]+(\S+)',line)
472
- if m:
473
- self.authUserPassword = m.groups()[0]
474
-
475
- elif re.match(r'neos_server[\s=]+(\S+)://(\S+)',line):
476
- m = re.match(r'neos_server[\s=]+(\S+)://(\S+)',line)
477
- self.serverProtocol = m.groups()[0]
478
- self.serverHost = m.groups()[1]
479
-
480
- elif re.match(r'neos_server[\s=]+(\S+):(\d+)',line):
481
- m = re.match(r'neos_server[\s=]+(\S+):(\d+)',line)
482
- self.serverHost = m.groups()[0]
483
- self.serverPort = m.groups()[1]
484
-
485
- else:
486
- m = re.match(r'neos_server[\s=]+(\S+)',line)
487
- if m:
488
- self.serverHost = m.groups()[0]
489
-
490
- m = re.match(r'kestrel_(job|jobnumber|jobNumber)[\s=]+(\d+)', line)
491
- if m:
492
- self.jobNumber=int(m.groups()[1])
493
-
494
- m = re.match(r'kestrel_(pass|password)[\s=]+(\S+)', line)
495
- if m:
496
- self.password = m.groups()[1]
497
-
498
- m = re.match(r'socket_timeout[\s=]+(\d+)',line)
499
- if m:
500
- self.socket_timeout = m.groups()[0]
501
- socket.setdefaulttimeout(float(self.socket_timeout))
502
-
503
- optfile.close()
504
- self.writeLog("\nFinished reading from \"" + self.optfilename + "\"\n")
505
- else:
506
- raise KestrelSolverException("Could not read options file %s\n" % self.optfilename,self.kestrelGamsSolvers)
507
-
508
- def connectServer(self):
509
- if self.logopt in [1,3,4]:
510
- sys.stdout.write("Connecting to: %s://%s:%s\n" % (self.serverProtocol,self.serverHost,self.serverPort))
511
- if self.logopt in [2,4]:
512
- # Append the message to the logfile indicated
513
- try:
514
- f = open(kestrel.logfilename,'a')
515
- f.write("Connecting to: %s://%s:%s\n" % (self.serverProtocol,self.serverHost,self.serverPort))
516
- f.close()
517
- except IOError as e:
518
- self.Fatal("Could not append to log file %s" % self.logfilename)
519
- ssl_context = ssl.create_default_context()
520
- if ssl_context.minimum_version < ssl.TLSVersion.TLSv1_2:
521
- ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
522
- if sys.platform == "win32":
523
- ssl_context.load_verify_locations(certifi.where())
524
- self.neos = xmlrpc.client.Server("%s://%s:%s" % (self.serverProtocol,self.serverHost,self.serverPort), context=ssl_context)
525
-
526
- reply = self.neos.ping()
527
- if reply.find('alive') < 0:
528
- raise KestrelException("Unable to contact NEOS at https://%s:%d" % \
529
- (self.host, self.port))
530
-
531
- def obtainSolvers(self):
532
- # Form a list of all kestrel-gams solver available on NEOS
533
- allKestrelSolvers = self.neos.listSolversInCategory("kestrel")
534
- self.kestrelGamsSolvers = []
535
- for s in allKestrelSolvers:
536
- i = s.find(':GAMS')
537
- if i > 0:
538
- self.kestrelGamsSolvers.append(s[0:i])
539
-
540
- def checkOptionsFile(self):
541
- if self.solverName and (self.solverName.lower() not in [s.lower() for s in self.kestrelGamsSolvers]):
542
- errmsg = "Solver '%s' not available on NEOS.\n" % self.solverName
543
- raise KestrelSolverException(errmsg, self.kestrelGamsSolvers)
544
-
545
- def formSubmission(self):
546
- if not self.solverName:
547
- raise KestrelSolverException("No 'kestrel_solver' option found in option file\n",self.kestrelGamsSolvers)
548
-
549
- # Get the matrix, dictionary and instruction file
550
- gamsFiles = {}
551
- gamsFiles['cntr'] = io.BytesIO(self.cntr.encode())
552
-
553
- # Need to read empinfo.dat or empinfo.scr
554
- empInfoFileName = os.path.join(self.scrdir, "empinfo." + self.scrext)
555
- if os.access(empInfoFileName,os.R_OK):
556
- gamsFiles['empinfo'] = io.BytesIO()
557
- f = open(empInfoFileName,"rb")
558
- zipper = gzip.GzipFile(mode='wb',fileobj=gamsFiles['empinfo'])
559
- zipper.write(f.read())
560
- zipper.close()
561
- f.close()
562
-
563
- # Need to read scenarios
564
- scenDictName = os.path.join(self.scrdir, "scenario_dict." + self.scrext)
565
- if os.access(scenDictName,os.R_OK):
566
- gamsFiles['scenario'] = io.BytesIO()
567
- f = open(scenDictName,"rb")
568
- zipper = gzip.GzipFile(mode='wb',fileobj=gamsFiles['scenario'])
569
- zipper.write(f.read())
570
- zipper.close()
571
- f.close()
572
-
573
- if os.access(self.matrfilename,os.R_OK):
574
- gamsFiles['matr'] = io.BytesIO()
575
- f = open(self.matrfilename,"rb")
576
- zipper = gzip.GzipFile(mode='wb',fileobj=gamsFiles['matr'])
577
- zipper.write(f.read())
578
- zipper.close()
579
- f.close()
580
-
581
- if os.access(self.instfilename,os.R_OK):
582
- gamsFiles['inst'] = io.BytesIO()
583
- f = open(self.instfilename,"rb")
584
- zipper = gzip.GzipFile(mode='wb',fileobj=gamsFiles['inst'])
585
- zipper.write(f.read())
586
- zipper.close()
587
- f.close()
588
-
589
- if os.access(self.dictfilename,os.R_OK):
590
- gamsFiles['dict'] = io.BytesIO()
591
- f = open(self.dictfilename,"rb")
592
- zipper = gzip.GzipFile(mode='wb',fileobj=gamsFiles['dict'])
593
- zipper.write(f.read())
594
- zipper.close()
595
- f.close()
596
-
597
- if self.isMPSGE != 0 and self.modeltype == 5 and os.access(os.path.join(self.scrdir,'gedata.' + self.scrext),os.R_OK): # MCP might be an MPSGE model
598
- gamsFiles['cge'] = io.BytesIO()
599
- f = open(os.path.join(self.scrdir,'gedata.' + self.scrext),"rb")
600
- zipper = gzip.GzipFile(mode='wb',fileobj=gamsFiles['cge'])
601
- s=f.read()
602
- end = s.find(b"gamsdict.")
603
- if end != -1:
604
- start = end
605
- while ord(s[end]) != 32: #whitespace
606
- end = end+1
607
- while ord(s[start]) != 0:
608
- start = start-1
609
- orgStr = s[start+1:end]
610
- replStr = b"./gamsdict.scr" + b" "*(len(orgStr) - len("./gamsdict.scr"))
611
- s = s.replace(orgStr, replStr)
612
- zipper.write(s)
613
- zipper.close()
614
- f.close()
615
-
616
- self.xml = """
617
- <document>
618
- <category>kestrel</category>
619
- <solver>%s</solver>
620
- <inputType>GAMS</inputType>
621
- <priority>%s</priority>
622
- """ % (self.solverName,self.priority)
623
-
624
- for key in list(gamsFiles.keys()):
625
- self.xml += "<%s><base64>%s</base64></%s>\n" % (key,base64.b64encode(gamsFiles[key].getvalue()).decode(),key)
626
- gamsFiles[key].close()
627
-
628
- # Remove 'kestrel', 'neos' and 'socket_timeout' options from options file; they are not needed
629
- email = None
630
- xpressemail = None
631
- runningtime = None
632
- self.xml += "<options><![CDATA["
633
- if self.useOptions:
634
- with open(self.optfilename) as fp:
635
- for line in fp.readlines():
636
- if not re.match(r'kestrel|neos_server|neos_username|neos_user_password|email|xpressemail|runtime|socket_timeout',line):
637
- self.xml += line
638
- elif re.match(r'email',line):
639
- email = line.rsplit()[1]
640
- elif re.match(r'xpressemail',line):
641
- xpressemail = line.rsplit()[1]
642
- elif re.match(r'runtime',line):
643
- runningtime = line.rsplit()[1]
644
- self.xml += "]]></options>\n"
645
-
646
- if not email:
647
- email = self.getDefaultEmail()
648
- if not email:
649
- self.Error("No email address provided. Either specify it in an option file or set environment variable NEOS_EMAIL (e.g. via gamsconfig.yaml).")
650
- self.xml += "<email>"
651
- self.xml += email
652
- self.xml += "</email>\n"
653
-
654
- if xpressemail:
655
- self.xml += "<xpressemail>"
656
- self.xml += xpressemail
657
- self.xml += "</xpressemail>\n"
658
-
659
- if runningtime:
660
- self.xml += "<priority>"
661
- self.xml += runningtime
662
- self.xml += "</priority>"
663
-
664
- self.xml += "</document>"
665
-
666
- def submit(self):
667
- user = "%s on %s" % (os.getenv('LOGNAME'),
668
- socket.getfqdn(socket.gethostname()))
669
- if self.authUsername is None or self.authUserPassword is None:
670
- if self.authUsername: self.writeLog("\nWarning: 'neos_username' was specified, but not 'neos_user_password'")
671
- if self.authUserPassword: self.writeLog("\nWarning: 'neos_user_password' was specified, but not 'neos_username'")
672
- (self.jobNumber,self.password) = \
673
- self.neos.submitJob(self.xml,user,"kestrel")
674
- else:
675
- (self.jobNumber,self.password) = \
676
- self.neos.authenticatedSubmitJob(self.xml,self.authUsername,self.authUserPassword,"kestrel")
677
- if self.jobNumber==0:
678
- raise KestrelException(self.password)
679
-
680
- if self.logopt in [1,3,4]:
681
- # Send the output to the screen
682
- sys.stdout.write("\nNEOS job#=%d, pass=%s\n\n" % (self.jobNumber,self.password))
683
- sys.stdout.write("Check the following URL for progress report :\n")
684
- #sys.stdout.write("http://www-neos.mcs.anl.gov/cgi-bin/nph-neos-solver.cgi?admin=results&jobnumber=%d&pass=%s\n\n" % (self.jobNumber,self.password))
685
- sys.stdout.write("%s://%s/neos/cgi-bin/nph-neos-solver.cgi?admin=results&jobnumber=%d&pass=%s\n\n" % (self.serverProtocol,self.serverHost,self.jobNumber,self.password))
686
- if self.logopt in [2,4]:
687
- # Append the error message to the logfile indicated
688
- try:
689
- f = open(self.logfilename,'a')
690
- f.write("\nNEOS job#=%d, pass=%s\n\n" % (self.jobNumber,self.password))
691
- f.write("Check the following URL for progress report :\n")
692
- f.write("%s://%s/neos/cgi-bin/nph-neos-solver.cgi?admin=results&jobnumber=%d&pass=%s\n\n" % (self.serverProtocol,self.serverHost,self.jobNumber,self.password))
693
- f.close()
694
- except IOError as e:
695
- self.Error("Could not append to log file %s" % self.logfilename)
696
-
697
- try:
698
- f = open(self.statfilename,'a')
699
- f.write("=1\n\n")
700
- f.write("\nNEOS job#=%d, pass=%s\n\n" % (self.jobNumber,self.password))
701
- f.write("Check the following URL for progress report :\n")
702
- f.write("%s://%s/neos/cgi-bin/nph-neos-solver.cgi?admin=results&jobnumber=%d&pass=%s\n\n" % (self.serverProtocol,self.serverHost,self.jobNumber,self.password))
703
- f.write("=2\n")
704
- f.close()
705
- except IOError as e:
706
- self.Error("Could not append to status file %s\n" % self.statfilename)
707
-
708
- def getText(self,node):
709
- """
710
- Returns the text from the node of an xml document
711
- """
712
- s = ""
713
- if isinstance(node,str):
714
- return node
715
- if isinstance(node.nodeValue,str):
716
- return node.data
717
- elif node.hasChildNodes():
718
- for n in node.childNodes:
719
- s += self.getText(n)
720
- return s
721
-
722
- def parseSolution(self,xmlstring):
723
- doc = xml.dom.minidom.parseString(xmlstring)
724
- for tag in ['allsolutions', 'scenrep']:
725
- xmltag = tag[:4]
726
- node = doc.getElementsByTagName(xmltag)
727
- if node and len(node):
728
- try:
729
- f = open(os.path.join(self.scrdir, f"{tag}.{self.scrext}"), 'wb')
730
- f.write(bytes.fromhex(self.getText(node[0])))
731
- f.close()
732
- except IOError as e:
733
- self.Error("Could not write file %s.%s\n" % (tag, self.scrext))
734
- node = doc.getElementsByTagName('solu')
735
- if node and len(node):
736
- try:
737
- f = open(self.solufilename,'w')
738
- f.write(self.getText(node[0]))
739
- f.close()
740
- except IOError as e:
741
- self.Error("Could not write solution file %s\n" % self.solufilename)
742
-
743
- node = doc.getElementsByTagName('stat')
744
- if node and len(node):
745
- try:
746
- f = open(self.statfilename,'w',errors='replace')
747
- f.write(self.getText(node[0]))
748
- f.close()
749
- except IOError as e:
750
- self.Error("Could not write status file %s\n" % self.statfilename)
751
-
752
- node = doc.getElementsByTagName('log')
753
- if node and len(node):
754
- if self.logopt in [1,3,4]:
755
- # Send the output to the screen
756
- encoding = sys.stdout.encoding
757
- encoded_text = self.getText(node[0]).encode(encoding,errors='replace').decode(encoding)
758
- sys.stdout.write(encoded_text)
759
- if self.logopt in [2,4]:
760
- # Append the error message to the logfile indicated
761
- try:
762
- f = open(self.logfilename,'a',errors='replace')
763
- f.write(self.getText(node[0]))
764
- f.close()
765
- except IOError as e:
766
- self.Error("Could not append log file %s\n" % self.logfilename)
767
-
768
- doc.unlink()
769
-
770
- def getResults(self):
771
- offset = 0
772
- status = self.neos.getJobStatus(self.jobNumber,self.password)
773
- try:
774
- while (status == "Waiting" or status=="Running"):
775
- (results,offset) = self.neos.getIntermediateResults(self.jobNumber, self.password,offset)
776
- if isinstance(results,xmlrpc.client.Binary):
777
- results = results.data.decode()
778
- if results and len(results):
779
-
780
- if self.logopt in [1,3,4]:
781
- # Send the output to the screen
782
- sys.stdout.write(results)
783
- if self.logopt in [2,4]:
784
- # Append the error message to the logfile indicated
785
- try:
786
- f = open(self.logfilename,'a')
787
- f.write(results)
788
- f.close()
789
- except IOError as e:
790
- self.Error("Could not append to log file %s" % self.logfilename)
791
-
792
- try:
793
- f = open(self.statfilename,'a')
794
- f.write("=1\n\n")
795
- f.write(results)
796
- f.write("=2\n")
797
- f.close()
798
- except IOError as e:
799
- self.Error("Could not append to status file %s\n" % self.statfilename)
800
- status = self.neos.getJobStatus(self.jobNumber,self.password)
801
- time.sleep(5)
802
-
803
- except KeyboardInterrupt as e:
804
- msg = '''Keyboard Interrupt\n\
805
- Job is still running on remote machine\n\
806
- To retrieve results, run GAMS using solver 'kestrel' with option file:\n\
807
- kestrel_job %d\n\
808
- kestrel_pass %s\n\n\
809
- To stop job, run GAMS using solver 'kestrelkil' with above option file\n\
810
- ''' % (self.jobNumber, self.password)
811
- self.Error(msg)
812
-
813
- resultsXML = self.neos.getFinalResults(self.jobNumber,self.password)
814
- if isinstance(resultsXML,xmlrpc.client.Binary):
815
- resultsXML = resultsXML.data
816
- self.parseSolution(resultsXML)
817
-
818
- if __name__=="__main__":
819
- # print 'in gmske_ux.out'
820
- # Initialization phase
821
-
822
- try:
823
- kestrel = KestrelGamsClient(sys.argv)
824
- kestrel.parseControlFile()
825
- try:
826
- f = open(os.path.join(pathlib.Path(__file__).parent.absolute(),'gamsstmp.txt'),'r')
827
- auditLine = f.readline()
828
- f.close()
829
- kestrel.writeLog('NEOS Kestrel ' + auditLine)
830
- except:
831
- pass
832
- kestrel.writeLog('\nFor terms of use please inspect https://neos-server.org/neos/termofuse.html\n\n')
833
- kestrel.writeErrorOutputFiles()
834
- kestrel.parseOptionsFile()
835
- kestrel.connectServer()
836
- kestrel.obtainSolvers()
837
- except KestrelException as e:
838
- kestrel.Error(e.msg)
839
-
840
- if kestrel.action=="solve":
841
- # Solve with job number and password retrieves the results
842
- # Otherwise we obtain them from the submission
843
-
844
- try:
845
- kestrel.parseOptionsFile()
846
- kestrel.writeLog("NEOS Solver: %s\n" % kestrel.solverName)
847
- if (not kestrel.jobNumber) or (not kestrel.password):
848
- kestrel.checkOptionsFile()
849
- kestrel.formSubmission()
850
- kestrel.submit()
851
- kestrel.getResults()
852
- except KestrelException as e:
853
- kestrel.Error(e.msg)
854
-
855
- elif kestrel.action=="submit":
856
- try:
857
- kestrel.parseOptionsFile()
858
- kestrel.checkOptionsFile()
859
- kestrel.formSubmission()
860
- kestrel.submit()
861
-
862
- fname = os.path.join(kestrel.scrdir, "kestrel." + kestrel.scrext)
863
- try:
864
- f = open(fname,'a')
865
- f.write("%d %s\n" % (kestrel.jobNumber, kestrel.password))
866
- f.close()
867
- except IOError as e:
868
- kestrel.Error("Could not append to submission file %s\n" % fname)
869
-
870
- except KestrelException as e:
871
- kestrel.Error(e.msg)
872
-
873
- elif kestrel.action=="retrieve":
874
- fname = os.path.join(kestrel.scrdir, "kestrel." + kestrel.scrext)
875
-
876
- try:
877
- f = open(fname,'r')
878
- except IOError as e:
879
- kestrel.Error("Could not open submission file %s\n" % fname)
880
-
881
- m = re.match(r'(\d+) ([a-zA-Z]+)',f.readline())
882
- if m:
883
- kestrel.jobNumber = int(m.groups()[0])
884
- kestrel.password = m.groups()[1]
885
- rest = f.read()
886
- f.close()
887
-
888
- if kestrel.jobNumber and kestrel.password:
889
- try:
890
- kestrel.getResults()
891
- except KestrelException as e:
892
- kestrel.Error(e.msg)
893
- else:
894
- kestrel.Error( "Corrupt submission file %s\n" % fname)
895
-
896
- if (rest):
897
- try:
898
- f = open(fname,'w')
899
- f.write(rest);
900
- f.close()
901
- except IOError as e:
902
- kestrel.Error("Could not rewrite submission file %s\n" % fname)
903
- else:
904
- os.unlink(fname)
905
-
906
- elif kestrel.action=="kill":
907
- # Kill and job retrieval do not require a valid solver
908
- kestrel.parseOptionsFile()
909
- if kestrel.jobNumber and kestrel.password:
910
- response = kestrel.neos.killJob(kestrel.jobNumber,kestrel.password)
911
-
912
- if kestrel.logopt in [1,3,4]:
913
- # Send the output to the screen
914
- sys.stdout.write("\n%s\n\n" % response)
915
- elif (kestrel.logopt == 2):
916
- # Append the error message to the logfile indicated
917
- try:
918
- f = open(kestrel.logfilename,'a')
919
- f.write("\n%s\n\n" % response)
920
- f.close()
921
- except IOError as e:
922
- kestrel.Error("Could not append to log file %s" % kestrel.logfilename)
923
-
924
- try:
925
- f = open(kestrel.statfilename,'a')
926
- f.write("=1\n\n")
927
- f.write("%s\n\n" % response)
928
- f.write("=2\n")
929
- f.close()
930
- except IOError as e:
931
- kestrel.Error("Could not append to status file %s\n" % kestrel.statfilename)
932
- else:
933
- kestrel.Error( "No 'kestrel_job' and 'kestrel_pass' options found in %s\n\n" % kestrel.optfilename)