warehouse.cpp
Go to the documentation of this file.
1/*
2 *
3 * GAMS - General Algebraic Modeling System C++ API
4 *
5 * Copyright (c) 2017 GAMS Software GmbH <support@gams.com>
6 * Copyright (c) 2017 GAMS Development Corp. <support@gams.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26#include <iostream>
27#include <fstream>
28#include <mutex>
29#include <thread>
30#include "gams.h"
31
32using namespace gams;
33using namespace std;
34
35static int status;
36static string statusString;
37
40{
41 return "$title Warehouse.gms \n"
42 " \n"
43 "$eolcom // \n"
44 "$SetDDList warehouse store fixed disaggregate // acceptable defines \n"
45 "$if not set warehouse $set warehouse 10 \n"
46 "$if not set store $set store 50 \n"
47 "$if not set fixed $set fixed 20 \n"
48 "$if not set disaggregate $set disaggregate 1 // indicator for tighter bigM constraint \n"
49 "$ife %store%<=%warehouse% $abort Increase number of stores (>%warehouse) \n"
50 " \n"
51 "set res respond codes / 0 Normal \n"
52 " 1 License Error \n"
53 " 2 No solution \n"
54 " 3 Other Error / \n"
55 " ares(res) / 3 /; \n"
56 " \n"
57 "Sets Warehouse /w1*w%warehouse% / \n"
58 " Store /s1*s%store% / \n"
59 "Alias (Warehouse,w), (Store,s); \n"
60 "Scalar \n"
61 " fixed fixed cost for opening a warehouse / %fixed% / \n"
62 "Parameter \n"
63 " capacity(WareHouse) \n"
64 " supplyCost(Store,Warehouse); \n"
65 " \n"
66 "$eval storeDIVwarehouse trunc(card(store)/card(warehouse)) \n"
67 "capacity(w) = %storeDIVwarehouse% + mod(ord(w),%storeDIVwarehouse%); \n"
68 "supplyCost(s,w) = 1+mod(ord(s)+10*ord(w), 100); \n"
69 " \n"
70 "Variables \n"
71 " open(Warehouse) \n"
72 " supply(Store,Warehouse) \n"
73 " obj; \n"
74 "Binary variables open, supply; \n"
75 " \n"
76 "Equations \n"
77 " defobj \n"
78 " oneWarehouse(s) \n"
79 " defopen(w); \n"
80 " \n"
81 "defobj.. obj =e= sum(w, fixed*open(w)) + sum((w,s), supplyCost(s,w)*supply(s,w)); \n"
82 " \n"
83 "oneWarehouse(s).. sum(w, supply(s,w)) =e= 1; \n"
84 " \n"
85 "defopen(w).. sum(s, supply(s,w)) =l= open(w)*capacity(w); \n"
86 " \n"
87 "$ifthen %disaggregate%==1 \n"
88 "Equations \n"
89 " defopen2(s,w); \n"
90 "defopen2(s,w).. supply(s,w) =l= open(w); \n"
91 "$endif \n"
92 " \n"
93 "model distrib /all/; \n"
94 "solve distrib min obj using mip; \n"
95 " \n"
96 "$macro setResult(n) option clear=ares; ares(n) = yes; \n"
97 "if (distrib.modelstat=%ModelStat.LicensingProblem% or \n"
98 " distrib.solvestat=%Solvestat.LicensingProblems%, \n"
99 " setResult('1'); \n"
100 " abort 'License Error'; \n"
101 "); \n"
102 "if (distrib.solvestat<>%SolveStat.NormalCompletion% or \n"
103 " distrib.modelstat<>%ModelStat.Optimal% and \n"
104 " distrib.modelstat<>%ModelStat.IntegerSolution%, \n"
105 " setResult('2'); \n"
106 " abort 'No solution'; \n"
107 "); \n"
108 "setResult('0'); \n";
109}
110
111void solveWarehouse(GAMSWorkspace* ws, int numberOfWarehouses, GAMSDatabase* resultDB, mutex* dbMutex)
112{
114 try{
115 // instantiate GAMSOptions and define some scalars
116 GAMSOptions gmsOpt = ws->addOptions();
117 gmsOpt.setAllModelTypes("cplex");
118 gmsOpt.setDefine("Warehouse", to_string(numberOfWarehouses));
119 gmsOpt.setDefine("Store", "65");
120 gmsOpt.setDefine("fixed", "22");
121 gmsOpt.setDefine("disaggregate", "0");
122 gmsOpt.setOptCR(0.0);
123
124 // create a GAMSJob from string and write results to the result database
125 gmsJ.run(gmsOpt);
126
127 // need to lock database write operations
128 {
129 lock_guard<mutex> dbLock(*dbMutex);
130 resultDB->getParameter("objrep").addRecord(to_string(numberOfWarehouses)).setValue(gmsJ.outDB().getVariable("obj").findRecord().level());
131 }
132
133 for(GAMSVariableRecord supplyRec : gmsJ.outDB().getVariable("supply"))
134 {
135 if (supplyRec.level() > 0.5)
136 {
137 lock_guard<mutex> dbLock(*dbMutex);
138 resultDB->getSet("supplyMap").addRecord(to_string(numberOfWarehouses), supplyRec.key(0), supplyRec.key(1));
139 }
140 }
141 }
143 {
145 {
146 lock_guard<mutex> dbLock(*dbMutex);
147 statusString = gmsJ.outDB().getSet("res").findRecord(gmsJ.outDB().getSet("ares").firstRecord().key(0)).text();
148 }
149 {
150 lock_guard<mutex> dbLock(*dbMutex);
151 status = e.rc();
152 }
153 }
154 catch (GAMSException e)
155 {
156 cout << e.what() << endl;
157 lock_guard<mutex> dbLock(*dbMutex);
158 status = -1;
159 }
160 catch (exception e)
161 {
162 cout << e.what() << endl;
163 lock_guard<mutex> dbLock(*dbMutex);
164 status = -2;
165 }
166}
167
176int main(int argc, char* argv[])
177{
178 cout << "---------- Warehouse --------------" << endl;
179
180 try{
181 GAMSWorkspaceInfo wsInfo;
182 if (argc > 1)
183 wsInfo.setSystemDirectory(argv[1]);
184 GAMSWorkspace ws(wsInfo);
185
186 // create a GAMSDatabase for the results
187 GAMSDatabase resultDB = ws.addDatabase();
188
189 resultDB.addParameter("objrep", 1, "Objective value");
190 resultDB.addSet("supplyMap", 3, "Supply connection with level");
191 // run multiple parallel jobs
192 mutex dbMutex;
193 vector<thread> v;
194 for(int nrWarehouses=10; nrWarehouses<22; nrWarehouses++)
195 v.emplace_back([&ws, nrWarehouses, &resultDB, &dbMutex]{solveWarehouse(&ws, nrWarehouses, &resultDB, &dbMutex);});
196 for (auto& t : v)
197 t.join();
198 if (status > 0)
199 throw GAMSExceptionExecution("Error when running GAMS: " + GAMSEnum::text((GAMSEnum::GAMSExitCode) status) + " " + statusString, status);
200 else if (status == -1)
201 throw GAMSException("Error in GAMS API");
202 else if (status == -2)
203 throw exception();
204 // export the result database to a GDX file
205 resultDB.doExport("\\tmp\\resultCpp.gdx");
206 } catch (GAMSException &ex) {
207 cout << "GAMSException occured: " << ex.what() << endl;
208 } catch (exception &ex) {
209 cout << ex.what() << endl;
210 }
211 return status;
212}
void setValue(const double val)
string getModelText()
Get model as string.
Definition: warehouse.cpp:39
GAMSParameter getParameter(const std::string &name)
static std::string text(GAMSEnum::SymbolType type)
void setAllModelTypes(const std::string &solver)
GAMSSet getSet(const std::string &name)
GAMSSet addSet(const std::string &name, const int dimension, const std::string &explanatoryText="")
GAMSParameter addParameter(const std::string &name, const int dimension, const std::string &explanatoryText="")
void setSystemDirectory(std::string systemDir)
void setOptCR(const double value)
GAMSDatabase addDatabase(const std::string &databaseName="", const std::string &inModelName="")
GAMSDatabase outDB()
GAMSSetRecord findRecord(const std::vector< std::string > &keys)
void setDefine(const std::string &key, const std::string &value)
GAMSOptions addOptions()
GAMSVariable getVariable(const std::string &name)
std::string key(int index)
GAMSVariableRecord findRecord(const std::vector< std::string > &keys)
GAMSSetRecord firstRecord(const std::vector< std::string > &slice)
void doExport(const std::string &filePath="")
GAMSJob addJobFromString(const std::string &gamsSource, const std::string &jobName="")
GAMSSetRecord addRecord(const std::vector< std::string > &keys)
GAMSParameterRecord addRecord(const std::vector< std::string > &keys)