run_engine.py
Go to the documentation of this file.
11 
12 from gams import *
13 import os
14 import sys
15 import time
16 import json
17 from threading import Thread
18 try:
19  from StringIO import StringIO
20 except ImportError:
21  from io import StringIO
22 
23 
25  return '''
26  Sets
27  i canning plants / seattle, san-diego /
28  j markets / new-york, chicago, topeka / ;
29 
30  Parameters
31 
32  a(i) capacity of plant i in cases
33  / seattle 350
34  san-diego 600 /
35 
36  b(j) demand at market j in cases
37  / new-york 325
38  chicago 300
39  topeka 275 / ;
40 
41  Table d(i,j) distance in thousands of miles
42  new-york chicago topeka
43  seattle 2.5 1.7 1.8
44  san-diego 2.5 1.8 1.4 ;
45 
46  Scalar f freight in dollars per case per thousand miles /90/ ;
47  Scalar bmult demand multiplier /1/; '''
48 
49 
51  return '''
52  Sets
53  i canning plants
54  j markets
55 
56  Parameters
57  a(i) capacity of plant i in cases
58  b(j) demand at market j in cases
59  d(i,j) distance in thousands of miles
60  Scalar f freight in dollars per case per thousand miles;
61  Scalar bmult demand multiplier;
62 
63 $if not set gdxincname $abort 'no include file name for data file provided'
64 $gdxin %gdxincname%
65 $load i j a b d f bmult
66 $gdxin
67 
68 $echo "test" > test.txt
69 
70  Parameter c(i,j) transport cost in thousands of dollars per case ;
71 
72  c(i,j) = f * d(i,j) / 1000 ;
73 
74  Variables
75  x(i,j) shipment quantities in cases
76  z total transportation costs in thousands of dollars ;
77 
78  Positive Variable x ;
79 
80  Equations
81  cost define objective function
82  supply(i) observe supply limit at plant i
83  demand(j) satisfy demand at market j ;
84 
85  cost .. z =e= sum((i,j), c(i,j)*x(i,j)) ;
86 
87  supply(i) .. sum(j, x(i,j)) =l= a(i) ;
88 
89  demand(j) .. sum(i, x(i,j)) =g= bmult*b(j) ;
90 
91  Model transport /all/ ;
92 
93  Solve transport using lp minimizing z ;
94 
95  Scalar ms 'model status', ss 'solve status';
96 
97  Display x.l, x.m ; '''
98 
99 
100 if __name__ == "__main__":
101  if len(sys.argv) > 1:
102  ws = GamsWorkspace(system_directory=sys.argv[1])
103  else:
104  ws = GamsWorkspace()
105 
106  # --------------------------------------------
107  # Set up configuration required for any job
108  # on GAMS Engine
109  # --------------------------------------------
110 
111  engine_configuration = GamsEngineConfiguration(host=os.environ['ENGINE_URL'],
112  username=os.environ['ENGINE_USER'],
113  password=os.environ['ENGINE_PASSWORD'],
114  namespace=os.environ['ENGINE_NAMESPACE'])
115 
116  t3 = ws.add_job_from_string(get_data_text())
117  t3.run_engine(engine_configuration)
118  gdx_file_path = os.path.join(ws.working_directory, "tdata.gdx")
119  t3.out_db.export(gdx_file_path)
120  t3 = ws.add_job_from_string(get_model_text())
121 
122  opt = ws.add_options()
123  opt.defines["gdxincname"] = "tdata"
124  opt.all_model_types = "xpress"
125  t3.run_engine(engine_configuration,
126  extra_model_files=gdx_file_path,
127  engine_options={"inex_string": json.dumps(
128  {"type": "include", "files": ["*.gdx"]})},
129  gams_options=opt)
130  expected_levels = {"seattle.new-york": 0.0, "seattle.chicago": 300.0, "seattle.topeka": 0.0,
131  "san-diego.new-york": 325.0, "san-diego.chicago": 0.0, "san-diego.topeka": 275.0}
132 
133  for rec in t3.out_db["x"]:
134  print("x(" + rec.key(0) + "," + rec.key(1) + "): level=" +
135  str(rec.level) + " marginal=" + str(rec.marginal))
136  assert expected_levels[rec.key(0) + "." + rec.key(1)] == rec.level
137 
138  assert os.path.exists(os.path.join(
139  ws.working_directory, "test.txt")) == False
140 
141  cp = ws.add_checkpoint()
142 
143  t3a = ws.add_job_from_string(get_data_text())
144  t3b = ws.add_job_from_string(get_model_text())
145  t3a.run_engine(engine_configuration)
146  opt.defines["gdxincname"] = t3a.out_db.name
147 
148  t3b.run_engine(engine_configuration,
149  gams_options=opt, databases=t3a.out_db, checkpoint=cp)
150 
151  for rec in t3.out_db["x"]:
152  assert expected_levels[rec.key(0) + "." + rec.key(1)] == rec.level
153 
154  bmultExpected = [
155  {"bmult": 0.9, "ms": 1, "ss": 1, "obj": 138.31},
156  {"bmult": 1.2, "ms": 4, "ss": 1, "obj": 184.41}]
157 
158  # create a new GAMSJob that is initialized from the GAMSCheckpoint
159  for scen in bmultExpected:
160  t5 = ws.add_job_from_string(
161  "bmult=" + str(scen["bmult"]) + "; solve transport min z use lp; ms=transport.modelstat; ss=transport.solvestat;", cp)
162  t5.run_engine(engine_configuration)
163  print("Scenario bmult=" + str(scen["bmult"]) + ":")
164  print(" Modelstatus: " + str(t5.out_db["ms"].find_record().value))
165  print(" Solvestatus: " + str(t5.out_db["ss"].find_record().value))
166  print(" Obj: " + str(t5.out_db["z"].find_record().level))
167  assert t5.out_db["bmult"].find_record().value == scen["bmult"]
168  assert t5.out_db["ms"].find_record().value == scen["ms"]
169  assert t5.out_db["ss"].find_record().value == scen["ss"]
170  assert round(t5.out_db["z"].find_record().level, 2) == scen["obj"]
171 
172  # --------------------------------------------
173  # Example how to interrupt Engine job
174  # --------------------------------------------
175 
176  ws.gamslib("clad")
177  j1 = ws.add_job_from_file("clad")
178 
179  # Define an option file for the solver to be used
180  option_file1_path = os.path.join(ws.working_directory, "cplex.opt")
181  with open(option_file1_path, "w") as f:
182  # Set relative stopping tolerance to 0 initially
183  f.write("epgap 0\n")
184  # Activate interactive option setting on interrupt
185  f.write("interactive 1\n")
186  # Define new option file to read on interrupt
187  f.write("iafile cplex.op2\n")
188 
189  # Write new Cplex option file
190  option_file2_path = os.path.join(ws.working_directory, "cplex.op2")
191  with open(option_file2_path, "w") as f:
192  f.write("epgap 0.1")
193 
194  opt = ws.add_options()
195  opt.mip = "cplex"
196  opt.optfile = 1
197  opt.solvelink = SolveLink.LoadLibrary
198 
199  sw = StringIO()
200 
201  # Run GamsJob j1 in separate thread
202  opt_thread = Thread(target=j1.run_engine, args=(
203  engine_configuration,), kwargs={"output": sw,
204  "extra_model_files": [option_file1_path, option_file2_path, "claddat.gdx"],
205  "gams_options": opt})
206  opt_thread.start()
207 
208  prev_step = 0.0
209  while True:
210  if sw.tell() == 0:
211  time.sleep(0.5)
212  continue
213  j1.interrupt()
214  print("Interrupted Cplex to continue with new option")
215  break
216 
217  # If j1 is still running, wait until it is finished
218  if opt_thread.is_alive:
219  opt_thread.join()
220  # Check if everything worked as expected
221  log = sw.getvalue()
222  if not "Interrupted..." in log:
223  raise Exception("Expected the solver to be interrupted at least once.")
def get_model_text()
Definition: run_engine.py:50
def get_data_text()
Definition: run_engine.py:24