warehouse.cpp
Go to the documentation of this file.
1/*
2  *
3  * GAMS - General Algebraic Modeling System C++ API
4  *
5  * Copyright (c) 2017-2022 GAMS Software GmbH <support@gams.com>
6  * Copyright (c) 2017-2022 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 
32 using namespace gams;
33 using namespace std;
34 
35 static int status;
36 static string statusString;
37 
39 string getModelText()
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 
111 void solveWarehouse(GAMSWorkspace* ws, int numberOfWarehouses, GAMSDatabase* resultDB, mutex* dbMutex)
112 {
113  GAMSJob gmsJ = ws->addJobFromString(getModelText());
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  }
142  catch(GAMSExceptionExecution& e)
143  {
144  if(e.rc() == GAMSEnum::ExecutionError)
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 
176 int 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 }
GAMSJob addJobFromString(const std::string &gamsSource, const std::string &jobName="")
void setSystemDirectory(std::string systemDir)
GAMSSetRecord findRecord(const std::vector< std::string > &keys)
GAMSVariable getVariable(const std::string &name)
void setAllModelTypes(const std::string &solver)
GAMSSet addSet(const std::string &name, const int dimension, const std::string &explanatoryText="", GAMSEnum::SetType setType=GAMSEnum::SetType::Multi)
GAMSParameterRecord addRecord(const std::vector< std::string > &keys)
GAMSDatabase outDB()
GAMSVariableRecord findRecord(const std::vector< std::string > &keys)
GAMSDatabase addDatabase(const std::string &databaseName="", const std::string &inModelName="")
static std::string text(GAMSEnum::SymbolType type)
GAMSSetRecord addRecord(const std::vector< std::string > &keys)
GAMSParameter addParameter(const std::string &name, const int dimension, const std::string &explanatoryText="")
GAMSSet getSet(const std::string &name)
std::string text()
void setValue(const double val)
GAMSParameter getParameter(const std::string &name)
void doExport(const std::string &filePath="")
void setDefine(const std::string &key, const std::string &value)
GAMSSetRecord firstRecord(const std::vector< std::string > &slice)
void setOptCR(const double value)
string getModelText()
Get model as string.
Definition: warehouse.cpp:39
GAMSOptions addOptions()
std::string key(int index)