CONOPT
Loading...
Searching...
No Matches
pindyck.cpp
Go to the documentation of this file.
1
7
8#include <stdlib.h>
9#include <stdio.h>
10#include <math.h>
11#include <string.h>
12#include <iostream>
13#include <map>
14#include <utility>
15#include "conopt.hpp"
16#include <cassert>
17
18#define CONS_SEQ 0
19#define CONS_DREV 1
20
22{
23public:
24 int T = 16; /* Number of time periods */
25 int Vpp = 7; /* Variables per period */
26 int Epp = 6; /* Equations per period */
27
28 /* the demand vector */
29 std::vector<double> demand;
30
31 /* index arrays for the variables */
32 std::vector<int> vartd;
33 std::vector<int> varcs;
34 std::vector<int> vars;
35 std::vector<int> vard;
36 std::vector<int> varr;
37 std::vector<int> varp;
38 std::vector<int> varrev;
39
40 std::map<int, std::pair<int, int>> consmapping;
41
46 {
47 int varidx;
48
49 /* defining the demand for each time period. */
50 for (int t = 0; t < T; t++)
51 demand.push_back(1.0 + 2.3 * pow(1.015, t));
52
77
78 for (int t = 0; t < T; t++)
79 {
80 /* td: Lower=0, Upper=inf, Curr=18 */
81 varidx = addVariable(0, Conopt::Infinity, 18);
82 vartd.push_back(varidx);
83
84 /* cs: Lower=0, Upper=inf, Curr=7*t */
85 varidx = addVariable(0, Conopt::Infinity, 7 * (t + 1));
86 varcs.push_back(varidx);
87
88 /* s: Lower=0, Upper=inf, Curr=7 */
89 varidx = addVariable(0, Conopt::Infinity, 7);
90 vars.push_back(varidx);
91
92 /* d: Lower=0, Upper=inf, Curr=td-s */
93 varidx =
95 vard.push_back(varidx);
96
97 /* r: Lower=1, Upper=inf, Curr=r(t-1)-d */
98 if (t > 0)
99 varidx = addVariable(
100 1, Conopt::Infinity, getVariable(varr[t - 1]).curr - getVariable(vard[t]).curr);
101 else
102 varidx = addVariable(1, Conopt::Infinity, 500 - getVariable(vard[t]).curr);
103 varr.push_back(varidx);
104
105 /* p: Lower=1, Upper=inf, Curr=14 */
106 varidx = addVariable(1, Conopt::Infinity, 14);
107 varp.push_back(varidx);
108
109 /* rev: Lower=-inf, Upper=inf, Curr=0 */
111 varrev.push_back(varidx);
112 }
113
114 /* adding the objective */
115 std::vector<double> objcoeff;
116 std::vector<int> objnlflag(T, 0);
117 for (int t = 0; t < T; ++t)
118 {
119 objcoeff.push_back(pow(1.05, 1 - (t + 1)));
120 }
121 int objidx = addConstraint(ConoptConstraintType::Free, 0.0, varrev, objcoeff, objnlflag);
122
123 /* adding the constraint information */
124 int considx;
125 for (int t = 0; t < T; t++)
126 {
127 /* adding the tdeq equations
128 * for the initial time period, the fixed value for td_{t - 1} is applied to the RHS
129 *
130 * tdeq(t): td(t) = 0.87*td(t-1) - 0.13*p(t) + demand(t)
131 *
132 * In GAMS, td("1974") is fixed (td.fx = 18), and the first equation is for 1975.
133 * So here for t=0 (1974), we apply the fixed value 18.0 directly on the RHS.
134 *
135 * That is why below we check if t == 0 and apply the fixed value of 18.0 directly
136 * to the RHS. Otherwise, we use the value of td(t-1) from the previous period.
137 *
138 * The same applies to the remaining equations.
139 */
140 if (t == 0)
141 {
143 {vartd[t], varp[t]}, // the variables
144 {1.0, 0.13}, // the coefficients
145 {0, 0} // nlflags
146 );
147 }
148 else
149 {
151 {1.0, -0.87, 0.13}, {0, 0, 0});
152 }
153
154 /* adding the seq Equations
155 * for the initial time period, the fixed value of s(1974)=6.5 is applied to the RHS
156 * GAMS: s(t) = 0.75*s(t-1) + (1.1+0.1*p(t))*1.02^(-cs(t)/7)
157 */
158 if (t == 0)
159 {
160 considx = addConstraint(ConoptConstraintType::Eq, 0.75 * 6.5,
161 {vars[t], varp[t], varcs[t]}, {1.0, 0.0, 0.0}, {0, 1, 1});
162 }
163 else
164 {
166 {vars[t], vars[t - 1], varp[t], varcs[t]}, {1.0, -0.75, 0.0, 0.0}, {0, 0, 1, 1});
167 }
168
169 /* storing the constraint index for the seq constraint, so that we can identify then
170 * constraint in FDEval
171 */
172 consmapping.emplace(considx, std::make_pair(CONS_SEQ, t));
173
174 /* adding the cseq Equations
175 * for the initial time period, cs(1974)=0.0
176 * cs(t) = cs(t-1) + s(t)
177 * So for t=0, we use cs(0) = s(0) and drop cs(t-1)
178 */
179 if (t == 0)
180 {
181 addConstraint(ConoptConstraintType::Eq, 0.0, {varcs[t], vars[t]}, {1.0, -1.0}, {0, 0});
182 }
183 else
184 {
186 {1.0, -1.0, -1.0}, {0, 0, 0});
187 }
188
189 /* adding the deq equations */
191 {1.0, -1.0, 1.0}, {0, 0, 0});
192
193 /* adding the req equations
194 * for the initial time period, the value of r(1974)=500 is applied to the RHS
195 * r(t) = r(t-1) - d(t)
196 * So for t=0, we use r(0) + d(0) = 500
197 */
198 if (t == 0)
199 {
200 addConstraint(ConoptConstraintType::Eq, 500.0, {varr[t], vard[t]}, {1.0, 1.0}, {0, 0});
201 }
202 else
203 {
204 addConstraint(ConoptConstraintType::Eq, 0.0, {varr[t], varr[t - 1], vard[t]},
205 {1.0, -1.0, 1.0}, {0, 0, 0});
206 }
207
208 /* adding the drev equations */
210 {varrev[t], vard[t], varp[t], varr[t]}, {1.0, 0.0, 0.0, 0.0}, {0, 1, 1, 1});
211
212 /* storing the constraint index for the drev constraint, so that we can identify then
213 * constraint in FDEval
214 */
215 consmapping.emplace(considx, std::make_pair(CONS_DREV, t));
216 }
217
218 /* setting the objective constraint */
220
221 /* setting the optimisation direction */
223 }
224
229 int FDEval(const double x[], double *g, double jac[], int rowno, const int jacnum[], int mode,
230 int ignerr, int *errcnt, int numvar, int numjac, int thread) override
231 {
232 /* returning an iterator based on the row number.
233 * NOTE: a map is just an array of pairs. So for the iterator, the
234 * first element is the key and the second is the value. In our case,
235 * then value is also a pair.
236 */
237 auto itr = consmapping.find(rowno);
238 if (itr == consmapping.end())
239 return 0;
240
241 /* storing the value (a pair) as a separate variable to make the
242 * extraction easier
243 */
244 auto conspair = itr->second;
245 /* I think that this will be a .first and .second. It could be ->first
246 * and ->second
247 */
248 int consset = conspair.first;
249 int t = conspair.second;
250 assert(consset == CONS_SEQ || consset == CONS_DREV);
251
252 if (consset == CONS_SEQ)
253 {
254 double h1, h2;
255 /* seq equation. Nonlinear term = -(1.1+0.1*p(t))*1.02**(-cs(t)/7) */
256
257 h1 = (1.1 + 0.1 * x[varp[t]]);
258 h2 = pow(1.02, -x[varcs[t]] / 7.0);
259 if (1 == mode || 3 == mode)
260 *g = -h1 * h2;
261 if (2 == mode || 3 == mode)
262 {
263 jac[varcs[t]] = h1 * h2 * log(1.02) / 7.0;
264 jac[varp[t]] = -h2 * 0.1;
265 }
266 }
267 else if (consset == CONS_DREV)
268 {
269 /* drev equation. Nonlinear term = -d(to)*(p(to)-250/r(to)) */
270
271 if (1 == mode || 3 == mode)
272 *g = -x[vard[t]] * (x[varp[t]] - 250. / x[varr[t]]);
273 if (2 == mode || 3 == mode)
274 {
275 jac[vard[t]] = -(x[varp[t]] - 250. / x[varr[t]]);
276 jac[varr[t]] = -x[vard[t]] * 250. / pow(x[varr[t]], 2);
277 jac[varp[t]] = -x[vard[t]];
278 }
279 }
280
281 return 0;
282 }
283};
284
285#include "std.cpp"
286
290int main(int argc, char **argv)
291{
292 int COI_Error = 0;
293
294 // getting the program name from the executable path
295 std::string pname = getProgramName(argv[0]);
296
297 // initialising the Conopt Object
299 PD_ModelData modeldata;
300 Tut_MessageHandler msghandler(pname);
301
302 // adding the message handler to the conopt interface
303 conopt.setMessageHandler(msghandler);
304
305 // building the model
306 modeldata.buildModel();
307
308 // loading the model in the conopt object
309 conopt.loadModel(modeldata);
310
311#if defined(CONOPT_LICENSE_INT_1) && defined(CONOPT_LICENSE_INT_2) && defined(CONOPT_LICENSE_INT_3) && defined(CONOPT_LICENSE_TEXT)
312 std::string license = CONOPT_LICENSE_TEXT;
313 COI_Error += conopt.setLicense(CONOPT_LICENSE_INT_1, CONOPT_LICENSE_INT_2, CONOPT_LICENSE_INT_3, license);
314#endif
315
316 if (COI_Error)
317 {
318 conopt.sendMessage(
319 "Skipping COI_Solve due to setup errors. COI_Error = " + std::to_string(COI_Error));
320 cpp_log(conopt, "Skipping Solve due to setup errors", COI_Error);
321 }
322
323 COI_Error = conopt.solve(); /* Optimize */
324
325 conopt.sendMessage("After solving. COI_Error = " + std::to_string(COI_Error));
326 if (conopt.modelStatus() != 2 || conopt.solutionStatus() != 1)
327 cpp_log(conopt, "Incorrect Model or Solver Status", -1);
328 else if (fabs(conopt.objectiveValue() - 1170.486) > 0.001)
329 cpp_log(conopt, "Incorrect objective returned", -1);
330
331 conopt.printStatus();
332
333 cpp_log(conopt, "Successful Solve", COI_Error);
334}
The Conopt class.
Definition conopt.hpp:27
static constexpr double Infinity
Definition conopt.hpp:30
std::vector< int > varp
Definition pindyck.cpp:37
std::vector< int > varcs
Definition pindyck.cpp:33
std::vector< int > vars
Definition pindyck.cpp:34
std::vector< int > vard
Definition pindyck.cpp:35
std::map< int, std::pair< int, int > > consmapping
Definition pindyck.cpp:40
std::vector< int > varr
Definition pindyck.cpp:36
std::vector< int > varrev
Definition pindyck.cpp:38
std::vector< int > vartd
Definition pindyck.cpp:32
std::vector< double > demand
Definition pindyck.cpp:29
char pname[MAXLINE]
Definition comdecl.h:10
int COI_Error
Definition comdecl.h:15
CONOPT C++ interface header file. This is the main object for the CONOPT C++ interface.
int main(int argc, char **argv)
Main program. A simple setup and call of CONOPT.
Definition pindyck.cpp:290
int FDEval(const double x[], double *g, double jac[], int rowno, const int jacnum[], int mode, int ignerr, int *errcnt, int numvar, int numjac, int thread) override
defines the nonlinearities of the model by returning numerical values.
Definition pindyck.cpp:229
void buildModel()
adds the variables and constraints for the problem
Definition pindyck.cpp:45
int addVariable(double lower, double upper, double curr=0, int varstatus=-1)
adds a variable to the model. The non-zero coefficients are added later.
void setObjectiveElement(ConoptObjectiveElement elem, int elemindex)
sets the index for the objective variable or constraint
int addConstraint(ConoptConstraintType constype, double rhs, int slackstatus=-1)
adds a constraint to the problem. The non-zero coefficients are added later
void setOptimizationSense(ConoptSense sense)
sets the optimisation direction.
const ConoptVariable & getVariable(int index) const
returns a reference to the variable object
#define CONS_SEQ
Definition pindyck.cpp:18
#define CONS_DREV
Definition pindyck.cpp:19
void cpp_log(Conopt &conopt, std::string msg, int code)
Definition std.cpp:111
std::string getProgramName(char *execname)
Definition std.cpp:95