FFSM++  1.1.0
French Forest Sector Model ++
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 
50 using namespace Ipopt;
51 
52 typedef std::map<string, endvar> VarMap;
53 typedef std::pair<std::string, endvar > VarPair;
54 
55 // ****** MODEL IMPLEMENTATION START HERE ********************************
56 
57 
58 void
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 /**
81 Declare the constrains and their properties. For the domain type @see BaseClass
82 */
83 void
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 /**
217 Define the objective function
218 */
219 template<class T> bool
220 Opt::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.
306 To 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.
307 It 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 */
310 template<class T> bool
311 Opt::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
329  CONSTRAIN_START_LOOP(secPr,1)
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 ?
377  CONSTRAIN_START_LOOP(secPr,2)
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
386  CONSTRAIN_START_LOOP(secPr,3)
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
392  CONSTRAIN_START_LOOP(secPr,4)
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
405  CONSTRAIN_START_LOOP(priPr,5)
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
418  CONSTRAIN_START_LOOP(priPr,6)
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 
431  CONSTRAIN_START_LOOP(priPr,7)
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 ?
451  CONSTRAIN_START_LOOP(priPr,8)
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
460  CONSTRAIN_START_LOOP(priPr,9)
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
466  CONSTRAIN_START_LOOP(priPr,10)
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
479  CONSTRAIN_START_LOOP(secPr,11)
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;
485  CONSTRAIN_START_LOOP(allPr,12)
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
494  CONSTRAIN_START_LOOP(secPr,13)
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
512  CONSTRAIN_START_LOOP(priPrCombs,14)
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 
550 bool
551 Opt::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");
569  secondYear = firstYear+1;
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
585  priPrCombs = MTHREAD->MD->createCombinationsVector(nPriPr);
586  nPriPrCombs = priPrCombs.size();
587 
588  // put the variables and their domain in the vars map
589  declareVariables();
590 
591  // declaring the contrains...
592  declareConstrains();
593 
594  // calculate number of variables and constrains..
595  calculateNumberVariablesConstrains();
596 
597  // cache initial positions (variables and constrains)..
598  cacheInitialPosition();
599 
600  // cache initial positions (variables and constrains)..
601  cachePositions();
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 
616  copyInventoryResourses();
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 
633 bool
634 Opt::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 
663 bool
664 Opt::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 
731 void
732 Opt::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 
821 bool
822 Opt::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 
828 bool
829 Opt::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 
836 bool
837 Opt::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 
844 bool
845 Opt::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 
870 bool
871 Opt::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 
917 void
918 Opt::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 
1273 const int
1274 Opt::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 
1286 const int
1287 Opt::gip(const int &cn) const { // get initial position
1288  return cInitPos.at(cn);
1289 }
1290 
1291 const int
1292 Opt::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 
1304 const int
1305 Opt::gdt(const int &cn){ // get domain type
1306  return cons.at(cn).domain;
1307 }
1308 
1309 template<class T> const int
1310 Opt::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);
1341  case DOM_PRI_PR_ALLCOMBS:
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 
1350 const int
1351 Opt::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 
1364 const int
1365 Opt::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 
1369 void
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 
1385 void
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 
1400 template<class T> vector < vector < vector < vector <int> > > >
1401 Opt::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;
1426  case DOM_PRI_PR_ALLCOMBS:
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 
1454 void
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;
1465  nEqualityConstrains = 0;
1466  nLowerEqualZeroConstrains = 0;
1467  nGreaterEqualZeroConstrains = 0;
1468  for(uint i=0;i<cons.size();i++){
1469  nCons += getDomainElements(cons[i].domain);
1470  if(cons[i].direction == CONSTR_EQ){
1471  nEqualityConstrains += getDomainElements(cons[i].domain);
1472  continue;
1473  } else if (cons[i].direction == CONSTR_LE0) {
1474  nLowerEqualZeroConstrains += getDomainElements(cons[i].domain);
1475  continue;
1476  } else if (cons[i].direction == CONSTR_GE0) {
1477  nGreaterEqualZeroConstrains += getDomainElements(cons[i].domain);
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 
1487 int
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;
1514  case DOM_PRI_PR_ALLCOMBS:
1515  return nL2r*nPriPrCombs;
1516  default:
1517  msgOut(MSG_CRITICAL_ERROR, "Asking for an unknown domain type ("+i2s(domain)+")");
1518  }
1519 }
1520 
1521 int
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 
1537 double
1538 Opt::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 
1568 double
1569 Opt::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 
1591 constrain*
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 
1608 void
1609 Opt::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 
1665 int
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 
1679 void
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 
1707 void
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 
1732 void
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 
1748 const Number&
1749 Opt::mymax(const Number& a, const Number& b){
1750  return (a<b)?b:a;
1751 }
1752 const adouble&
1753 Opt::mymax(const adouble& a, const adouble& b){
1754  return (a<b)?b:a;
1755 }
1756 
1757 
1758 bool
1759 Opt::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 
1767 int
1768 Opt::getVarInstances(const string& varName){
1769  return getDomainElements(gdt(varName));
1770 }
1771 
1772 /*
1773 template <class T> const T&
1774 Opt::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 
1790 void
1791 Opt::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 /*
1813 vector < vector <int> >
1814 Opt::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 
1844 void
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 }
virtual bool eval_f(Index n, const Number *x, bool new_x, Number &obj_value)
Definition: Opt.cpp:822
int getConNumber(constrain *con)
Return the position in the cons vector.
Definition: Opt.cpp:1666
#define tag_g
virtual bool eval_grad_f(Index n, const Number *x, bool new_x, Number *grad_f)
Definition: Opt.cpp:829
The required data is for the current year.
Definition: BaseClass.h:73
int direction
Definition: Opt.h:275
void declareConstrains()
declare the constrains, their domain, their direction and their associated evaluation function ...
Definition: Opt.cpp:84
double l_bound
A fixed numerical lower bound for all the domain.
Definition: Opt.h:283
double u_bound
A fixed numerical upper bound for all the domain.
Definition: Opt.h:284
string desc
Description of the variable.
Definition: Opt.h:282
~Opt()
Definition: Opt.cpp:545
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
#define CONSTRAIN_START_LOOP(pVector, cn)
Definition: Opt.cpp:40
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 gdt(const string &varName)
Get the domain type of a given variable.
Definition: Opt.cpp:1292
string name
Definition: Opt.h:271
virtual bool eval_g(Index n, const Number *x, bool new_x, Index m, Number *g)
Definition: Opt.cpp:837
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
#define tag_f
int getVarInstances(const string &varName)
build the matrix of the positions for a given variable or contrain
Definition: Opt.cpp:1768
virtual bool get_nlp_info(Index &n, Index &m, Index &nnz_jac_g, Index &nnz_h_lag, IndexStyleEnum &index_style)
Definition: Opt.cpp:551
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
void declareVariables()
declare the variables, their domains and their bounds
Definition: Opt.cpp:59
Thread manager. Responsable to manage the main thread and "speak" with the GUI.
Definition: ThreadManager.h:65
int domain
Definition: Opt.h:281
Primary products // domain of variables and constrains: primary, secondary, all products or all produ...
Definition: BaseClass.h:93
#define tag_L
vector< double > inResByAnyCombination
Vector of inventory resource for each possible combination of primary products. This store both alive...
Definition: ModelRegion.h:86
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
Opt(ThreadManager *MTHREAD_h)
Constructor.
Definition: Opt.cpp:537
std::pair< std::string, endvar > VarPair
Definition: Opt.cpp:53
Print an error message and stop the model.
Definition: BaseClass.h:62
const int gip(const string &varName) const
Get the initial index position of a given variable in the concatenated array.
Definition: Opt.cpp:1274
constrain * getConstrainByIndex(int idx)
Definition: Opt.cpp:1592
Definition: Opt.h:270
#define CONSTRAIN_END_LOOP
Definition: Opt.cpp:46
Secondary products over r2 couple regions (in-country commercial flows)
Definition: BaseClass.h:97
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
int getDomainElements(int domain)
return the number of elements of a domain
Definition: Opt.cpp:1488
Secondary products.
Definition: BaseClass.h:94
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
bool eval_obj(Index n, const T *x, T &obj_value)
Definition: Opt.cpp:220
Print a debug message, normally filtered out.
Definition: BaseClass.h:58
Primary products over r2 couple regions (in-country commercial flows)
Definition: BaseClass.h:96
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
Scalar variable (not used)
Definition: BaseClass.h:99
bool eval_constraints(Index n, const T *x, Index m, T *g)
Definition: Opt.cpp:311
All products over r2 couple regions (in-country commercial flows)
Definition: BaseClass.h:98
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
string comment
Definition: Opt.h:273
void cachePositions()
cache the exact position index (initial+f(r1,r2,p,r2To) for each variable and constrain ...
Definition: Opt.cpp:1386
const Number & mymax(const Number &a, const Number &b)
Definition: Opt.cpp:1749
All possible combinations of primary products (2^ number of primary products)
Definition: BaseClass.h:100
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, the reg lev2 index and the prod. index.
Definition: Opt.cpp:1351
Definition: Opt.h:279
vector< ModelRegion * > getChildren(bool excludeResidual=true)
Returns a pointer to the parent regions.
Definition: ModelRegion.cpp:55
string name
Definition: Opt.h:280
double getBoundByIndex(const int &bound_type, const int &idx)
Return the bound of a given variable (by index)
Definition: Opt.cpp:1538
void tempDebug()
Definition: Opt.cpp:1733
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
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
int domain
Definition: Opt.h:274
Print an INFO message.
Definition: BaseClass.h:59
std::map< string, endvar > VarMap
Definition: Opt.cpp:52
All products (primary+secondary)
Definition: BaseClass.h:95
void copyInventoryResourses()
Copy the inventoried resources in the in vector for better performances.
Definition: Opt.cpp:1845
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
int getConstrainDirectionByIndex(int idx)
Return the direction of a given constrain.
Definition: Opt.cpp:1522
#define HPOFF
Definition: Opt.h:38
void calculateSparsityPatternJ()
Definition: Opt.cpp:1680
void calculateSparsityPatternH()
Definition: Opt.cpp:1708
virtual void generate_tapes(Index n, Index m, Index &nnz_jac_g, Index &nnz_h_lag)
Definition: Opt.cpp:918
void calculateNumberVariablesConstrains()
calculate the number of variables and constrains
Definition: Opt.cpp:1455
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
void cacheInitialPosition()
cache the initial positions of the variables and the constrains
Definition: Opt.cpp:1370