FFSM++ 1.1.0
French Forest Sector Model ++
Loading...
Searching...
No Matches
Opt.cpp File Reference
#include <stdlib.h>
#include <cassert>
#include <map>
#include <adolc/drivers/drivers.h>
#include <adolc/adolc_sparse.h>
#include "Opt.h"
#include "ModelData.h"
#include "Pixel.h"
#include "ThreadManager.h"
#include "Scheduler.h"
#include "ModelRegion.h"
Include dependency graph for Opt.cpp:

Go to the source code of this file.

Macros

#define CONSTRAIN_START_LOOP(pVector, cn)
 
#define CONSTRAIN_END_LOOP    }}}
 

Typedefs

typedef std::map< string, endvarVarMap
 
typedef std::pair< std::string, endvarVarPair
 

Macro Definition Documentation

◆ CONSTRAIN_END_LOOP

#define CONSTRAIN_END_LOOP    }}}

Definition at line 46 of file Opt.cpp.

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

◆ CONSTRAIN_START_LOOP

#define CONSTRAIN_START_LOOP (   pVector,
  cn 
)
Value:
for (uint r1=0;r1<l2r.size();r1++){ \
for (uint r2=0;r2<l2r[r1].size();r2++){ \
for (uint p=0;p<(pVector).size();p++){ \
int psec = p+nPriPr; \
cix = gix((cn), r1, r2, p);

Definition at line 40 of file Opt.cpp.

41 { \
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);

Typedef Documentation

◆ VarMap

typedef std::map<string, endvar> VarMap

Definition at line 52 of file Opt.cpp.

◆ VarPair

typedef std::pair<std::string, endvar > VarPair

Definition at line 53 of file Opt.cpp.