FFSM++ 1.1.0
French Forest Sector Model ++
Loading...
Searching...
No Matches
Opt.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2015 by Laboratoire d'Economie Forestière *
3 * http://ffsm-project.org *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version, given the compliance with the *
9 * exceptions listed in the file COPYING that is distribued together *
10 * with this file. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22
23#include <stdlib.h>
24
25#include <cassert>
26
27#include <map>
28#include <adolc/drivers/drivers.h>
29#include <adolc/adolc_sparse.h>
30
31#include "Opt.h"
32
33#include "ModelData.h"
34#include "Pixel.h"
35#include "ThreadManager.h"
36#include "Scheduler.h"
37#include "ModelRegion.h"
38#include "Opt.h"
39
40#define CONSTRAIN_START_LOOP(pVector,cn) \
41 for (uint r1=0;r1<l2r.size();r1++){ \
42 for (uint r2=0;r2<l2r[r1].size();r2++){ \
43 for (uint p=0;p<(pVector).size();p++){ \
44 int psec = p+nPriPr; \
45 cix = gix((cn), r1, r2, p);
46#define CONSTRAIN_END_LOOP \
47 }}}
48
49
50using namespace Ipopt;
51
52typedef std::map<string, endvar> VarMap;
53typedef std::pair<std::string, endvar > VarPair;
54
55// ****** MODEL IMPLEMENTATION START HERE ********************************
56
57
58void
60 // filling the list of variables and their domain and optionally their bonds
61 // if you add variables in the model that enter optimisation you'll have to add them here
62 // the underlying map goes automatically in alphabetical order
63 // original order: pc,pl,dc,dl,da,sc,sl,sa,exp
64 // 20140328: if these vars have a lower bound > 0 the model doesn't solve when volumes in a region go to zero !!!
65
66 // syntax: declareVariable("name", domainType, lbound[default=0], ubound[default= +inf], variable defining lower bounds[default=""], variable defining upper bound[default=""])
67
68 // all variables have upper or equal than zero bound:
69 declareVariable("da", DOM_SEC_PR, "Demand from abroad (imports)");
70 declareVariable("dc", DOM_SEC_PR, "Demand, composite");
71 declareVariable("dl", DOM_ALL_PR, "Demand from local");
72 declareVariable("pc", DOM_ALL_PR, "Price, composite");
73 declareVariable("pl", DOM_ALL_PR, "Price, local") ;
74 declareVariable("rt", DOM_R2_ALL_PR, "Regional trade"); //it was exp in gams
75 declareVariable("sa", DOM_PRI_PR, "Supply to abroad (exports)");
76 declareVariable("sc", DOM_PRI_PR, "Supply, composite");
77 declareVariable("sl", DOM_ALL_PR, "Supply to locals");
78 //declareVariable("st", DOM_PRI_PR, "Supply, total", 0.0,UBOUND_MAX,"","in");
79}
80/**
81Declare the constrains and their properties. For the domain type @see BaseClass
82*/
83void
85 // domain of constrains variables
86 // for domain
87 constrain mkeq2;
88 mkeq2.name="mkeq2";
89 mkeq2.comment="[h1] Conservation of matters of transformed products";
90 mkeq2.domain=DOM_SEC_PR;
91 mkeq2.direction = CONSTR_EQ;
92 //mkeq2.evaluate = Opt::mkteq2f;
93
94 constrain mkeq3;
95 mkeq3.name="mkeq3";
96 mkeq3.comment="[h2] Conservation of matters of raw products";
97 mkeq3.domain=DOM_PRI_PR;
98 mkeq3.direction = CONSTR_EQ;
99 //mkeq3.evaluate = Opt::mkteq3f;
100
101 constrain mkeq4;
102 mkeq4.name="mkeq4";
103 mkeq4.comment="[eq 13] Leontief transformation function";
104 mkeq4.domain=DOM_PRI_PR;
105 mkeq4.direction = CONSTR_EQ;
106
107 constrain mkeq5;
108 mkeq5.name="mkeq5";
109 mkeq5.comment="[eq 21] Raw product supply function";
110 mkeq5.domain=DOM_PRI_PR;
111 mkeq5.direction = CONSTR_EQ;
112
113 constrain mkeq6;
114 mkeq6.name="mkeq6";
115 mkeq6.comment="[eq 20] Trasformed products demand function";
116 mkeq6.domain=DOM_SEC_PR;
117 mkeq6.direction = CONSTR_EQ;
118
119 constrain mkeq7;
120 mkeq7.name="mkeq7";
121 mkeq7.comment="[h7 and h3] Transformed products import function";
122 mkeq7.domain=DOM_SEC_PR;
123 mkeq7.direction = CONSTR_EQ;
124
125 constrain mkeq8;
126 mkeq8.name="mkeq8";
127 mkeq8.comment="[h8 and h4] Raw products export function";
128 mkeq8.domain=DOM_PRI_PR;
129 mkeq8.direction = CONSTR_EQ;
130
131 constrain mkeq13;
132 mkeq13.name="mkeq13";
133 mkeq13.comment="[h9] Calculation of the composite price of transformed products (PPC_Dp)";
134 mkeq13.domain=DOM_SEC_PR;
135 mkeq13.direction = CONSTR_EQ;
136
137 constrain mkeq14;
138 mkeq14.name="mkeq14";
139 mkeq14.comment="[h10] Calculation of the composite price of raw products (PPC_Sw)";
140 mkeq14.domain=DOM_PRI_PR;
141 mkeq14.direction = CONSTR_EQ;
142
143 constrain mkeq17;
144 mkeq17.name="mkeq17";
145 mkeq17.comment="[h16] Constrain of the transformaton supply (lower than the regional maximal production capacity)";
146 mkeq17.domain=DOM_SEC_PR;
147 mkeq17.direction = CONSTR_LE0;
148
149
150 constrain mkeq23;
151 mkeq23.name="mkeq23";
152 mkeq23.comment="[h3] Composit demand eq. (Dp)";
153 mkeq23.domain=DOM_SEC_PR;
154 mkeq23.direction = CONSTR_EQ;
155
156 constrain mkeq24;
157 mkeq24.name="mkeq24";
158 mkeq24.comment="[h4] Composite supply eq. (Sw)";
159 mkeq24.domain=DOM_PRI_PR;
160 mkeq24.direction = CONSTR_EQ;
161
162 constrain mkeq26;
163 mkeq26.name="mkeq26";
164 mkeq26.comment="[eq ] Verification of the null transport agents supply";
165 mkeq26.domain=DOM_R2_ALL_PR;
166 mkeq26.direction = CONSTR_LE0;
167
168 constrain mkeq25;
169 mkeq25.name="mkeq25";
170 mkeq25.comment="Verification of the null trasformers supply (price of raw product + trasf product > trasf product)";
171 mkeq25.domain=DOM_SEC_PR;
172 mkeq25.direction = CONSTR_GE0;
173
174 constrain mkeq18;
175 mkeq18.name="mkeq18";
176 mkeq18.comment="Constrain on raw material supply (lower than inventory)";
177 mkeq18.domain=DOM_PRI_PR;
178 mkeq18.direction = CONSTR_LE0;
179
180 constrain resbounds;
181 resbounds.name="resbounds";
182 resbounds.comment="Constrain on raw material supply (lower than inventory, for each possible combination of primary products)";
183 resbounds.domain=DOM_PRI_PR_ALLCOMBS;
184 resbounds.direction = CONSTR_LE0;
185
186
187
188 //constrain steq;
189 //steq.name="steq";
190 //steq.comment="computation of total supply";
191 //steq.domain=DOM_PRI_PR;
192 //steq.direction = CONSTR_EQ;
193
194 cons.push_back(mkeq2);
195 cons.push_back(mkeq6);
196 cons.push_back(mkeq7);
197 cons.push_back(mkeq13);
198 cons.push_back(mkeq23);
199 cons.push_back(mkeq3);
200 cons.push_back(mkeq4);
201 cons.push_back(mkeq5);
202 cons.push_back(mkeq8);
203 cons.push_back(mkeq14);
204 cons.push_back(mkeq24);
205 cons.push_back(mkeq17);
206 cons.push_back(mkeq26);
207 cons.push_back(mkeq25);
208 //cons.push_back(mkeq18);
209 cons.push_back(resbounds);
210 //cons.push_back(steq);
211;
212
213
214
215}
216/**
217Define the objective function
218*/
219template<class T> bool
220Opt::eval_obj(Index n, const T *x, T& obj_value){
221
222 double aa, bb, dc0, sigma, a_pr, ct, m, zeromax,supCorr2;
223 obj_value = 0.;
224 zeromax = 0.;
225
226 for (uint r1=0;r1<l2r.size();r1++){
227 for (uint r2=0;r2<l2r[r1].size();r2++){
228 // // consumer's surplus..
229 // sum ((i,p_tr),
230 // AA(i,p_tr)*(RVAR('dc',i,p_tr)**((sigma(p_tr)+1)/sigma(p_tr)))
231 // - AA(i,p_tr)*((0.5*dc0(i,p_tr))**((sigma(p_tr)+1)/sigma(p_tr)))
232 // - RVAR('pc',i,p_tr)*RVAR('dc',i,p_tr)
233 // )
234 // 20161003: TODO: check if subsidies should enter also the obj function other than the bounds equations. For the moment, as agreed with Sylvain, they are left outside the obj function, but I am not sure of it.
235 // 20170306: Subsides (but not substitute products) added to the aa and bb parameters. They do not change anything.
236 // 20170307: obj_value does not account for the minus 0-5dc0 part anymore. It doesn't chang anything if not that the "reported" surplus is negative.
237 // The integral of a power function p=q^a with a < -1 (derived from an q=p^b function with b between 0 and -1) is negative ranging from -inf at q=0
238 // to 0- with q = +inf
239 for (uint p=0;p<secPr.size();p++){
240 aa = gpd("aa",l2r[r1][r2],secPr[p]);
241 sigma = gpd("sigma",l2r[r1][r2],secPr[p]);
242 dc0 = gpd("dc",l2r[r1][r2],secPr[p],secondYear);
243 //obj_value += aa*pow(mymax(zeromax,x[gix("dc",r1,r2,p)]),(sigma+1)/sigma)-aa*pow(mymax(zeromax,0.5*dc0),(sigma+1)/sigma)-x[gix("pc",r1,r2,p+nPriPr)]*x[gix("dc",r1,r2,p)];
244 obj_value += aa*pow(mymax(zeromax,x[gix("dc",r1,r2,p)]),(sigma+1)/sigma)-x[gix("pc",r1,r2,p+nPriPr)]*x[gix("dc",r1,r2,p)];
245
246 }
247 // // producers surplus..
248 // + sum((i,p_pr),
249 // RVAR('pc',i,p_pr)*RVAR('sc',i,p_pr)
250 // - BB(i,p_pr)*(RVAR('sc',i,p_pr)**((sigma(p_pr)+1)/sigma(p_pr)))
251 // )
252 for (uint p=0;p<priPr.size();p++){
253 bb = gpd("bb",l2r[r1][r2],priPr[p]);
254 sigma = gpd("sigma",l2r[r1][r2],priPr[p]);
255 //supCorr2 = gpd("supCorr2",l2r[r1][r2],priPr[p]);
256 obj_value += x[gix("pc",r1,r2,p)]*x[gix("sc",r1,r2,p)] - bb*pow(mymax(zeromax,x[gix("sc",r1,r2,p)]),((sigma+1)/sigma));
257 }
258 // // trasformations between primary products
259 // + sum ((i,p_pr,p_pr2),
260 // +RVAR('pc',i,p_pr2)*pres(p_pr,p_pr2)*RVAR('sc',i,p_pr)
261 // -BB(i,p_pr2)*(pres(p_pr,p_pr2)*RVAR('sc',i,p_pr))**((sigma(p_pr2)+1)/sigma(p_pr2))
262 // )
263
264 for (uint p1=0;p1<priPr.size();p1++){
265 for (uint p2=0;p2<priPr.size();p2++){
266 a_pr = gpd("a_pr",l2r[r1][r2],priPr[p1],DATA_NOW,priPr[p2]);
267 bb = gpd("bb",l2r[r1][r2],priPr[p2]);
268 sigma = gpd("sigma",l2r[r1][r2],priPr[p2]);
269 obj_value += x[gix("pc",r1,r2,p2)]*a_pr*x[gix("sc",r1,r2,p1)]-bb*pow(mymax(zeromax,a_pr*x[gix("sc",r1,r2,p1)]),(sigma+1)/sigma);
270 }
271 }
272 // // surplus of transport agents..
273 // + sum((i,j,prd), (RVAR('pl',j,prd)-RVAR('pl',i,prd)-CT(i,j,prd))*EXP(i,j,prd))
274 for (uint p=0;p<allPr.size();p++){
275 for (uint r2To=0;r2To<l2r[r1].size();r2To++){
276 ct = (gpd("ct",l2r[r1][r2],allPr[p],DATA_NOW,i2s(l2r[r1][r2To])) * gpd("pol_tcSub",l2r[r1][r2],allPr[p]));
277 obj_value += (x[gix("pl",r1,r2To,p)]-x[gix("pl",r1,r2,p)]-ct)*x[gix("rt",r1,r2,p,r2To)];
278 }
279 }
280
281 // // transformers surplus..
282 // + sum((i,p_tr), (RVAR('pl',i,p_tr)-m(i,p_tr))*(RVAR('sl',i,p_tr))) // attenction it's local. if we include w imports or p expports this have to change
283 for (uint p=0;p<secPr.size();p++){
284 m = (gpd("m",l2r[r1][r2],secPr[p]) * gpd("pol_trSub",l2r[r1][r2],secPr[p]));
285 obj_value += (x[gix("pl",r1,r2,p+nPriPr)]-m)*x[gix("sl",r1,r2,p+nPriPr)];
286 }
287 // - sum((i,p_pr), RVAR('pl',i,p_pr)*RVAR('dl',i,p_pr)) // to total and an other equation total=local+abroad should be added
288 for (uint p=0;p<priPr.size();p++){
289 obj_value -= x[gix("pl",r1,r2,p)]*x[gix("dl",r1,r2,p)];
290 }
291 } // end of each lev2 regions
292
293 } //end of each r1 regions
294
295 //obj_value = -obj_value; // we want maximisation, ipopt minimize! (donei n the options - scaling obj function)
296
297 //exit(0);
298 return true;
299 // checked 20120802 this function is ok with gams, both in input and in output of the preoptimisation stage
300
301}
302
303
304
305/** Template function to implement (define) the previously declared constains.
306To the initial macro loop it must be passed the product vector over where to loop (priPr, secPr or allPr) and the order of the constrain has it has been added to the const vector.
307It could be possible to change this in a map and uses name, but then we would loose control on the constrains order, and we saw that it matters for finding the equilibrium.
308
309*/
310template<class T> bool
311Opt::eval_constraints(Index n, const T *x, Index m, T* g){
312
313 double a_pr, a, sigma, ff, pol_mktDirInt_s, pol_mktDirInt_d, pol_mktDirInt_d_pSubstituted, pol_mktDirInt_d_1, pol_mktDirInt_d_1_pSubstituted, gg, q1, p1v, t1, r1v, psi, eta, pworld, ct, k, dispor, mv, in, in_1, supCorr, es_d, pc_1, pc_pSubstituted, pc_1_pSubstituted, additionalDemand;
314 Index cix = 0;
315 Index debug = 0;
316
317 // mkteq2(i,p_tr).. RVAR('dl',i,p_tr)+sum(j,EXP(i,j,p_tr)) =e= RVAR('sl',i,p_tr)+ sum(b,EXP(b,i,p_tr)); // h1
318 CONSTRAIN_START_LOOP(secPr, 0) // attenction! you have to give the same order number as you inserted in the cons vector
319 //g[cix] = x[gix("dl",r1,r2,psec)]-x[gix("sl",r1,r2,psec)]+x[gix("da",r1,r2,p)];
320 g[cix] = x[gix("dl",r1,r2,psec)]-x[gix("sl",r1,r2,psec)];
321 for (uint r2To=0;r2To<l2r[r1].size();r2To++){
322 g[cix] += x[gix("rt",r1,r2,psec,r2To)]-x[gix("rt",r1,r2To,psec,r2)];
323 }
325
326
327 // mkteq6(i,p_tr).. RVAR('dc',i,p_tr) =e= GG(i,p_tr)*(RVAR('pc',i,p_tr)**sigma(p_tr)); // eq. 20 20160216: added sustitution elasticity in the demand
328 // DEMAND EQUATION of transformed products
330 gg = gpd("gg",l2r[r1][r2],secPr[p]);
331 sigma = gpd("sigma",l2r[r1][r2],secPr[p]);
332 pc_1 = gpd("pc",l2r[r1][r2],secPr[p],previousYear);
333 pol_mktDirInt_d = gpd("pol_mktDirInt_d",l2r[r1][r2],secPr[p]); // market policies (subs or taxes) this year
334 pol_mktDirInt_d_1 = gpd("pol_mktDirInt_d",l2r[r1][r2],secPr[p],previousYear); // market policies previous year
335 additionalDemand = gpd("additionalDemand",l2r[r1][r2],secPr[p]);
336 g[cix] = - gg*pow(x[gix("pc",r1,r2,psec)]*pol_mktDirInt_d,sigma); // note that putting 0.0 and 0.000 IS NOT the same thing. With 0.000 I have a seg fault in ADOL-C !!
337 vector<string> debug = secPr;
338 // Substitution part within forest producs (whose price is endogenous to the model)..
339 for (uint p2=0;p2<secPr.size();p2++){
340 es_d = gpd("es_d",l2r[r1][r2],secPr[p],DATA_NOW,secPr[p2]);
341 if(es_d){
342 pc_1_pSubstituted = gpd("pc",l2r[r1][r2],secPr[p2],previousYear);
343 pol_mktDirInt_d_pSubstituted = gpd("pol_mktDirInt_d",l2r[r1][r2],secPr[p2]); // market policies this year for the substitute product
344 pol_mktDirInt_d_1_pSubstituted = gpd("pol_mktDirInt_d",l2r[r1][r2],secPr[p2],previousYear); // market policies last year for the substitute product
345
346 g[cix] *= pow(
347 (
348 ((x[gix("pc",r1,r2,psec)]*pol_mktDirInt_d) / (x[gix("pc",r1,r2,priPr.size()+p2)]*pol_mktDirInt_d_pSubstituted))
349 /
350 ((pc_1*pol_mktDirInt_d_1) / (pc_1_pSubstituted*pol_mktDirInt_d_1_pSubstituted))
351 ), es_d
352 );
353 }
354 }
355 // Substitution part with other products with exogenous prices (e.g. fossilFuels)..
356 for (uint p3=0;p3<othPr.size();p3++){
357 es_d = gpd("es_d",l2r[r1][r2],secPr[p],DATA_NOW,othPr[p3]);
358 if(es_d){
359 pc_pSubstituted = gpd("pl",l2r[r1][r2],othPr[p3],DATA_NOW);
360 pc_1_pSubstituted = gpd("pl",l2r[r1][r2],othPr[p3],previousYear);
361
362 g[cix] *= pow(
363 (
364 (x[gix("pc",r1,r2,psec)]*pol_mktDirInt_d / pc_pSubstituted)
365 /
366 (pc_1*pol_mktDirInt_d_1 / pc_1_pSubstituted)
367 ), es_d
368 );
369 }
370 }
371 //g[cix] = x[gix("dc",r1,r2,p)]-gg*pow(x[gix("pc",r1,r2,psec)],sigma); // original without substitution elasticity
372 g[cix] += x[gix("dc",r1,r2,p)]-additionalDemand;
374
375
376 // mkteq7(i,p_tr).. RVAR('da',i,p_tr)/RVAR('dl',i,p_tr) =e= ((q1(i,p_tr)*RVAR('pl',i,p_tr))/(p1(i,p_tr)*PT_t(p_tr)))**psi(i,p_tr); // h7 and h3 ?
378 q1 = gpd("q1_polCorr",l2r[r1][r2],secPr[p]);
379 p1v = 1-q1;
380 psi = gpd("psi",l2r[r1][r2],secPr[p]);
381 pworld = gpd("pl", worldCodeLev2,secPr[p]);
382 g[cix] = x[gix("da",r1,r2,p)]/x[gix("dl",r1,r2,psec)] - pow((q1*x[gix("pl",r1,r2,psec)])/(p1v*pworld),psi);
384
385 // mkteq13(i,p_tr).. RVAR('pc',i,p_tr)*RVAR('dc',i,p_tr) =e= RVAR('dl',i,p_tr)*RVAR('pl',i,p_tr)+RVAR('da',i,p_tr)*PT_t(p_tr); // h9
387 pworld = gpd("pl", worldCodeLev2,secPr[p]);
388 g[cix] = x[gix("pc",r1,r2,psec)]*x[gix("dc",r1,r2,p)]-x[gix("dl",r1,r2,psec)]*x[gix("pl",r1,r2,psec)]-x[gix("da",r1,r2,p)]*pworld;
390
391 // mkteq23(i,p_tr).. RVAR('dc',i,p_tr) =e= (q1(i,p_tr)*(RVAR('da',i,p_tr)**((psi(i,p_tr)-1)/psi(i,p_tr)))+ p1(i,p_tr)*(RVAR('dl',i,p_tr)**((psi(i,p_tr)-1)/psi(i,p_tr))))**(psi(i,p_tr)/(psi(i,p_tr)-1)); // h3
393 q1 = gpd("q1_polCorr",l2r[r1][r2],secPr[p]);
394 psi = gpd("psi",l2r[r1][r2],secPr[p]);
395 p1v = 1-q1;
396 g[cix] = x[gix("dc",r1,r2,p)] -
397 pow(
398 q1 * pow(x[gix("da",r1,r2,p)],(psi-1)/psi)
399 + p1v * pow(x[gix("dl",r1,r2,psec)],(psi-1)/psi),
400 psi/(psi-1)
401 );
403
404 // mkteq3(i,p_pr).. RVAR('dl',i,p_pr)+sum(j,EXP(i,j,p_pr)) =e= RVAR('sl',i,p_pr)+ sum(b,EXP(b,i,p_pr))+sum(p_pr2, pres(p_pr2,p_pr)* RVAR('sl',i,p_pr2)); // h2
406 //g[cix] = x[gix("dl",r1,r2,p)]-x[gix("sl",r1,r2,p)]-x[gix("sa",r1,r2,p)];
407 g[cix] = x[gix("dl",r1,r2,p)]-x[gix("sl",r1,r2,p)];
408 for (uint r2To=0;r2To<l2r[r1].size();r2To++){
409 g[cix] += x[gix("rt",r1,r2,p,r2To)]-x[gix("rt",r1,r2To,p,r2)];
410 }
411 for (uint p2=0;p2<priPr.size();p2++){
412 a_pr = gpd("a_pr",l2r[r1][r2],priPr[p2],DATA_NOW,priPr[p]);
413 g[cix] -= a_pr*x[gix("sl",r1,r2,p2)];
414 }
416
417 //mkteq4(i,p_pr).. RVAR('dl',i,p_pr) =e= sum(p_tr, a(p_pr,p_tr)*(RVAR('sl',i,p_tr))); // eq. 13
419 g[cix] = x[gix("dl",r1,r2,p)];
420 for (uint p2=0;p2<secPr.size();p2++){
421 a = gpd("a",l2r[r1][r2],priPr[p],DATA_NOW,secPr[p2]);
422 g[cix] -= a*x[gix("sl",r1,r2,p2+nPriPr)];
423 }
425
426
427 // mkteq5(i,p_pr).. RVAR('sc',i,p_pr) =e= FF(i,p_pr)*(RVAR('pc',i,p_pr)**sigma(p_pr)); // eq. 21
428 // SUPPLY EQUATION OF PRIMARY PRODUCTS
429
430
432 ff = gpd("ff",l2r[r1][r2],priPr[p]);
433 pol_mktDirInt_s = gpd("pol_mktDirInt_s",l2r[r1][r2],priPr[p]);
434 sigma = gpd("sigma",l2r[r1][r2],priPr[p]);
435
436 // Added for carbon project ----------------------
437 double carbonPrice = gpd("carbonPrice",l2r[r1][r2],"",DATA_NOW); //using dummy region until Anto solves issue // Solved and generalised ;-)
438 double intRate = MTHREAD->MD->getDoubleSetting("ir");
439 double Pct = carbonPrice*intRate;
440 double omega = gpd("co2content_products", l2r[r1][r2], priPr[p])/1000; // Generalised
441 // ------------------------------------------------
442
443 g[cix] = x[gix("sc",r1,r2,p)]-ff*pow((x[gix("pc",r1,r2,p)]-omega*Pct)*pol_mktDirInt_s,sigma);
444 // -----------------------------------------------
445
446 //g[cix] = x[gix("sc",r1,r2,p)]-ff*pow(x[gix("pc",r1,r2,p)]*pol_mktDirInt_s,sigma);
448
449
450 // mkteq8(i,p_pr).. RVAR('sa',i,p_pr)/RVAR('sl',i,p_pr) =e= ((t1(i,p_pr)*RVAR('pl',i,p_pr))/(r1(i,p_pr)*PT_t(p_pr)))**eta(i,p_pr); // h8 and h4 ?
452 t1 = gpd("t1_polCorr",l2r[r1][r2],priPr[p]);
453 r1v = 1-t1;
454 eta = gpd("eta",l2r[r1][r2],priPr[p]);
455 pworld = gpd("pl", worldCodeLev2,priPr[p]);
456 g[cix] = x[gix("sa",r1,r2,p)]/x[gix("sl",r1,r2,p)] - pow((t1*x[gix("pl",r1,r2,p)])/(r1v*pworld),eta);
458
459 // mkteq14(i,p_pr).. RVAR('pc',i,p_pr)*RVAR('sc',i,p_pr) =e= RVAR('sl',i,p_pr)*RVAR('pl',i,p_pr)+RVAR('sa',i,p_pr)*PT_t(p_pr); // h10
461 pworld = gpd("pl", worldCodeLev2,priPr[p]);
462 g[cix] = x[gix("pc",r1,r2,p)]*x[gix("sc",r1,r2,p)]-x[gix("sl",r1,r2,p)]*x[gix("pl",r1,r2,p)]-x[gix("sa",r1,r2,p)]*pworld;
464
465 //mkteq24(i,p_pr).. RVAR('sc',i,p_pr) =e= (t1(i,p_pr)*(RVAR('sa',i,p_pr)**((eta(i,p_pr)-1)/eta(i,p_pr)))+ r1(i,p_pr)*(RVAR('sl',i,p_pr)**((eta(i,p_pr)-1)/eta(i,p_pr))))**(eta(i,p_pr)/(eta(i,p_pr)-1)); // h4
467 t1 = gpd("t1_polCorr",l2r[r1][r2],priPr[p]);
468 r1v = 1-t1;
469 eta = gpd("eta",l2r[r1][r2],priPr[p]);
470 g[cix] = x[gix("sc",r1,r2,p)] -
471 pow(
472 t1 * pow(x[gix("sa",r1,r2,p)],(eta-1)/eta)
473 + r1v * pow(x[gix("sl",r1,r2,p)],(eta-1)/eta),
474 eta/(eta-1)
475 );
477
478 // mkteq17(i,p_tr).. RVAR('sl',i,p_tr) =l= Kt(i,p_tr); // h16 in the presentation paper
480 k = gpd("k",l2r[r1][r2],secPr[p]);
481 g[cix] = x[gix("sl",r1,r2,p+nPriPr)]-k;
483
484 // mkeq26(i,prd,j).. RVAR('pl',j,prd)-RVAR('pl',i,prd)-CT(i,j,prd) =l= 0;
486 for (uint r2To=0;r2To<l2r[r1].size();r2To++){
487 cix = gix(12, r1, r2, p,r2To); // attenction we must redefine it, as we are now in a r2to loop
488 ct = (gpd("ct",l2r[r1][r2],allPr[p],DATA_NOW,i2s(l2r[r1][r2To])) * gpd("pol_tcSub",l2r[r1][r2],allPr[p])) ;
489 g[cix] = (x[gix("pl",r1,r2To,p)]-x[gix("pl",r1,r2,p)]-ct);
490 }
492
493 // mkteq25(i,p_tr).. sum(p_pr, a(p_pr,p_tr)*RVAR('pl',i,p_pr))+m(i,p_tr) =g= (RVAR('pl',i,p_tr)); // price of raw products + transf cost > trasf product
495 mv = (gpd("m",l2r[r1][r2],secPr[p]) * gpd("pol_trSub",l2r[r1][r2],secPr[p]));
496 g[cix] = mv - x[gix("pl",r1,r2,p+nPriPr)];
497 for (uint p2=0;p2<priPr.size();p2++){
498 a = gpd("a",l2r[r1][r2],priPr[p2],DATA_NOW,secPr[p]);
499 g[cix] += a * x[gix("pl",r1,r2,p2)];
500 }
502
503// // mkteq18(i,p_pr).. RVAR('sa',i,p_pr)+RVAR('sl',i,p_pr) =l= dispor(i,p_pr); // total supply lower than the available stock
504// CONSTRAIN_START_LOOP(priPr,14)
505// in = gpd("in",l2r[r1][r2],priPr[p]);
506// double d1 = gix("sa",r1,r2,p);
507// double d2 = gix("sl",r1,r2,p);
508// g[cix] = x[gix("sa",r1,r2,p)]+x[gix("sl",r1,r2,p)]-in;
509// CONSTRAIN_END_LOOP
510
511 // resbounds(i, p_pr_comb).. RVAR('sa',i,p_pr)+RVAR('sl',i,p_pr) =l= dispor(i,p_pr); // total supply lower than the available stock - FOR all combination subsets of ins
513 //ModelRegion* REG = MTHREAD->MD->getRegion(l2r[r1][r2]); // possibly slower
514 //in = REG->inResByAnyCombination[p];
515 in = ins[r1][r2][p];
516 //if(p==0){
517 // in = 1.0; // workaround to lead -1<0 rather than 0<0 for the first (empty) subset - notneeded
518 //}
519 g[cix] = -in;
520 for(uint i=0;i<priPrCombs[p].size();i++){
521 g[cix] += x[gix("sa",r1,r2,priPrCombs[p][i])]+x[gix("sl",r1,r2,priPrCombs[p][i])];
522 }
523 g[cix] -= overharvestingAllowance; //0.02 don't work always, expecially intermediate scnearios, 0.1 seems to work but produce a large artefact 20160219: made it a parameter
524
526
527 //CONSTRAIN_START_LOOP(priPr,15)
528 // g[cix] = x[gix("st",r1,r2,p)]-(x[gix("sl",r1,r2,p)]+x[gix("sa",r1,r2,p)]);
529 //CONSTRAIN_END_LOOP
530
531 return true;
532}
533
534
535// ******** NOTHING TO DO BELOW THIS LINE ********************************
536
538 MTHREAD = MTHREAD_h;
539 nVar = 0;
540 nCons = 0;
541 debugRunOnce = false;
542 initOpt = true;
543}
544
546
547}
548
549
550bool
551Opt::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
552 Index& nnz_h_lag, IndexStyleEnum& index_style){
553
554
555 if(initOpt){
556 // does this initialisation code only once
557 priPr = MTHREAD->MD->getStringVectorSetting("priProducts");
558 secPr = MTHREAD->MD->getStringVectorSetting("secProducts");
559 othPr = MTHREAD->MD->getStringVectorSetting("othExogenousProducts");
560 allPr = priPr;
561 allPr.insert( allPr.end(), secPr.begin(), secPr.end() );
562 nPriPr = priPr.size();
563 nSecPr = secPr.size();
564 nAllPr = allPr.size();
565 nOthPr = othPr.size();
566 std::vector<int> l1regIds = MTHREAD->MD->getRegionIds(1, true);
567 nL2r = MTHREAD->MD->getRegionIds(2, true).size();
568 firstYear = MTHREAD->MD->getIntSetting("initialYear");
570 worldCodeLev2 = MTHREAD->MD->getIntSetting("worldCodeLev2");
571
572 for(uint i=0;i<l1regIds.size();i++){
573 std::vector<int> l2ChildrenIds;
574 ModelRegion* l1Region = MTHREAD->MD->getRegion(l1regIds[i]);
575 std::vector<ModelRegion*> l2Childrens = l1Region->getChildren(true);
576 for(uint j=0;j<l2Childrens.size();j++){
577 l2ChildrenIds.push_back(l2Childrens[j]->getRegId());
578 }
579 if(l2ChildrenIds.size()){
580 l2r.push_back(l2ChildrenIds);
581 }
582 }
583
584 // Create a vector with all possible combinations of primary products
586 nPriPrCombs = priPrCombs.size();
587
588 // put the variables and their domain in the vars map
590
591 // declaring the contrains...
593
594 // calculate number of variables and constrains..
596
597 // cache initial positions (variables and constrains)..
599
600 // cache initial positions (variables and constrains)..
602
603 //tempDebug();
604
605 //debugPrintParameters();
606
607 } // finish initialisation things to be done only the first year
608
609 previousYear = MTHREAD->SCD->getYear()-1; // this has to be done EVERY years !!
610
611 n = nVar; // 300; // nVar;
612 m = nCons; // 70; // nCons;
613
614 overharvestingAllowance = MTHREAD->MD->getDoubleSetting("overharvestingAllowance",DATA_NOW);
615
617
618 generate_tapes(n, m, nnz_jac_g, nnz_h_lag);
619
620 //if(initOpt){
621 // calculateSparsityPatternJ();
622 // calculateSparsityPatternH();
623 //tempDebug();
624 //}
625
626 // use the C style indexing (0-based)
627 index_style = C_STYLE;
628
629 initOpt=false;
630 return true;
631}
632
633bool
634Opt::get_bounds_info(Index n, Number* x_l, Number* x_u, Index m, Number* g_l, Number* g_u){
635
636 // Set the bounds for the endogenous variables..
637 for (Index i=0; i<n; i++) {
638 x_l[i] = getBoundByIndex(LBOUND,i);
639 x_u[i] = getBoundByIndex(UBOUND,i);
640 }
641
642 // Set the bounds for the constraints..
643 for (Index i=0; i<m; i++) {
644 int direction = getConstrainDirectionByIndex(i);
645 switch (direction){
646 case CONSTR_EQ:
647 g_l[i] = 0.;
648 g_u[i] = 0.;
649 break;
650 case CONSTR_LE0:
651 g_l[i] = -2e19;
652 g_u[i] = 0.;
653 break;
654 case CONSTR_GE0:
655 g_l[i] = 0.;
656 g_u[i] = 2e19;
657 break;
658 }
659 }
660 return true;
661}
662
663bool
664Opt::get_starting_point(Index n, bool init_x, Number* x, bool init_z, Number* z_L, Number* z_U,
665 Index m, bool init_lambda, Number* lambda){
666
667 // function checked on 20120724 on a subset of 3 regions and 4 products. All variables initial values are correctly those outputed by gams in 2006.
668 //int thisYear = MTHREAD->SCD->getYear();
669 //int initialOptYear = MTHREAD->MD->getIntSetting("initialOptYear");
670 //if(thisYear != initialOptYear) return true;
671
672 //msgOut(MSG_DEBUG,"Giving optimising variables previous years value as starting point");
673 // Here, we assume we only have starting values for x, if you code
674 // your own NLP, you can provide starting values for the others if
675 // you wish.
676 assert(init_x == true);
677 assert(init_z == false);
678 assert(init_lambda == false);
679
680 VarMap::iterator viter;
681
682 // fixing the starting points for each variable at the level of the previous years
683 for (viter = vars.begin(); viter != vars.end(); ++viter) {
684 //string debugs = viter->first;
685 int vdomtype = viter->second.domain;
686 if(vdomtype==DOM_PRI_PR){
687 for(uint r1=0;r1<l2r.size();r1++){
688 for(uint r2=0;r2<l2r[r1].size();r2++){
689 for(uint p=0;p<priPr.size();p++){
690 x[gix(viter->first,r1,r2,p)]= gpd(viter->first,l2r[r1][r2],priPr[p],previousYear);
691 }
692 }
693 }
694 } else if (vdomtype==DOM_SEC_PR) {
695 for(uint r1=0;r1<l2r.size();r1++){
696 for(uint r2=0;r2<l2r[r1].size();r2++){
697 for(uint p=0;p<secPr.size();p++){
698 x[gix(viter->first,r1,r2,p)]= gpd(viter->first,l2r[r1][r2],secPr[p],previousYear);
699 }
700 }
701 }
702 } else if (vdomtype==DOM_ALL_PR) {
703 for(uint r1=0;r1<l2r.size();r1++){
704 for(uint r2=0;r2<l2r[r1].size();r2++){
705 for(uint p=0;p<allPr.size();p++){
706 x[gix(viter->first,r1,r2,p)]= gpd(viter->first,l2r[r1][r2],allPr[p],previousYear);
707 }
708 }
709 }
710 } else if (vdomtype==DOM_R2_ALL_PR) {
711 for(uint r1=0;r1<l2r.size();r1++){
712 for(uint r2=0;r2<l2r[r1].size();r2++){
713 for(uint p=0;p<allPr.size();p++){
714 for(uint r2To=0;r2To<l2r[r1].size();r2To++){
715 x[gix(viter->first,r1,r2,p,r2To)]= gpd(viter->first,l2r[r1][r2],allPr[p],previousYear,i2s(l2r[r1][r2To]));
716 }
717 }
718 }
719 }
720 } else {
721 msgOut(MSG_CRITICAL_ERROR,"Try to setting the initial value of a variable of unknow type ("+viter->first+")");
722 }
723 }
724
725 //msgOut(MSG_DEBUG,"Finisced initial value assignments");
726
727 return true;
728}
729
730
731void
732Opt::finalize_solution(SolverReturn status,
733 Index n, const Number* x, const Number* z_L, const Number* z_U,
734 Index m, const Number* g, const Number* lambda,
735 Number obj_value, const IpoptData* ip_data, IpoptCalculatedQuantities* ip_cq){
736
737 printf("\n\nObjective value\n");
738 printf("f(x*) = %e\n", obj_value);
739
740 // --> here is where to code the assignment of optimal values to to spd()
741
742 VarMap::iterator viter;
743
744 // fixing the starting points for each variable at the level of the previous years
745 for (viter = vars.begin(); viter != vars.end(); ++viter) {
746 //string debugs = viter->first;
747 int vdomtype = viter->second.domain;
748 if(vdomtype==DOM_PRI_PR){
749 for(uint r1=0;r1<l2r.size();r1++){
750 for(uint r2=0;r2<l2r[r1].size();r2++){
751 for(uint p=0;p<priPr.size();p++){
752 spd(x[gix(viter->first,r1,r2,p)],viter->first,l2r[r1][r2],priPr[p]);
753 }
754 }
755 }
756 } else if (vdomtype==DOM_SEC_PR) {
757 for(uint r1=0;r1<l2r.size();r1++){
758 for(uint r2=0;r2<l2r[r1].size();r2++){
759 for(uint p=0;p<secPr.size();p++){
760 spd(x[gix(viter->first,r1,r2,p)],viter->first,l2r[r1][r2],secPr[p]);
761
762 }
763 }
764 }
765 } else if (vdomtype==DOM_ALL_PR) {
766 for(uint r1=0;r1<l2r.size();r1++){
767 for(uint r2=0;r2<l2r[r1].size();r2++){
768 for(uint p=0;p<allPr.size();p++){
769 spd(x[gix(viter->first,r1,r2,p)],viter->first,l2r[r1][r2],allPr[p]);
770 }
771 }
772 }
773 } else if (vdomtype==DOM_R2_ALL_PR) {
774 for(uint r1=0;r1<l2r.size();r1++){
775 for(uint r2=0;r2<l2r[r1].size();r2++){
776 for(uint p=0;p<allPr.size();p++){
777 for(uint r2To=0;r2To<l2r[r1].size();r2To++){
778 //if(x[gix(viter->first,r1,r2,p,r2To)] > 0){
779 // cout << l2r[r1][r2] << "\t" << allPr[p] << "\t" << l2r[r1][r2To] << "\t" << x[gix(viter->first,r1,r2,p,r2To)] << endl;
780 //}
781 spd(x[gix(viter->first,r1,r2,p,r2To)],viter->first,l2r[r1][r2],allPr[p],DATA_NOW,false,i2s(l2r[r1][r2To]));
782 }
783 }
784 }
785 }
786 } else {
787 msgOut(MSG_CRITICAL_ERROR,"Try to setting the solved value of a variable of unknow type ("+viter->first+")");
788 }
789 }
790
791 // memory deallocation of ADOL-C variables
792 delete[] x_lam;
793
794 free(rind_g);
795 free(cind_g);
796
797 delete[] rind_L;
798 delete[] cind_L;
799
800 free(rind_L_total);
801 free(cind_L_total);
802 free(jacval);
803 free(hessval);
804
805 for (int i=0;i<n+m+1;i++) {
806 free(HP_t[i]);
807 }
808 free(HP_t);
809
810}
811
812//*************************************************************************
813//
814//
815// Nothing has to be changed below this point !!
816//
817//
818//*************************************************************************
819
820
821bool
822Opt::eval_f(Index n, const Number* x, bool new_x, Number& obj_value){
823 eval_obj(n,x,obj_value);
824
825 return true;
826}
827
828bool
829Opt::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f){
830
831 gradient(tag_f,n,x,grad_f);
832
833 return true;
834}
835
836bool
837Opt::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g){
838
839 eval_constraints(n,x,m,g);
840
841 return true;
842}
843
844bool
845Opt::eval_jac_g(Index n, const Number *x, bool new_x,Index m, Index nele_jac,
846 Index* iRow, Index *jCol, Number* values){
847 if (values == NULL) {
848 // return the structure of the jacobian
849
850 for(Index idx=0; idx<nnz_jac; idx++)
851 {
852 iRow[idx] = rind_g[idx];
853 jCol[idx] = cind_g[idx];
854 }
855 }
856 else {
857 // return the values of the jacobian of the constraints
858
859 sparse_jac(tag_g, m, n, 1, x, &nnz_jac, &rind_g, &cind_g, &jacval, options_g);
860
861 for(Index idx=0; idx<nnz_jac; idx++)
862 {
863 values[idx] = jacval[idx];
864
865 }
866 }
867 return true;
868}
869
870bool
871Opt::eval_h(Index n, const Number* x, bool new_x, Number obj_factor, Index m, const Number* lambda,
872 bool new_lambda, Index nele_hess, Index* iRow, Index* jCol, Number* values){
873
874 //return false;
875
876 if (values == NULL) {
877 // return the structure. This is a symmetric matrix, fill the lower left
878 // triangle only.
879
880 for(Index idx=0; idx<nnz_L; idx++)
881 {
882 iRow[idx] = rind_L[idx];
883 jCol[idx] = cind_L[idx];
884 }
885 }
886 else {
887 // return the values. This is a symmetric matrix, fill the lower left
888 // triangle only
889
890 for(Index idx = 0; idx<n ; idx++)
891 x_lam[idx] = x[idx];
892 for(Index idx = 0; idx<m ; idx++)
893 x_lam[n+idx] = lambda[idx];
894 x_lam[n+m] = obj_factor;
895
896 sparse_hess(tag_L, n+m+1, 1, x_lam, &nnz_L_total, &rind_L_total, &cind_L_total, &hessval, options_L);
897
898 Index idx = 0;
899 for(Index idx_total = 0; idx_total <nnz_L_total ; idx_total++)
900 {
901 if((rind_L_total[idx_total] < (unsigned int) n) && (cind_L_total[idx_total] < (unsigned int) n))
902 {
903 values[idx] = hessval[idx_total];
904 idx++;
905 }
906 }
907 }
908
909 return true;
910
911 //return false;
912}
913
914
915//*************** ADOL-C part ***********************************
916
917void
918Opt::generate_tapes(Index n, Index m, Index& nnz_jac_g, Index& nnz_h_lag){
919 /// Copied from http://bocop.org/
920 Number *xp = new double[n];
921 Number *lamp = new double[m];
922 Number *zl = new double[m];
923 Number *zu = new double[m];
924
925 adouble *xa = new adouble[n];
926 adouble *g = new adouble[m];
927 adouble *lam = new adouble[m];
928 adouble sig;
929 adouble obj_value;
930
931 double dummy;
932// double *jacval;
933
934 int i,j,k,l,ii;
935
936 x_lam = new double[n+m+1];
937
938// cout << " Avant get_start" << endl;
939 get_starting_point(n, 1, xp, 0, zl, zu, m, 0, lamp);
940// cout << " Apres get_start" << endl;
941
942 //if(initOpt){ // that's funny, if I use this I get it slighly longer times, whatever I then use trace_off() or trace_off(1) (save to disk, seems unnecessary). If I use regenerated tapes I have also slighly inaccurate results.
943 trace_on(tag_f);
944
945 for(Index idx=0;idx<n;idx++)
946 xa[idx] <<= xp[idx];
947
948 eval_obj(n,xa,obj_value);
949
950 obj_value >>= dummy;
951
952 trace_off();
953
954 trace_on(tag_g);
955
956 for(Index idx=0;idx<n;idx++)
957 xa[idx] <<= xp[idx];
958
959 eval_constraints(n,xa,m,g);
960
961
962 for(Index idx=0;idx<m;idx++)
963 g[idx] >>= dummy;
964
965 trace_off();
966
967 trace_on(tag_L);
968
969 for(Index idx=0;idx<n;idx++)
970 xa[idx] <<= xp[idx];
971 for(Index idx=0;idx<m;idx++)
972 lam[idx] <<= 1.0;
973 sig <<= 1.0;
974
975 eval_obj(n,xa,obj_value);
976
977 obj_value *= sig;
978 eval_constraints(n,xa,m,g);
979
980 for(Index idx=0;idx<m;idx++)
981 obj_value += g[idx]*lam[idx];
982
983 obj_value >>= dummy;
984
985 trace_off();
986 //} // end of if initOpt()
987
988
989
990 rind_g = NULL;
991 cind_g = NULL;
992
993 options_g[0] = 0; /* sparsity pattern by index domains (default) */
994 options_g[1] = 0; /* safe mode (default) */
995 options_g[2] = -1; /* &jacval is not computed */
996 options_g[3] = 0; /* column compression (default) */
997
998 jacval=NULL;
999
1000 sparse_jac(tag_g, m, n, 0, xp, &nnz_jac, &rind_g, &cind_g, &jacval, options_g);
1001
1002 options_g[2] = 0;
1003 nnz_jac_g = nnz_jac;
1004
1005 unsigned int **JP_f=NULL; /* compressed block row storage */
1006 unsigned int **JP_g=NULL; /* compressed block row storage */
1007 unsigned int **HP_f=NULL; /* compressed block row storage */
1008 unsigned int **HP_g=NULL; /* compressed block row storage */
1009 unsigned int *HP_length=NULL; /* length of arrays */
1010 unsigned int *temp=NULL; /* help array */
1011
1012 int ctrl_H;
1013
1014 JP_f = (unsigned int **) malloc(sizeof(unsigned int*));
1015 JP_g = (unsigned int **) malloc(m*sizeof(unsigned int*));
1016 HP_f = (unsigned int **) malloc(n*sizeof(unsigned int*));
1017 HP_g = (unsigned int **) malloc(n*sizeof(unsigned int*));
1018 HP_t = (unsigned int **) malloc((n+m+1)*sizeof(unsigned int*));
1019 HP_length = (unsigned int *) malloc((n)*sizeof(unsigned int));
1020 ctrl_H = 0;
1021
1022 hess_pat(tag_f, n, xp, HP_f, ctrl_H);
1023
1024 indopro_forward_safe(tag_f, 1, n, xp, JP_f);
1025 indopro_forward_safe(tag_g, m, n, xp, JP_g);
1026 nonl_ind_forward_safe(tag_g, m, n, xp, HP_g);
1027
1028 for (i=0;i<n;i++)
1029 {
1030 if (HP_f[i][0]+HP_g[i][0]!=0)
1031 {
1032 if (HP_f[i][0]==0) // number of non zeros in the i-th row
1033 {
1034 HP_t[i] = (unsigned int *) malloc((HP_g[i][0]+HPOFF)*sizeof(unsigned int));
1035 for(j=0;j<=(int) HP_g[i][0];j++)
1036 {
1037 HP_t[i][j] = HP_g[i][j];
1038 }
1039 HP_length[i] = HP_g[i][0]+HPOFF;
1040 }
1041 else
1042 {
1043 if (HP_g[i][0]==0) // number of non zeros in the i-th row
1044 {
1045 HP_t[i] = (unsigned int *) malloc((HP_f[i][0]+HPOFF)*sizeof(unsigned int));
1046 for(j=0;j<=(int) HP_f[i][0];j++)
1047 {
1048 HP_t[i][j] = HP_f[i][j];
1049 }
1050 HP_length[i] = HP_f[i][0]+HPOFF;
1051 }
1052 else
1053 {
1054 HP_t[i] = (unsigned int *) malloc((HP_f[i][0]+HP_g[i][0]+HPOFF)*sizeof(unsigned int));
1055 k = l = j = 1;
1056 while ((k<=(int) HP_f[i][0]) && (l <= (int) HP_g[i][0]))
1057 {
1058 if (HP_f[i][k] < HP_g[i][l])
1059 {
1060 HP_t[i][j]=HP_f[i][k];
1061 j++; k++;
1062 }
1063 else
1064 {
1065 if (HP_f[i][k] == HP_g[i][l])
1066 {
1067 HP_t[i][j]=HP_f[i][k];
1068 l++;j++;k++;
1069 }
1070 else
1071 {
1072 HP_t[i][j]=HP_g[i][l];
1073 j++;l++;
1074 }
1075 }
1076 } // end while
1077
1078 // Fill the end of the vector if HP_g[i][0] < HP_f[i][0]
1079 for(ii=k;ii<=(int) HP_f[i][0];ii++)
1080 {
1081 HP_t[i][j] = HP_f[i][ii];
1082 j++;
1083 }
1084
1085 // Fill the end of the vector if HP_f[i][0] < HP_g[i][0]
1086 for(ii=l;ii<=(int) HP_g[i][0];ii++)
1087 {
1088 HP_t[i][j] = HP_g[i][ii];
1089 j++;
1090 }
1091
1092 }
1093 }
1094 HP_t[i][0]=j-1; // set the first element with the number of non zeros in the i-th line
1095 HP_length[i] = HP_f[i][0]+HP_g[i][0]+HPOFF; // length of the i-th line
1096 }
1097 else
1098 {
1099 HP_t[i] = (unsigned int *) malloc((HPOFF+1)*sizeof(unsigned int));
1100 HP_t[i][0]=0;
1101 HP_length[i]=HPOFF;
1102 }
1103
1104// if (i==(int)n-1)
1105// {
1106// cout << " DISPLAY FINAL TIME HP : " << endl;
1107// for (ii=0;ii<=(int)HP_length[i];ii++)
1108// cout << " -------> HP[last][" << ii << "] = " << HP_t[i][ii] << endl;
1109// }
1110 }
1111
1112// cout << " Avant les boucles" << endl;
1113// cout << " m = " << m << endl;
1114
1115 for (i=0;i<m;i++)
1116 {
1117// cout << i << " --> nnz JP_g = " << JP_g[i][0]+1 << " -- ";
1118 HP_t[n+i] = (unsigned int *) malloc((JP_g[i][0]+1)*sizeof(unsigned int));
1119 HP_t[n+i][0]=JP_g[i][0];
1120
1121// cout << HP_t[n+i][0] << endl;
1122
1123 for(j=1;j<= (int) JP_g[i][0];j++)
1124 {
1125 HP_t[n+i][j]=JP_g[i][j];
1126// cout << " ---------> " << HP_t[n+i][j] << endl;
1127// cout << " --> HP_length[" << JP_g[i][j] << "] = " << HP_length[JP_g[i][j]] << " -- HP_t[" << JP_g[i][j] << "][0] = " << HP_t[JP_g[i][j]][0]+1 << endl;
1128 // We write the rows allocated in the previous "for" loop
1129 // If the memory allocated for the row is not big enough :
1130 if (HP_length[JP_g[i][j]] <= HP_t[JP_g[i][j]][0]+1) //! test avec "<=" (avant on avait "<" : bug, acces memoire non allouee)
1131 {
1132// cout << " ---------> WARNING " << endl;
1133// cout << " At index " << JP_g[i][j] << endl;
1134
1135
1136 // save a copy of existing vector elements :
1137 temp = (unsigned int *) malloc((HP_t[JP_g[i][j]][0]+1)*sizeof(unsigned int));
1138 for(l=0;l<=(int)HP_t[JP_g[i][j]][0];l++)
1139 {
1140 temp[l] = HP_t[JP_g[i][j]][l]; //! valgrind : invalid read
1141// cout << " -------> l = " << l << " -- " << temp[l] << endl;
1142 }
1143
1144// cout << " -----------> DISPLAY " << endl;
1145// for(l=0;l<=(int)HP_t[JP_g[i][j]][0];l++)
1146// {
1147// temp[l] = HP_t[JP_g[i][j]][l]; //! valgrind : invalid read & write
1148// cout << " -------> HP[machin][" << l << "] = " << HP_t[JP_g[i][j]][l] << endl; //! valgrind : invalid read
1149// }
1150
1151
1152 // Free existing row, and allocate more memory for it :
1153// cout << " Avant free --> pointeur = " <<HP_t[JP_g[i][j]]<< endl;
1154 unsigned int machin = JP_g[i][j];
1155 free(HP_t[machin]); // !Problem double free or corruption
1156// cout << " Apres free --> pointeur = " <<HP_t[JP_g[i][j]]<< endl;
1157
1158 HP_t[JP_g[i][j]] = (unsigned int *) malloc(2*HP_length[JP_g[i][j]]*sizeof(unsigned int));
1159 HP_length[JP_g[i][j]] = 2*HP_length[JP_g[i][j]];
1160
1161 // Put back the values in this bigger vector :
1162 for(l=0;l<=(int)temp[0];l++)
1163 HP_t[JP_g[i][j]][l] =temp[l];
1164 free(temp);
1165
1166// HP_t[JP_g[i][j]] = (unsigned int*) realloc (HP_t[JP_g[i][j]], 2*HP_length[JP_g[i][j]] * sizeof(unsigned int));
1167// HP_length[JP_g[i][j]] = 2*HP_length[JP_g[i][j]];
1168 }
1169 HP_t[JP_g[i][j]][0] = HP_t[JP_g[i][j]][0]+1; // The size of the row is one greater than before
1170 HP_t[JP_g[i][j]][HP_t[JP_g[i][j]][0]] = i+n; // Now adding the element at the end //! valgrind : invalid write
1171 }
1172 }
1173// cout << " Apres les boucles" << endl;
1174
1175 for(j=1;j<= (int) JP_f[0][0];j++)
1176 {
1177 if (HP_length[JP_f[0][j]] <= HP_t[JP_f[0][j]][0]+1) //! test avec "<=" (pour etre coherent avec la remarque ci dessus, mais pas de cas test, a verifier)
1178 {
1179 temp = (unsigned int *) malloc((HP_t[JP_f[0][j]][0])*sizeof(unsigned int));
1180 for(l=0;l<=(int)HP_t[JP_f[0][j]][0];l++)
1181 temp[l] = HP_t[JP_f[0][j]][l];
1182 free(HP_t[JP_f[0][j]]);
1183 HP_t[JP_f[0][j]] = (unsigned int *) malloc(2*HP_length[JP_f[0][j]]*sizeof(unsigned int));
1184 HP_length[JP_f[0][j]] = 2*HP_length[JP_f[0][j]];
1185 for(l=0;l<=(int)temp[0];l++)
1186 HP_t[JP_f[0][j]][l] =temp[l];
1187 free(temp);
1188 }
1189 HP_t[JP_f[0][j]][0] = HP_t[JP_f[0][j]][0]+1;
1190 HP_t[JP_f[0][j]][HP_t[JP_f[0][j]][0]] = n+m;
1191 }
1192
1193 HP_t[n+m] = (unsigned int *) malloc((JP_f[0][0]+2)*sizeof(unsigned int));
1194 HP_t[n+m][0]=JP_f[0][0]+1;
1195 for(j=1;j<= (int) JP_f[0][0];j++)
1196 HP_t[n+m][j]=JP_f[0][j];
1197 HP_t[n+m][JP_f[0][0]+1]=n+m;
1198
1199 set_HP(tag_L,n+m+1,HP_t); // set sparsity pattern for the Hessian
1200
1201 nnz_h_lag = 0;
1202 for (i=0;i<n;i++)
1203 {
1204 for (j=1;j<=(int) HP_t[i][0];j++)
1205 if ((int) HP_t[i][j] <= i)
1206 nnz_h_lag++;
1207 free(HP_f[i]);
1208 free(HP_g[i]);
1209 }
1210 nnz_L = nnz_h_lag;
1211
1212 options_L[0] = 0;
1213 options_L[1] = 1;
1214
1215 rind_L_total = NULL;
1216 cind_L_total = NULL;
1217 hessval = NULL;
1218
1219 sparse_hess(tag_L, n+m+1, -1, xp, &nnz_L_total, &rind_L_total, &cind_L_total, &hessval, options_L);
1220
1221 rind_L = new unsigned int[nnz_L];
1222 cind_L = new unsigned int[nnz_L];
1223 rind_L_total = (unsigned int*) malloc(nnz_L_total*sizeof(unsigned int)); //! test
1224 cind_L_total = (unsigned int*) malloc(nnz_L_total*sizeof(unsigned int)); //! test
1225
1226 unsigned int ind = 0;
1227
1228 for (int i=0;i<n;i++)
1229 for (unsigned int j=1;j<=HP_t[i][0];j++)
1230 {
1231 if (((int) HP_t[i][j]>=i) &&((int) HP_t[i][j]<n))
1232 {
1233 rind_L[ind] = i;
1234 cind_L[ind++] = HP_t[i][j];
1235 }
1236 }
1237
1238 ind = 0;
1239 for (int i=0;i<n+m+1;i++)
1240 for (unsigned int j=1;j<=HP_t[i][0];j++)
1241 {
1242 if ((int) HP_t[i][j]>=i)
1243 {
1244 rind_L_total[ind] = i;
1245 cind_L_total[ind++] = HP_t[i][j];
1246 }
1247 }
1248
1249 for (i=0;i<m;i++) {
1250 free(JP_g[i]);
1251 }
1252
1253 free(JP_f[0]);
1254 free(JP_f);
1255 free(JP_g);
1256 free(HP_f);
1257 free(HP_g);
1258 free(HP_length);
1259
1260 delete[] lam;
1261 delete[] g;
1262 delete[] xa;
1263 delete[] zu;
1264 delete[] zl;
1265 delete[] lamp;
1266 delete[] xp;
1267
1268}
1269
1270
1271// *************** FFSM OPT specific part ***********************************
1272
1273const int
1274Opt::gip(const string &varName) const{ // get initial position
1275 map<string, int>::const_iterator p;
1276 p=initPos.find(varName);
1277 if(p != initPos.end()) {
1278 return p->second;
1279 }
1280 else {
1281 msgOut(MSG_CRITICAL_ERROR, "Asking the initial position in the concatenated array of a variable ("+varName+") that doesn't exist!");
1282 return 0;
1283 }
1284}
1285
1286const int
1287Opt::gip(const int &cn) const { // get initial position
1288 return cInitPos.at(cn);
1289}
1290
1291const int
1292Opt::gdt(const string &varName){ // get domain type
1293 VarMap::const_iterator p;
1294 p=vars.find(varName);
1295 if(p != vars.end()) {
1296 return p->second.domain;
1297 }
1298 else {
1299 msgOut(MSG_CRITICAL_ERROR, "Asking the domain type of a variable ("+varName+") that doesn't exist!");
1300 return 0;
1301 }
1302}
1303
1304const int
1305Opt::gdt(const int &cn){ // get domain type
1306 return cons.at(cn).domain;
1307}
1308
1309template<class T> const int
1310Opt::gix_uncached(const T &v_or_c, int r1Ix, int r2Ix, int prIx, int r2IxTo){
1311
1312 // attenction, for computational reason we are not checking the call is within vectors limits!!!
1313
1314 int dType = gdt(v_or_c);
1315 int othCountriesRegions = 0;
1316 int othCountriesRegions_r2case = 0;
1317 for (uint i=0;i<r1Ix;i++){
1318 othCountriesRegions += l2r[i].size();
1319 }
1320 for (uint i=0;i<r1Ix;i++){
1321 othCountriesRegions_r2case +=l2r[i].size()*l2r[i].size();
1322 }
1323
1324 switch (dType){
1325 case DOM_PRI_PR:
1326 return gip(v_or_c)+(othCountriesRegions+r2Ix)*nPriPr+prIx;
1327 case DOM_SEC_PR:
1328 return gip(v_or_c)+(othCountriesRegions+r2Ix)*nSecPr+prIx;;
1329 case DOM_ALL_PR:
1330 return gip(v_or_c)+(othCountriesRegions+r2Ix)*nAllPr+prIx;
1331 case DOM_R2_PRI_PR:
1332 return gip(v_or_c)+(othCountriesRegions_r2case)*nAllPr+(r2Ix*nPriPr+prIx)*l2r[r1Ix].size()+r2IxTo;
1333 case DOM_R2_SEC_PR:
1334 return gip(v_or_c)+(othCountriesRegions_r2case)*nAllPr+(r2Ix*nSecPr+prIx)*l2r[r1Ix].size()+r2IxTo;
1335 case DOM_R2_ALL_PR:
1336 return gip(v_or_c)+(othCountriesRegions_r2case)*nAllPr+(r2Ix*nAllPr+prIx)*l2r[r1Ix].size()+r2IxTo; // new 20120814, looping r1,r2,p,r2to
1337 // initial position + (other countries region pairs + same country other regions from pair + regions to)* number of all products+product
1338 //return gip(v_or_c)+(othCountriesRegions_r2case+r2Ix*l2r[r1Ix].size()+r2IxTo)*nAllPr+prIx; // looping r1,r2,r2to,p
1339 case DOM_SCALAR:
1340 return gip(v_or_c);
1342 return gip(v_or_c)+(othCountriesRegions+r2Ix)*nPriPrCombs+prIx;
1343 default:
1344 msgOut(MSG_CRITICAL_ERROR,"Try to calculate the position of a variable (or constrain) of unknow type.");
1345 return 0;
1346 }
1347}
1348
1349
1350const int
1351Opt::gix(const string &varName, const int& r1Ix, const int& r2Ix, const int& prIx, const int& r2IxTo) const{
1352 // attenction, for computational reasons we are not checking the call is within vectors limits!!!
1353 map <string, vector < vector < vector < vector <int> > > > >::const_iterator p;
1354 p=vpositions.find(varName);
1355 if(p != vpositions.end()) {
1356 return p->second[r1Ix][r2Ix][prIx][r2IxTo];
1357 }
1358 else {
1359 msgOut(MSG_CRITICAL_ERROR, "Asking the position of a variable ("+varName+") that doesn't exist!");
1360 return 0;
1361 }
1362}
1363
1364const int
1365Opt::gix(const int &cn, const int& r1Ix, const int& r2Ix, const int& prIx, const int& r2IxTo) const{
1366 return cpositions[cn][r1Ix][r2Ix][prIx][r2IxTo];
1367}
1368
1369void
1371 int vInitialPosition = 0;
1372 int cInitialPosition = 0;
1373 VarMap::iterator viter;
1374 for (viter = vars.begin(); viter != vars.end(); ++viter) {
1375 initPos.insert(pair<string, int>(viter->first, vInitialPosition));
1376 initPos_rev.insert(pair<int, string>(vInitialPosition,viter->first));
1377 vInitialPosition += getDomainElements(viter->second.domain);
1378 }
1379 for (uint i=0;i<cons.size();i++){
1380 cInitPos.push_back(cInitialPosition);
1381 cInitialPosition += getDomainElements(cons[i].domain);
1382 }
1383}
1384
1385void
1387
1388 // variables..
1389 VarMap::iterator viter;
1390 for (viter = vars.begin(); viter != vars.end(); ++viter) {
1391 vpositions.insert(pair<string, vector < vector < vector < vector <int> > > > >(viter->first, buildPositionVector(viter->first, viter->second.domain)));
1392 }
1393 // constrains..
1394 for (uint i=0; i<cons.size();i++){
1395 cpositions.push_back(buildPositionVector(i, cons[i].domain));
1396 }
1397
1398}
1399
1400template<class T> vector < vector < vector < vector <int> > > >
1401Opt::buildPositionVector(const T &v_or_c, int dType){
1402 int pVectorSize;
1403
1404 switch (dType){
1405 case DOM_PRI_PR:
1406 pVectorSize= priPr.size();
1407 break;
1408 case DOM_SEC_PR:
1409 pVectorSize= secPr.size();
1410 break;
1411 case DOM_ALL_PR:
1412 pVectorSize= allPr.size();
1413 break;
1414 case DOM_R2_PRI_PR:
1415 pVectorSize= priPr.size();
1416 break;
1417 case DOM_R2_SEC_PR:
1418 pVectorSize= secPr.size();
1419 break;
1420 case DOM_R2_ALL_PR:
1421 pVectorSize= allPr.size();
1422 break;
1423 case DOM_SCALAR:
1424 pVectorSize= allPr.size(); // it will simply fill the matrix all with the same value (the ip)
1425 break;
1427 pVectorSize= priPrCombs.size();
1428 break;
1429 default:
1430 msgOut(MSG_CRITICAL_ERROR,"Try to build the position of a variable (or contrain) of unknow type.");
1431 }
1432
1433
1434 vector < vector < vector < vector <int> > > > positionsToAdd;
1435 for(uint r1=0;r1<l2r.size();r1++){
1436 vector < vector < vector <int> > > dim1;
1437 for(uint r2=0;r2<l2r[r1].size();r2++){
1438 vector < vector <int> > dim2;
1439 for(uint p=0;p<pVectorSize;p++){
1440 vector <int> dim3;
1441 for(uint r2To=0;r2To<l2r[r1].size();r2To++){
1442 dim3.push_back(gix_uncached(v_or_c,r1,r2,p,r2To));
1443 }
1444 dim2.push_back(dim3);
1445 }
1446 dim1.push_back(dim2);
1447 }
1448 positionsToAdd.push_back(dim1);
1449 }
1450 return positionsToAdd;
1451}
1452
1453
1454void
1456 // calculating the number of variables and the initial positions in the concatenated array..
1457 nVar = 0;
1458 VarMap::iterator viter;
1459 for (viter = vars.begin(); viter != vars.end(); ++viter) {
1460 nVar += getDomainElements(viter->second.domain);
1461 }
1462
1463 // calculating the number of constrains..
1464 nCons = 0;
1468 for(uint i=0;i<cons.size();i++){
1469 nCons += getDomainElements(cons[i].domain);
1470 if(cons[i].direction == CONSTR_EQ){
1472 continue;
1473 } else if (cons[i].direction == CONSTR_LE0) {
1475 continue;
1476 } else if (cons[i].direction == CONSTR_GE0) {
1478 continue;
1479 } else {
1480 msgOut(MSG_CRITICAL_ERROR, "Asking for a constrain with unknown direction ("+i2s(cons[i].direction)+")");
1481 }
1482 }
1483
1484 msgOut(MSG_INFO,"The model will work with "+i2s(nVar)+" variables and "+i2s(nCons)+" constrains ("+i2s(nEqualityConstrains)+" equalities, "+i2s(nLowerEqualZeroConstrains)+" lower than 0 and "+i2s(nGreaterEqualZeroConstrains)+" greater than 0)");
1485}
1486
1487int
1489 int elements = 0;
1490 switch (domain){
1491 case DOM_PRI_PR:
1492 return nL2r*nPriPr;
1493 case DOM_SEC_PR:
1494 return nL2r*nSecPr;
1495 case DOM_ALL_PR:
1496 return nL2r*nAllPr;
1497 case DOM_R2_PRI_PR:
1498 for(uint r1=0;r1<l2r.size();r1++){
1499 elements += l2r[r1].size()*l2r[r1].size()*nPriPr; // EXP(i,j,p_pr)
1500 }
1501 return elements;
1502 case DOM_R2_SEC_PR:
1503 for(uint r1=0;r1<l2r.size();r1++){
1504 elements += l2r[r1].size()*l2r[r1].size()*nSecPr; // EXP(i,j,p_tr)
1505 }
1506 return elements;
1507 case DOM_R2_ALL_PR:
1508 for(uint r1=0;r1<l2r.size();r1++){
1509 elements += l2r[r1].size()*l2r[r1].size()*nAllPr; // EXP(i,j,prd)
1510 }
1511 return elements;
1512 case DOM_SCALAR:
1513 return 1;
1515 return nL2r*nPriPrCombs;
1516 default:
1517 msgOut(MSG_CRITICAL_ERROR, "Asking for an unknown domain type ("+i2s(domain)+")");
1518 }
1519}
1520
1521int
1523 for(uint i=0;i<cons.size();i++){
1524 if(i!=cons.size()-1){
1525 if (idx >= gip(i) && idx < gip(i+1)){
1526 return cons[i].direction;
1527 }
1528 } else {
1529 if (idx >= gip(i) && idx < nCons){
1530 return cons[i].direction;
1531 }
1532 }
1533 }
1534 msgOut(MSG_CRITICAL_ERROR, "Asking contrain direction for an out of range contrain index!");
1535}
1536
1537double
1538Opt::getBoundByIndex(const int & bound_type, const int & idx){
1539
1540 map <int, string>::const_iterator p;
1541 p=initPos_rev.upper_bound(idx);
1542 p--;
1543 VarMap::const_iterator p2;
1544 p2=vars.find(p->second);
1545 if(p2 != vars.end()) {
1546 if (bound_type==LBOUND){
1547 if (p2->second.l_bound_var == ""){ // this var don't specific a variable as bound
1548 return p2->second.l_bound;
1549 } else {
1550 return getDetailedBoundByVarAndIndex(p2->second,idx,LBOUND);
1551 }
1552 } else if (bound_type==UBOUND){
1553 if (p2->second.u_bound_var == ""){ // this var don't specific a variable as bound
1554 return p2->second.u_bound;
1555 } else {
1556 return getDetailedBoundByVarAndIndex(p2->second,idx,UBOUND);
1557 }
1558 } else {
1559 msgOut(MSG_CRITICAL_ERROR, "Asking the bound with a type ("+i2s(bound_type)+") that I don't know how to handle !");
1560 }
1561 }
1562 else {
1563 msgOut(MSG_CRITICAL_ERROR, "Asking the bound from a variable ("+p->second+") that doesn't exist!");
1564 }
1565 return 0.;
1566}
1567
1568double
1569Opt::getDetailedBoundByVarAndIndex(const endvar & var, const int & idx, const int & bType){
1570 // Tested 2015.01.08 with DOM_ALL_PR, DOM_PRI_PR, DOM_ALL_PR, DOM_R2_ALL_PR.
1571 int r1,r2,p,r2to;
1572 unpack(idx,var.domain,gip(var.name),r1,r2,p,r2to,true);
1573 //cout << "getBoundByVarAndIndex():\t" << var.name << '\t' << idx << '\t' << gip(var.name) << '\t' << r1 << '\t' << r2 << '\t' << p << '\t' << r2to << endl;
1574 //cout << " --variables:\t" << var.l_bound_var << '\t' << var.u_bound_var << '\t' << "" << '\t' << l2r[r1][r2] << '\t' << "" << '\t' << allPr[p] << '\t' << l2r[r1][r2to] << endl;
1575 if(bType==LBOUND){
1576 if(r2to){
1577 return gpd(var.l_bound_var,l2r[r1][r2],allPr[p],DATA_NOW,i2s(l2r[r1][r2to]));
1578 } else {
1579 return gpd(var.l_bound_var,l2r[r1][r2],allPr[p],DATA_NOW,i2s(l2r[r1][r2to]));
1580 }
1581 } else {
1582 if(r2to){
1583 return gpd(var.u_bound_var,l2r[r1][r2],allPr[p]);
1584 } else {
1585 //cout << gpd(var.u_bound_var,l2r[r1][r2],allPr[p]) << endl;
1586 return gpd(var.u_bound_var,l2r[r1][r2],allPr[p]);
1587 }
1588 }
1589}
1590
1591constrain*
1593 for(uint i=0;i<cons.size();i++){
1594 if(i!=cons.size()-1){
1595 if (idx >= gip(i) && idx < gip(i+1)){
1596 return &cons[i];
1597 }
1598 } else {
1599 if (idx >= gip(i) && idx < nCons){
1600 return &cons[i];
1601 }
1602 }
1603 }
1604 msgOut(MSG_CRITICAL_ERROR, "Asking contrain direction for an out of range contrain index!");
1605}
1606
1607
1608void
1609Opt::unpack(int ix_h, int domain, int initial, int &r1_h, int &r2_h, int&p_h, int&r2to_h, bool fullp){
1610 ix_h = ix_h-initial;
1611 double ix=0;
1612 bool r2flag = false;
1613 int pIndexToAdd = 0;
1614 int np=0;
1615 if(domain==DOM_PRI_PR || domain==DOM_R2_PRI_PR) {
1616 np = nPriPr;
1617 } else if (domain==DOM_SEC_PR || domain==DOM_R2_SEC_PR) {
1618 np = nSecPr;
1619 } else if (domain==DOM_ALL_PR || domain==DOM_R2_ALL_PR) {
1620 np = nAllPr;
1621 } else if (domain=DOM_SCALAR){
1622 r1_h=0;r2_h=0;p_h=0;r2to_h=0;
1623 return;
1624 } else {
1625 msgOut(MSG_CRITICAL_ERROR,"unknow domain ("+i2s(domain)+") in unpack() function.");
1626 }
1627 if(domain==DOM_R2_PRI_PR || domain==DOM_R2_SEC_PR ||domain==DOM_R2_ALL_PR){
1628 r2flag = true;
1629 }
1630 if(fullp && (domain==DOM_SEC_PR || domain==DOM_R2_SEC_PR)){ // changed 20140107 (any how, previously the unpack() function was not used!!)
1631 pIndexToAdd = nPriPr;
1632 //cout << "pindexToAdd: " << pIndexToAdd << endl;
1633 }
1634
1635 for (uint r1=0;r1<l2r.size();r1++){
1636 for (uint r2=0;r2<l2r[r1].size();r2++){
1637 for (uint p=0;p<np;p++){
1638 if(!r2flag){
1639 if(ix==ix_h){
1640 r1_h=r1;
1641 r2_h=r2;
1642 p_h=p+pIndexToAdd;
1643 r2to_h=0;
1644 return;
1645 }
1646 ix++;
1647 } else {
1648 for (uint r2To=0;r2To<l2r[r1].size();r2To++){
1649 if(ix==ix_h){
1650 r1_h=r1;
1651 r2_h=r2;
1652 p_h=p+pIndexToAdd;
1653 r2to_h=r2To;
1654 return;
1655 }
1656 ix++;
1657 }
1658 }
1659 }
1660 }
1661 }
1662 msgOut(MSG_CRITICAL_ERROR, "Error in unpack() function. Ix ("+i2s(ix_h)+") can not be unpacked");
1663}
1664
1665int
1667 for(uint i=0;i<cons.size();i++){
1668 if( cons[i].name == con->name
1669 && cons[i].comment == con->comment
1670 && cons[i].domain == con->domain
1671 && cons[i].direction == con->direction){
1672 return i;
1673 }
1674 }
1675 msgOut(MSG_CRITICAL_ERROR,"Constrain didn't found in list.");
1676}
1677
1678
1679void
1681
1682 unsigned int **jacpat=NULL; // compressed row storage
1683 int options_j[3]; // options for the jacobian patterns
1684 double *x;
1685 int retv_j = -1; // return value
1686
1687 options_j[0] = 0; // index domain propagation
1688 options_j[1] = 0; // automatic mode choice (ignored here)
1689 options_j[2] = 0; // safe
1690 jacpat = new unsigned int* [nCons];
1691 x = new double[nVar];
1692
1693 nzjelements.clear();
1694
1695 retv_j = jac_pat(tag_g, nCons, nVar, x, jacpat, options_j);
1696
1697 for (int i=0;i<nCons;i++) {
1698 for (int j=1;j<=jacpat[i][0];j++){
1699 vector <int> nzjelement;
1700 nzjelement.push_back(i);
1701 nzjelement.push_back(jacpat[i][j]);
1702 nzjelements.push_back(nzjelement);
1703 }
1704 }
1705}
1706
1707void
1709
1710 unsigned int **hesspat=NULL; // compressed row storage
1711 int options_h=0; // options for the hessian patterns
1712 double *x;
1713 int retv_h = -1; // return value
1714
1715 hesspat = new unsigned int* [(nVar+nCons+1)];
1716 x = new double[(nVar+nCons+1)];
1717
1718 retv_h = hess_pat(tag_L,nVar+nCons+1, x, hesspat, options_h);
1719
1720 for (int i=0;i<(nVar);i++) {
1721 for (int j=1;j<=hesspat[i][0];j++){
1722 if(hesspat[i][j]<=i){
1723 vector <int> nzhelement;
1724 nzhelement.push_back(i);
1725 nzhelement.push_back(hesspat[i][j]);
1726 nzhelements.push_back(nzhelement);
1727 }
1728 }
1729 }
1730}
1731
1732void
1734
1735 cout << "Num of variables: " << nVar << " - Num of constrains:" << nCons << endl;
1736 cout << "IDX;ROW;COL" << endl;
1737 for(uint i=0;i<nzhelements.size();i++){
1738 cout << i << ";" << nzhelements[i][0] << ";" << nzhelements[i][1] << endl;
1739 }
1740
1741 cout << "Dense jacobian: " << nCons * nVar << " elements" << endl;
1742 cout << "Dense hessian: " << nVar*(nVar-1)/2+nVar << " elements" << endl;
1743 //exit(0);
1744
1745}
1746
1747
1748const Number&
1749Opt::mymax(const Number& a, const Number& b){
1750 return (a<b)?b:a;
1751}
1752const adouble&
1753Opt::mymax(const adouble& a, const adouble& b){
1754 return (a<b)?b:a;
1755}
1756
1757
1758bool
1759Opt::intermediate_callback(AlgorithmMode mode, Index iter, Number obj_value, Number inf_pr, Number inf_du, Number mu, Number d_norm, Number regularization_size, Number alpha_du, Number alpha_pr, Index ls_trials, const IpoptData *ip_data, IpoptCalculatedQuantities *ip_cq){
1760 int itnumber = iter;
1761 if(itnumber%10==0){
1762 msgOut(MSG_DEBUG,"Running ("+i2s(itnumber)+" iter) ..");
1763 }
1764 return true;
1765}
1766
1767int
1768Opt::getVarInstances(const string& varName){
1769 return getDomainElements(gdt(varName));
1770}
1771
1772/*
1773template <class T> const T&
1774Opt::mymax ( const T& a, const T& b ){
1775 return (a<b)?b:a;
1776}
1777*/
1778/**
1779 * @brief Opt::declareVariable
1780 * Define a single variable together with its domain and optionally its lower and upper bound (default 0.0, +inf)
1781 *
1782 * @param name var name
1783 * @param domain domain of the variable
1784 * @param l_bound lower bound (fixed)
1785 * @param u_bound upper bound (fixed)
1786 * @param l_bound_var variable name defining lower bound
1787 * @param u_bound_var variable name defining upper bound
1788 */
1789
1790void
1791Opt::declareVariable(const string &name, const int & domain, const string &desc, const double & l_bound, const double & u_bound, const string & l_bound_var, const string & u_bound_var){
1792 endvar end_var;
1793 end_var.name = name;
1794 end_var.domain = domain;
1795 end_var.l_bound = l_bound;
1796 end_var.u_bound = u_bound;
1797 end_var.l_bound_var = l_bound_var;
1798 end_var.u_bound_var = u_bound_var;
1799 end_var.desc= desc;
1800 vars.insert(std::pair<std::string, endvar >(name, end_var));
1801}
1802/**
1803 * @brief Opt::createCombinationsVector
1804 * Return a vector containing any possible combination of nItems items (including all subsets).
1805 *
1806 * For example with nItems = 3:
1807 * 0: []; 1: [0]; 2: [1]; 3: [0,1]; 4: [2]; 5: [0,2]; 6: [1,2]; 7: [0,1,2]
1808
1809 * @param nItems number of items to create p
1810 * @return A vector with in each slot the items present in that specific combination subset.
1811 */
1812/*
1813vector < vector <int> >
1814Opt::createCombinationsVector(const int& nItems) {
1815 // Not confuse combination with permutation where order matter. Here it doesn't matter, as much as the algorithm is the same and returns
1816 // to as each position always the same subset
1817 vector < vector <int> > toReturn;
1818 int nCombs = pow(2,nItems);
1819 //int nCombs = nItems;
1820 for (uint i=0; i<nCombs; i++){
1821 vector<int> thisCombItems; //concernedPriProducts;
1822 for(uint j=0;j<nItems;j++){
1823 uint j2 = pow(2,j);
1824 if(i & j2){ // bit a bit operator, p217 C++ book
1825 thisCombItems.push_back(j);
1826 }
1827 }
1828 toReturn.push_back(thisCombItems);
1829 }
1830
1831// cout << "N items:\t" << nItems << endl;
1832// for (uint i=0;i<nCombs; i++){
1833// cout << " "<< i << ":\t";
1834// for (uint j=0;j<toReturn[i].size();j++){
1835// cout << toReturn[i][j] << " ";
1836// }
1837// cout << endl;
1838// }
1839// exit(0);
1840 return toReturn;
1841}
1842*/
1843
1844void
1846 // This function is not really needed, as actually the solver works also picking the region and the in dynamically
1847 // Caching the inventories in a vector should however be faster.
1848 // We now need it, as the vector inResByAnyCombination() account for the union between the inv set of the various pp. Also it now include the total mortality (alive plus death, if modelled)
1849 vector < vector < vector <double> > > in_temp;
1850 for (uint r1=0;r1<l2r.size();r1++){
1851 vector < vector <double> > dim1;
1852 for (uint r2=0;r2<l2r[r1].size();r2++){
1853 vector <double> dim2;
1854 ModelRegion* REG = MTHREAD->MD->getRegion(l2r[r1][r2]);
1855 for (uint p=0;p<priPrCombs.size();p++){
1856 double this_in = REG->inResByAnyCombination[p];
1857 dim2.push_back(this_in);
1858 }
1859 dim1.push_back(dim2);
1860 }
1861 in_temp.push_back(dim1);
1862 }
1863 ins = in_temp;
1864}
@ CONSTR_LE0
Definition BaseClass.h:117
@ CONSTR_EQ
Definition BaseClass.h:116
@ CONSTR_GE0
Definition BaseClass.h:118
@ DATA_NOW
The required data is for the current year.
Definition BaseClass.h:73
@ LBOUND
Definition BaseClass.h:128
@ UBOUND
Definition BaseClass.h:129
@ MSG_CRITICAL_ERROR
Print an error message and stop the model.
Definition BaseClass.h:62
@ MSG_DEBUG
Print a debug message, normally filtered out.
Definition BaseClass.h:58
@ MSG_INFO
Print an INFO message.
Definition BaseClass.h:59
@ DOM_PRI_PR
Primary products // domain of variables and constrains: primary, secondary, all products or all produ...
Definition BaseClass.h:93
@ DOM_R2_SEC_PR
Secondary products over r2 couple regions (in-country commercial flows)
Definition BaseClass.h:97
@ DOM_SEC_PR
Secondary products.
Definition BaseClass.h:94
@ DOM_SCALAR
Scalar variable (not used)
Definition BaseClass.h:99
@ DOM_R2_PRI_PR
Primary products over r2 couple regions (in-country commercial flows)
Definition BaseClass.h:96
@ DOM_R2_ALL_PR
All products over r2 couple regions (in-country commercial flows)
Definition BaseClass.h:98
@ DOM_PRI_PR_ALLCOMBS
All possible combinations of primary products (2^ number of primary products)
Definition BaseClass.h:100
@ DOM_ALL_PR
All products (primary+secondary)
Definition BaseClass.h:95
std::map< string, endvar > VarMap
Definition Opt.cpp:52
#define CONSTRAIN_START_LOOP(pVector, cn)
Definition Opt.cpp:40
std::pair< std::string, endvar > VarPair
Definition Opt.cpp:53
#define CONSTRAIN_END_LOOP
Definition Opt.cpp:46
#define tag_f
Definition Opt.h:35
#define tag_g
Definition Opt.h:36
#define HPOFF
Definition Opt.h:38
#define tag_L
Definition Opt.h:37
ThreadManager * MTHREAD
Pointer to the Thread manager.
Definition BaseClass.h:467
void msgOut(const int &msgCode_h, const string &msg_h, const bool &refreshGUI_h=true) const
Overloaded function to print the output log.
Definition BaseClass.cpp:50
string i2s(const int &int_h) const
integer to string conversion
double getDoubleSetting(const string &name_h, int position=0, int reg=WORLD) const
vector< vector< int > > createCombinationsVector(const int &nItems)
Return a vector containing any possible combination of nItems items (including any possible subset)....
vector< string > getStringVectorSetting(const string &name_h, int reg=WORLD) const
vector< int > getRegionIds(int level_h, bool excludeResidual=true)
ModelRegion * getRegion(int regId_h)
int getIntSetting(const string &name_h, int position=0, int reg=WORLD) const
vector< ModelRegion * > getChildren(bool excludeResidual=true)
Returns a pointer to the parent regions.
vector< double > inResByAnyCombination
Vector of inventory resource for each possible combination of primary products. This store both alive...
Definition ModelRegion.h:88
int nEqualityConstrains
Definition Opt.h:214
vector< constrain > cons
Definition Opt.h:225
int nAllPr
Definition Opt.h:210
int nCons
Definition Opt.h:213
int nLowerEqualZeroConstrains
Definition Opt.h:215
double * jacval
Definition Opt.h:254
const double gpd(const string &type_h, const int &regId_h, const string &prodId_h, const int &year=DATA_NOW, const string &freeDim_h="") const
Definition Opt.h:168
map< string, vector< vector< vector< vector< int > > > > > vpositions
cached position in the concatenated vector for each variables. Dimensions are l1reg,...
Definition Opt.h:204
int nSecPr
Definition Opt.h:209
const int gix(const string &varName, const int &r1Ix, const int &r2Ix, const int &prIx, const int &r2IxTo=0) const
Get the index in the concatenated array gived a certain var name, the reg lev1 index,...
Definition Opt.cpp:1351
vector< vector< int > > priPrCombs
A vector with all the possible combinations of primary products.
Definition Opt.h:198
Opt(ThreadManager *MTHREAD_h)
Constructor.
Definition Opt.cpp:537
vector< vector< vector< double > > > ins
A copy of the inventoried resourses by region and primary product combination. It works also with dyn...
Definition Opt.h:199
int nGreaterEqualZeroConstrains
Definition Opt.h:216
vector< string > othPr
Definition Opt.h:196
constrain * getConstrainByIndex(int idx)
Definition Opt.cpp:1592
void declareVariables()
declare the variables, their domains and their bounds
Definition Opt.cpp:59
unsigned int * cind_L_total
Definition Opt.h:258
int getDomainElements(int domain)
return the number of elements of a domain
Definition Opt.cpp:1488
vector< vector< int > > l2r
Definition Opt.h:197
vector< string > priPr
Definition Opt.h:193
void calculateSparsityPatternH()
Definition Opt.cpp:1708
unsigned int * rind_g
Definition Opt.h:252
virtual bool intermediate_callback(AlgorithmMode mode, Index iter, Number obj_value, Number inf_pr, Number inf_du, Number mu, Number d_norm, Number regularization_size, Number alpha_du, Number alpha_pr, Index ls_trials, const IpoptData *ip_data, IpoptCalculatedQuantities *ip_cq)
Definition Opt.cpp:1759
bool eval_obj(Index n, const T *x, T &obj_value)
Definition Opt.cpp:220
virtual bool get_bounds_info(Index n, Number *x_l, Number *x_u, Index m, Number *g_l, Number *g_u)
Definition Opt.cpp:634
map< int, string > initPos_rev
A map with the name of the variable keyed by its initial position in the index.
Definition Opt.h:201
void cacheInitialPosition()
cache the initial positions of the variables and the constrains
Definition Opt.cpp:1370
unsigned int * rind_L
Definition Opt.h:255
double getBoundByIndex(const int &bound_type, const int &idx)
Return the bound of a given variable (by index)
Definition Opt.cpp:1538
int nVar
Definition Opt.h:212
int nPriPr
Definition Opt.h:206
bool initOpt
Definition Opt.h:224
int getConstrainDirectionByIndex(int idx)
Return the direction of a given constrain.
Definition Opt.cpp:1522
unsigned int * cind_L
Definition Opt.h:256
const int gip(const string &varName) const
Get the initial index position of a given variable in the concatenated array.
Definition Opt.cpp:1274
int options_L[4]
Definition Opt.h:263
virtual bool eval_f(Index n, const Number *x, bool new_x, Number &obj_value)
Definition Opt.cpp:822
double overharvestingAllowance
Allows to harvest more than the resources available. Useful when resources got completelly exausted a...
Definition Opt.h:222
int secondYear
Definition Opt.h:219
int nPriPrCombs
Definition Opt.h:208
map< string, int > initPos
A map that returns the initial index position in the concatenated array for each variable.
Definition Opt.h:200
void tempDebug()
Definition Opt.cpp:1733
unsigned int * rind_L_total
Definition Opt.h:257
virtual bool get_starting_point(Index n, bool init_x, Number *x, bool init_z, Number *z_L, Number *z_U, Index m, bool init_lambda, Number *lambda)
Definition Opt.cpp:664
void cachePositions()
cache the exact position index (initial+f(r1,r2,p,r2To) for each variable and constrain
Definition Opt.cpp:1386
int nnz_jac
Definition Opt.h:260
virtual bool get_nlp_info(Index &n, Index &m, Index &nnz_jac_g, Index &nnz_h_lag, IndexStyleEnum &index_style)
Definition Opt.cpp:551
~Opt()
Definition Opt.cpp:545
virtual bool eval_jac_g(Index n, const Number *x, bool new_x, Index m, Index nele_jac, Index *iRow, Index *jCol, Number *values)
Definition Opt.cpp:845
void declareVariable(const string &name, const int &domain, const string &desc="", const double &l_bound=0.0, const double &u_bound=UBOUND_MAX, const string &l_bound_var="", const string &u_bound_var="")
Declare a single variable, its domain and its bounds.
Definition Opt.cpp:1791
vector< vector< vector< vector< int > > > > buildPositionVector(const T &v_or_c, int dType)
build the matrix of the positions for a given variable or contrain
Definition Opt.cpp:1401
int nL2r
Definition Opt.h:211
virtual bool eval_g(Index n, const Number *x, bool new_x, Index m, Number *g)
Definition Opt.cpp:837
int previousYear
Definition Opt.h:217
double * hessval
Definition Opt.h:259
int firstYear
Definition Opt.h:218
int nOthPr
Definition Opt.h:207
unsigned int * cind_g
Definition Opt.h:253
void calculateNumberVariablesConstrains()
calculate the number of variables and constrains
Definition Opt.cpp:1455
unsigned int ** HP_t
Definition Opt.h:251
void copyInventoryResourses()
Copy the inventoried resources in the in vector for better performances.
Definition Opt.cpp:1845
void calculateSparsityPatternJ()
Definition Opt.cpp:1680
double * x_lam
Definition Opt.h:248
vector< vector< Index > > nzhelements
nzero elements for the hessian matrix
Definition Opt.h:227
int worldCodeLev2
Definition Opt.h:220
map< string, endvar > vars
List of variables in the model and their domain: pr product, sec prod, all products or all products o...
Definition Opt.h:203
int nnz_L
Definition Opt.h:261
int getConNumber(constrain *con)
Return the position in the cons vector.
Definition Opt.cpp:1666
bool debugRunOnce
Definition Opt.h:221
bool eval_constraints(Index n, const T *x, Index m, T *g)
Definition Opt.cpp:311
int getVarInstances(const string &varName)
build the matrix of the positions for a given variable or contrain
Definition Opt.cpp:1768
void unpack(int ix_h, int domain, int initial, int &r1_h, int &r2_h, int &p_h, int &r2to_h, bool fullp=false)
Return the dimensions given a certain index, domain type and initial position.
Definition Opt.cpp:1609
virtual void finalize_solution(SolverReturn status, Index n, const Number *x, const Number *z_L, const Number *z_U, Index m, const Number *g, const Number *lambda, Number obj_value, const IpoptData *ip_data, IpoptCalculatedQuantities *ip_cq)
Definition Opt.cpp:732
vector< string > allPr
Definition Opt.h:195
virtual bool eval_h(Index n, const Number *x, bool new_x, Number obj_factor, Index m, const Number *lambda, bool new_lambda, Index nele_hess, Index *iRow, Index *jCol, Number *values)
Definition Opt.cpp:871
const int gdt(const string &varName)
Get the domain type of a given variable.
Definition Opt.cpp:1292
void spd(const double &value_h, const string &type_h, const int &regId_h, const string &prodId_h, const int &year=DATA_NOW, const bool &allowCreate=false, const string &freeDim_h="") const
Definition Opt.h:170
virtual void generate_tapes(Index n, Index m, Index &nnz_jac_g, Index &nnz_h_lag)
Definition Opt.cpp:918
int options_g[4]
Definition Opt.h:262
vector< int > cInitPos
A vector that returns the initial index position in the concatenated array for each constrain.
Definition Opt.h:202
vector< string > secPr
Definition Opt.h:194
void declareConstrains()
declare the constrains, their domain, their direction and their associated evaluation function
Definition Opt.cpp:84
double getDetailedBoundByVarAndIndex(const endvar &var, const int &idx, const int &bType)
Return the bound of a given variable given the variable and the required index. Called by getBoundByI...
Definition Opt.cpp:1569
const int gix_uncached(const T &v_or_c, int r1Ix, int r2Ix, int prIx, int r2IxTo=0)
Get the index in the concatenated array gived a certain var name (string) or constrain index (int),...
Definition Opt.cpp:1310
vector< vector< vector< vector< vector< int > > > > > cpositions
cached position in the concatenated vector for each variables. Dimensions are contrain number,...
Definition Opt.h:205
int nnz_L_total
Definition Opt.h:261
const Number & mymax(const Number &a, const Number &b)
Definition Opt.cpp:1749
virtual bool eval_grad_f(Index n, const Number *x, bool new_x, Number *grad_f)
Definition Opt.cpp:829
vector< vector< Index > > nzjelements
nzero elements for the jacobian matrix. nzelements[i][0] -> row (constrain), nzelements[i][1] -> colu...
Definition Opt.h:226
int getYear()
Definition Scheduler.h:49
Thread manager. Responsable to manage the main thread and "speak" with the GUI.
Scheduler * SCD
the scheduler object (simulation-loops scheduler)
ModelData * MD
the model data object
int domain
Definition Opt.h:274
int direction
Definition Opt.h:275
string name
Definition Opt.h:272
string comment
Definition Opt.h:273
Definition Opt.h:279
int domain
Definition Opt.h:281
string l_bound_var
A variable giving the lower bound. If present, the value defined in the variable overrides l_bound.
Definition Opt.h:285
double u_bound
A fixed numerical upper bound for all the domain.
Definition Opt.h:284
string u_bound_var
A variable giving the upper bound. If present, the value defined in the variable overrides u_bound.
Definition Opt.h:286
string name
Definition Opt.h:280
string desc
Description of the variable.
Definition Opt.h:282
double l_bound
A fixed numerical lower bound for all the domain.
Definition Opt.h:283