CONOPT
Loading...
Searching...
No Matches
pinadd.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 Vpp = 7; /* Variables per period */
25 int Epp = 6; /* Equations per period */
26
27 /* the demand vector */
28 std::vector<double> demand;
29
30 /* index arrays for the variables */
31 std::vector<int> vartd;
32 std::vector<int> varcs;
33 std::vector<int> vars;
34 std::vector<int> vard;
35 std::vector<int> varr;
36 std::vector<int> varp;
37 std::vector<int> varrev;
38
39 /* index arrays for the constraints */
40 std::vector<int> consttdeq;
41 std::vector<int> constseq;
42 std::vector<int> constcseq;
43 std::vector<int> constdeq;
44 std::vector<int> constreq;
45 std::vector<int> constdrev;
46
47 std::map<int, std::pair<int, int>> consmapping;
48
52 void buildModel(int T, const std::vector<double> &xkeep, const std::vector<int> &xstat,
53 const std::vector<int> &estat)
54 {
55 int varidx;
56
57 /* defining the demand for each time period. */
58 for (int t = 0; t < T; t++)
59 demand.push_back(1.0 + 2.3 * pow(1.015, t));
60
85
86 for (int t = 0; t < T; t++)
87 {
88 /* td: Lower=0, Upper=inf, Curr=18 */
89 varidx = addVariable(0, Conopt::Infinity, 18);
90 vartd.push_back(varidx);
91
92 /* cs: Lower=0, Upper=inf, Curr=7*t */
93 varidx = addVariable(0, Conopt::Infinity, 7 * (t + 1));
94 varcs.push_back(varidx);
95
96 /* s: Lower=0, Upper=inf, Curr=7 */
97 varidx = addVariable(0, Conopt::Infinity, 7);
98 vars.push_back(varidx);
99
100 /* d: Lower=0, Upper=inf, Curr=td-s */
101 varidx =
103 vard.push_back(varidx);
104
105 /* r: Lower=1, Upper=inf, Curr=r(t-1)-d */
106 if (t > 0)
107 varidx = addVariable(
108 1, Conopt::Infinity, getVariable(varr[t - 1]).curr - getVariable(vard[t]).curr);
109 else
110 varidx = addVariable(1, Conopt::Infinity, 500 - getVariable(vard[t]).curr);
111 varr.push_back(varidx);
112
113 /* p: Lower=1, Upper=inf, Curr=14 */
114 varidx = addVariable(1, Conopt::Infinity, 14);
115 varp.push_back(varidx);
116
117 /* rev: Lower=-inf, Upper=inf, Curr=0 */
119 varrev.push_back(varidx);
120 }
121
128 if (xkeep.size() > 0)
129 {
130 for (size_t i = 0; i < xkeep.size(); i++)
131 {
132 getVariable(i).curr = xkeep[i];
133 }
134
135 /* linear extrapolation for the last period of variable td */
136 getVariable(vartd[T - 1]).curr =
137 2 * getVariable(vartd[T - 2]).curr - getVariable(vartd[T - 3]).curr;
138 /* cs */
139 getVariable(varcs[T - 1]).curr =
140 2 * getVariable(varcs[T - 2]).curr - getVariable(varcs[T - 3]).curr;
141 /* s */
142 getVariable(vars[T - 1]).curr =
143 2 * getVariable(vars[T - 2]).curr - getVariable(vars[T - 3]).curr;
144 /* d */
145 getVariable(vard[T - 1]).curr =
146 2 * getVariable(vard[T - 2]).curr - getVariable(vard[T - 3]).curr;
147 /* r */
148 getVariable(varr[T - 1]).curr =
149 2 * getVariable(varr[T - 2]).curr - getVariable(varr[T - 3]).curr;
150 /* p */
151 getVariable(varp[T - 1]).curr =
152 2 * getVariable(varp[T - 2]).curr - getVariable(varp[T - 3]).curr;
153 /* rev */
154 getVariable(varrev[T - 1]).curr =
155 2 * getVariable(varrev[T - 2]).curr - getVariable(varrev[T - 3]).curr;
156
162 for (size_t i = 0; i < xstat.size(); i++)
163 {
164 getVariable(i).varstatus = xstat[i];
165 }
166
167 /* td */
169 /* cs */
171 /* s */
173 /* d */
175 /* r */
177 /* p */
179 /* rev */
181 }
182
183 /* adding the objective */
184 std::vector<double> objcoeff;
185 std::vector<int> objnlflag(T, 0);
186 for (int t = 0; t < T; ++t)
187 {
188 objcoeff.push_back(pow(1.05, 1 - (t + 1)));
189 }
190 int objidx = addConstraint(ConoptConstraintType::Free, 0.0, varrev, objcoeff, objnlflag);
191
192 /* adding the constraint information */
193 int considx;
194 for (int t = 0; t < T; t++)
195 {
196 /* adding the tdeq equations
197 * for the initial time period, the fixed value for td_{t - 1} is applied to the RHS
198 *
199 * tdeq(t): td(t) = 0.87*td(t-1) - 0.13*p(t) + demand(t)
200 *
201 * In GAMS, td("1974") is fixed (td.fx = 18), and the first equation is for 1975.
202 * So here for t=0 (1974), we apply the fixed value 18.0 directly on the RHS.
203 *
204 * That is why below we check if t == 0 and apply the fixed value of 18.0 directly
205 * to the RHS. Otherwise, we use the value of td(t-1) from the previous period.
206 *
207 * The same applies to the remaining equations.
208 */
209 if (t == 0)
210 {
211 considx = addConstraint(ConoptConstraintType::Eq, demand[t] + 0.87 * 18.0,
212 {vartd[t], varp[t]}, // the variables
213 {1.0, 0.13}, // the coefficients
214 {0, 0} // nlflags
215 );
216 }
217 else
218 {
220 {vartd[t], vartd[t - 1], varp[t]}, {1.0, -0.87, 0.13}, {0, 0, 0});
221 }
222 consttdeq.push_back(considx);
223
224 /* adding the seq Equations
225 * for the initial time period, the fixed value of s(1974)=6.5 is applied to the RHS
226 * GAMS: s(t) = 0.75*s(t-1) + (1.1+0.1*p(t))*1.02^(-cs(t)/7)
227 */
228 if (t == 0)
229 {
230 considx = addConstraint(ConoptConstraintType::Eq, 0.75 * 6.5,
231 {vars[t], varp[t], varcs[t]}, {1.0, 0.0, 0.0}, {0, 1, 1});
232 }
233 else
234 {
236 {vars[t], vars[t - 1], varp[t], varcs[t]}, {1.0, -0.75, 0.0, 0.0}, {0, 0, 1, 1});
237 }
238 constseq.push_back(considx);
239
240 /* storing the constraint index for the seq constraint, so that we can identify then
241 * constraint in FDEval
242 */
243 consmapping.emplace(considx, std::make_pair(CONS_SEQ, t));
244
245 /* adding the cseq Equations
246 * for the initial time period, cs(1974)=0.0
247 * cs(t) = cs(t-1) + s(t)
248 * So for t=0, we use cs(0) = s(0) and drop cs(t-1)
249 */
250 if (t == 0)
251 {
252 considx = addConstraint(
253 ConoptConstraintType::Eq, 0.0, {varcs[t], vars[t]}, {1.0, -1.0}, {0, 0});
254 }
255 else
256 {
258 {varcs[t], varcs[t - 1], vars[t]}, {1.0, -1.0, -1.0}, {0, 0, 0});
259 }
260 constcseq.push_back(considx);
261
262 /* adding the deq equations */
263 considx = addConstraint(ConoptConstraintType::Eq, 0.0, {vard[t], vartd[t], vars[t]},
264 {1.0, -1.0, 1.0}, {0, 0, 0});
265 constdeq.push_back(considx);
266
267 /* adding the req equations
268 * for the initial time period, the value of r(1974)=500 is applied to the RHS
269 * r(t) = r(t-1) - d(t)
270 * So for t=0, we use r(0) + d(0) = 500
271 */
272 if (t == 0)
273 {
274 considx = addConstraint(
275 ConoptConstraintType::Eq, 500.0, {varr[t], vard[t]}, {1.0, 1.0}, {0, 0});
276 }
277 else
278 {
279 considx = addConstraint(ConoptConstraintType::Eq, 0.0, {varr[t], varr[t - 1], vard[t]},
280 {1.0, -1.0, 1.0}, {0, 0, 0});
281 }
282 constreq.push_back(considx);
283
284 /* adding the drev equations */
286 {varrev[t], vard[t], varp[t], varr[t]}, {1.0, 0.0, 0.0, 0.0}, {0, 1, 1, 1});
287 constdrev.push_back(considx);
288
289 /* storing the constraint index for the drev constraint, so that we can identify then
290 * constraint in FDEval
291 */
292 consmapping.emplace(considx, std::make_pair(CONS_DREV, t));
293 }
294
295 /* Restore values from previous runs */
296 if (estat.size() > 0)
297 {
298 /* the equation status */
299 for (size_t i = 0; i < estat.size(); i++)
300 {
301 getConstraint(i).slackstatus = estat[i];
302 }
303
304 /* tdeq */
306 /* seq */
308 /* cseq */
310 /* deq */
312 /* req */
314 /* drev */
316 }
317
318 /* setting the objective constraint */
320
321 /* setting the optimisation direction */
323 }
324
329 int FDEval(const double x[], double *g, double jac[], int rowno, const int jacnum[], int mode,
330 int ignerr, int *errcnt, int numvar, int numjac, int thread) override
331 {
332 /* returning an iterator based on the row number.
333 * NOTE: a map is just an array of pairs. So for the iterator, the
334 * first element is the key and the second is the value. In our case,
335 * then value is also a pair.
336 */
337 auto itr = consmapping.find(rowno);
338 if (itr == consmapping.end())
339 return 0;
340
341 /* storing the value (a pair) as a separate variable to make the
342 * extraction easier
343 */
344 auto conspair = itr->second;
345 /* I think that this will be a .first and .second. It could be ->first
346 * and ->second
347 */
348 int consset = conspair.first;
349 int t = conspair.second;
350 assert(consset == CONS_SEQ || consset == CONS_DREV);
351
352 if (consset == CONS_SEQ)
353 {
354 double h1, h2;
355 /* seq equation. Nonlinear term = -(1.1+0.1*p(t))*1.02**(-cs(t)/7) */
356
357 h1 = (1.1 + 0.1 * x[varp[t]]);
358 h2 = pow(1.02, -x[varcs[t]] / 7.0);
359 if (1 == mode || 3 == mode)
360 *g = -h1 * h2;
361 if (2 == mode || 3 == mode)
362 {
363 jac[varcs[t]] = h1 * h2 * log(1.02) / 7.0;
364 jac[varp[t]] = -h2 * 0.1;
365 }
366 }
367 else if (consset == CONS_DREV)
368 {
369 /* drev equation. Nonlinear term = -d(to)*(p(to)-250/r(to)) */
370
371 if (1 == mode || 3 == mode)
372 *g = -x[vard[t]] * (x[varp[t]] - 250. / x[varr[t]]);
373 if (2 == mode || 3 == mode)
374 {
375 jac[vard[t]] = -(x[varp[t]] - 250. / x[varr[t]]);
376 jac[varr[t]] = -x[vard[t]] * 250. / pow(x[varr[t]], 2);
377 jac[varp[t]] = -x[vard[t]];
378 }
379 }
380
381 return 0;
382 }
383};
384
385#include "std.cpp"
386
390int main(int argc, char **argv)
391{
392 int COI_Error = 0;
393
394 // getting the program name from the executable path
395 std::string pname = getProgramName(argv[0]);
396
397 // initialising the Conopt Object
399 Tut_MessageHandler msghandler(pname);
400
401 // adding the message handler to the conopt interface
402 conopt.setMessageHandler(msghandler);
403
404 for (int i = 16; i <= 20; i++)
405 {
406
407 PADD_ModelData modeldata;
408
409 auto xkeep = conopt.getVariableValues();
410 auto xstat = conopt.getVariableStatus();
411 auto estat = conopt.getConstraintStatus();
412
413 // building the model
414 modeldata.buildModel(i, xkeep, xstat, estat); // Add T, and other vectors as parameters
415
416 // loading the model in the conopt object
417 conopt.loadModel(modeldata);
418
419#if defined(CONOPT_LICENSE_INT_1) && defined(CONOPT_LICENSE_INT_2) && defined(CONOPT_LICENSE_INT_3) && defined(CONOPT_LICENSE_TEXT)
420 std::string license = CONOPT_LICENSE_TEXT;
421 COI_Error += conopt.setLicense(CONOPT_LICENSE_INT_1, CONOPT_LICENSE_INT_2, CONOPT_LICENSE_INT_3, license);
422#endif
423
424 if (COI_Error)
425 {
426 conopt.sendMessage(
427 "Skipping COI_Solve due to setup errors. COI_Error = " + std::to_string(COI_Error));
428 cpp_log(conopt, "Skipping Solve due to setup errors", COI_Error);
429 }
430
431 COI_Error = conopt.solve(); /* Optimize */
432
433 conopt.sendMessage("After solving. COI_Error = " + std::to_string(COI_Error));
434 if (conopt.modelStatus() != 2 || conopt.solutionStatus() != 1)
435 cpp_log(conopt, "Incorrect Model or Solver Status", -1);
436
437 conopt.printStatus();
438 }
439 cpp_log(conopt, "Successful Solve", COI_Error);
440}
The Conopt class.
Definition conopt.hpp:27
static constexpr double Infinity
Definition conopt.hpp:30
std::vector< double > demand
Definition pinadd.cpp:28
std::vector< int > constcseq
Definition pinadd.cpp:42
std::vector< int > constseq
Definition pinadd.cpp:41
std::vector< int > consttdeq
Definition pinadd.cpp:40
std::vector< int > varcs
Definition pinadd.cpp:32
std::vector< int > vars
Definition pinadd.cpp:33
std::vector< int > vard
Definition pinadd.cpp:34
std::vector< int > varp
Definition pinadd.cpp:36
std::vector< int > varrev
Definition pinadd.cpp:37
std::vector< int > constreq
Definition pinadd.cpp:44
std::vector< int > constdeq
Definition pinadd.cpp:43
std::vector< int > varr
Definition pinadd.cpp:35
std::vector< int > vartd
Definition pinadd.cpp:31
std::vector< int > constdrev
Definition pinadd.cpp:45
std::map< int, std::pair< int, int > > consmapping
Definition pinadd.cpp:47
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 pinadd.cpp:390
void buildModel(int T, const std::vector< double > &xkeep, const std::vector< int > &xstat, const std::vector< int > &estat)
adds the variables and constraints for the problem
Definition pinadd.cpp:52
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 pinadd.cpp:329
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 ConoptConstraint & getConstraint(int index) const
returns a reference to the constraint object
const ConoptVariable & getVariable(int index) const
returns a reference to the variable object
double xkeep[Tmax *Tmax *Vpp]
int T
Definition pinadd.c:14
#define CONS_SEQ
Definition pinadd.cpp:18
#define CONS_DREV
Definition pinadd.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