Loading...
Searching...
No Matches
warehouse.py
Go to the documentation of this file.
10
11import os
12import sys
13from threading import Lock, Thread
14from gams import GamsWorkspace, GamsException, GamsExceptionExecution, GamsExitCode
15
16GAMS_MODEL = """
17$eolcom //
18$SetDDList warehouse store fixed disaggregate // acceptable defines
19$if not set warehouse $set warehouse 10
20$if not set store $set store 50
21$if not set fixed $set fixed 20
22$if not set disaggregate $set disaggregate 1 // indicator for tighter bigM constraint
23
24$ife %store%<=%warehouse% $abort Increase number of stores (>%warehouse)
25
26Set
27 res 'respond codes'
28 / 0 Normal
29 1 License Error
30 2 No solution
31 3 Other Error /
32 ares(res) / 3 /
33 Warehouse / w1*w%warehouse% /
34 Store / s1*s%store% /;
35
36Alias
37 (Warehouse,w)
38 (Store,s);
39
40Scalar fixed 'fixed cost for opening a warehouse' / %fixed% /;
41
42Parameter
43 capacity(Warehouse)
44 supplyCost(Store,Warehouse);
45
46$eval storeDIVwarehouse trunc(card(store)/card(warehouse))
47
48capacity(w) = %storeDIVwarehouse% + mod(ord(w), %storeDIVwarehouse%);
49supplyCost(s,w) = 1 + mod(ord(s) + 10*ord(w), 100);
50
51Variable
52 open(Warehouse)
53 supply(Store,Warehouse)
54 obj;
55
56Binary Variable open, supply;
57
58Equation
59 defobj
60 oneWarehouse(s)
61 defopen(w);
62
63defobj.. obj =e= sum(w, fixed*open(w)) + sum((w,s), supplyCost(s,w)*supply(s,w));
64
65oneWarehouse(s).. sum(w, supply(s,w)) =e= 1;
66
67defopen(w).. sum(s, supply(s,w)) =l= open(w)*capacity(w);
68
69$ifthen %disaggregate%==1
70Equation defopen2(s,w);
71defopen2(s,w).. supply(s,w) =l= open(w);
72$endif
73
74Model distrib / all /;
75solve distrib min obj using mip;
76
77$macro setResult(n) option clear=ares; ares(n) = yes;
78
79if (distrib.modelstat=%ModelStat.LicensingProblem% or
80 distrib.solvestat=%Solvestat.LicensingProblems%,
81 setResult('1');
82 abort 'License Error';
83);
84
85if (distrib.solvestat<>%SolveStat.NormalCompletion% or
86 distrib.modelstat<>%ModelStat.Optimal% and
87 distrib.modelstat<>%ModelStat.IntegerSolution%,
88 setResult('2');
89 abort 'No solution';
90);
91
92setResult('0');
93"""
94
95
96def solve_warehouse(workspace, nr_warehouses, result, lock):
97 global status
98 global status_string
99 try:
100 # instantiate GamsOptions and define some scalars
101 opt = workspace.add_options()
102 opt.all_model_types = "cplex"
103 opt.defines["Warehouse"] = str(nr_warehouses)
104 opt.defines["Store"] = "65"
105 opt.defines["fixed"] = "22"
106 opt.defines["disaggregate"] = "0"
107 opt.optcr = 0.0 # solve to optimality
108
109 # create a GamsJob from string and write results to the result database
110 job = workspace.add_job_from_string(GAMS_MODEL)
111 job.run(opt)
112
113 # need to lock database write operations
114 lock.acquire()
115 result["objrep"].add_record(str(nr_warehouses)).value = (
116 job.out_db["obj"].first_record().level
117 )
118 lock.release()
119 for supply_rec in job.out_db["supply"]:
120 if supply_rec.level > 0.5:
121 lock.acquire()
122 result["supplyMap"].add_record(
123 (str(nr_warehouses), supply_rec.key(0), supply_rec.key(1))
124 )
125 lock.release()
126 except Exception as e:
127 lock.acquire()
128 if isinstance(e, GamsExceptionExecution):
129 # check if we see a user triggered abort and look for the user defined result
130 if e.rc == GamsExitCode.ExecutionError:
131 status_string = (
132 job.out_db["res"]
133 .find_record(job.out_db["ares"].first_record().key(0))
134 .text
135 )
136 status = e.rc
137 else:
138 print(e)
139 status = -1 if isinstance(e, GamsException) else -2
140 lock.release()
141
142
143if __name__ == "__main__":
144 sys_dir = sys.argv[1] if len(sys.argv) > 1 else None
145 ws = GamsWorkspace(system_directory=sys_dir)
146
147 # create a GamsDatabase for the results
148 result_db = ws.add_database()
149 result_db.add_parameter("objrep", 1, "Objective value")
150 result_db.add_set("supplyMap", 3, "Supply connection with level")
151
152 status_string = ""
153 status = 0
154
155 # run multiple parallel jobs
156 lock = Lock()
157 threads = []
158 for i in range(10, 22):
159 t = Thread(target=solve_warehouse, args=(ws, i, result_db, lock))
160 t.start()
161 threads.append(t)
162 for t in threads:
163 t.join()
164 if status > 0:
165 raise GamsExceptionExecution(
166 f"GamsException occurred: Error when running GAMS: {status} {status_string}",
167 status,
168 ws,
169 )
170 elif status == -1:
171 raise GamsException("GamsException occurred: Error in GAMS API", ws)
172 elif status == -2:
173 raise Exception("Error occurred")
174
175 # export the result database to a GDX file
176 result_db.export(os.path.join(os.getcwd(), "result.gdx"))