LuksanVlcek3.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. // Copyright (C) 2005, 2006 International Business Machines and others.
  2. // All Rights Reserved.
  3. // This code is published under the Eclipse Public License.
  4. //
  5. // $Id: LuksanVlcek3.cpp 2005 2011-06-06 12:55:16Z stefan $
  6. //
  7. // Authors: Andreas Waechter IBM 2005-10-127
  8. #include "LuksanVlcek3.hpp"
  9. #ifdef HAVE_CONFIG_H
  10. #include "config.h"
  11. #else
  12. #include "configall_system.h"
  13. #endif
  14. #ifdef HAVE_CMATH
  15. # include <cmath>
  16. #else
  17. # ifdef HAVE_MATH_H
  18. # include <math.h>
  19. # else
  20. # error "don't have header file for math"
  21. # endif
  22. #endif
  23. #ifdef HAVE_CSTDIO
  24. # include <cstdio>
  25. #else
  26. # ifdef HAVE_STDIO_H
  27. # include <stdio.h>
  28. # else
  29. # error "don't have header file for stdio"
  30. # endif
  31. #endif
  32. using namespace Ipopt;
  33. LuksanVlcek3::LuksanVlcek3(Number g_l, Number g_u)
  34. {
  35. g_l_ = g_l;
  36. g_u_ = g_u;
  37. }
  38. bool LuksanVlcek3::InitializeProblem(Index N)
  39. {
  40. N_=N;
  41. if (N_<=5 || 4*((N_+2)/4)!=N_+2) {
  42. printf("N needs to be at least 6 and N+2 needs to be a multiple of 4.\n");
  43. return false;
  44. }
  45. return true;
  46. }
  47. // returns the size of the problem
  48. bool LuksanVlcek3::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
  49. Index& nnz_h_lag, IndexStyleEnum& index_style)
  50. {
  51. // The problem described in LuksanVlcek3.hpp has 4 variables, x[0] through x[3]
  52. n = N_+2;
  53. m = 2;
  54. nnz_jac_g = 4;
  55. nnz_h_lag = 5*N_/2 + 3;
  56. // use the C style numbering of matrix indices (starting at 0)
  57. index_style = TNLP::C_STYLE;
  58. return true;
  59. }
  60. // returns the variable bounds
  61. bool LuksanVlcek3::get_bounds_info(Index n, Number* x_l, Number* x_u,
  62. Index m, Number* g_l, Number* g_u)
  63. {
  64. // none of the variables have bounds
  65. for (Index i=0; i<n; i++) {
  66. x_l[i] = -1e20;
  67. x_u[i] = 1e20;
  68. }
  69. // Set the bounds for the constraints
  70. for (Index i=0; i<m; i++) {
  71. g_l[i] = g_l_;
  72. g_u[i] = g_u_;
  73. }
  74. return true;
  75. }
  76. // returns the initial point for the problem
  77. bool LuksanVlcek3::get_starting_point(Index n, bool init_x, Number* x,
  78. bool init_z, Number* z_L, Number* z_U,
  79. Index m, bool init_lambda,
  80. Number* lambda)
  81. {
  82. if (!init_x || init_z || init_lambda) {
  83. return false;
  84. }
  85. // set the starting point
  86. for (Index i=0; i<n/4; i++) {
  87. x[4*i] = 3.;
  88. x[4*i+1] = -1.;
  89. x[4*i+2] = 0.;
  90. x[4*i+3] = 1.;
  91. }
  92. /*
  93. // DELETEME
  94. for (Index i=0; i<n; i++) {
  95. x[i] += 0.1*((Number) i);
  96. }
  97. */
  98. return true;
  99. }
  100. // returns the value of the objective function
  101. bool LuksanVlcek3::eval_f(Index n, const Number* x, bool new_x, Number& obj_value)
  102. {
  103. obj_value = 0.;
  104. for (Index i=0; i<N_/2; i++) {
  105. Number a1 = x[2*i]+10.*x[2*i+1];
  106. Number a2 = x[2*i+2] - x[2*i+3];
  107. Number a3 = x[2*i+1] - 2.*x[2*i+2];
  108. Number a4 = x[2*i] - x[2*i+3];
  109. obj_value += a1*a1 + 5.*a2*a2 + pow(a3,4)+ 10.*pow(a4,4);
  110. }
  111. return true;
  112. }
  113. // return the gradient of the objective function grad_{x} f(x)
  114. bool LuksanVlcek3::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
  115. {
  116. grad_f[0] = 0.;
  117. grad_f[1] = 0.;
  118. for (Index i=0; i<N_/2; i++) {
  119. Number a1 = x[2*i]+10.*x[2*i+1];
  120. Number a2 = x[2*i+2] - x[2*i+3];
  121. Number a3 = x[2*i+1] - 2.*x[2*i+2];
  122. Number a4 = x[2*i] - x[2*i+3];
  123. grad_f[2*i] += 2.*a1 + 40.*pow(a4,3);
  124. grad_f[2*i+1] += 20.*a1 + 4.*pow(a3,3);
  125. grad_f[2*i+2] = 10.*a2 - 8.*pow(a3,3);
  126. grad_f[2*i+3] = -10.*a2 - 40.*pow(a4,3);
  127. }
  128. return true;
  129. }
  130. // return the value of the constraints: g(x)
  131. bool LuksanVlcek3::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
  132. {
  133. g[0] = 3.*pow(x[0],3) + 2.*x[1] - 5. + sin(x[0]-x[1])*sin(x[0]+x[1]);
  134. g[1] = 4.*x[n-3] - x[n-4]*exp(x[n-4]-x[n-3]) - 3;
  135. ;
  136. return true;
  137. }
  138. // return the structure or values of the jacobian
  139. bool LuksanVlcek3::eval_jac_g(Index n, const Number* x, bool new_x,
  140. Index m, Index nele_jac, Index* iRow, Index *jCol,
  141. Number* values)
  142. {
  143. if (values == NULL) {
  144. // return the structure of the jacobian
  145. Index ijac = 0;
  146. iRow[ijac] = 0;
  147. jCol[ijac] = 0;
  148. ijac++;
  149. iRow[ijac] = 0;
  150. jCol[ijac] = 1;
  151. ijac++;
  152. iRow[ijac] = 1;
  153. jCol[ijac] = n-4;
  154. ijac++;
  155. iRow[ijac] = 1;
  156. jCol[ijac] = n-3;
  157. ijac++;
  158. DBG_ASSERT(ijac == nele_jac);
  159. }
  160. else {
  161. // return the values of the jacobian of the constraints
  162. Index ijac = 0;
  163. values[ijac] = 9.*x[0]*x[0]
  164. + cos(x[0]-x[1])*sin(x[0]+x[1])
  165. + sin(x[0]-x[1])*cos(x[0]+x[1]);
  166. ijac++;
  167. values[ijac] = 2.
  168. - cos(x[0]-x[1])*sin(x[0]+x[1])
  169. + sin(x[0]-x[1])*cos(x[0]+x[1]);
  170. ijac++;
  171. values[ijac] = -(1.+x[n-4])*exp(x[n-4]-x[n-3]);
  172. ijac++;
  173. values[ijac] = 4. + x[n-4]*exp(x[n-4]-x[n-3]);
  174. ijac++;
  175. }
  176. return true;
  177. }
  178. //return the structure or values of the hessian
  179. bool LuksanVlcek3::eval_h(Index n, const Number* x, bool new_x,
  180. Number obj_factor, Index m, const Number* lambda,
  181. bool new_lambda, Index nele_hess, Index* iRow,
  182. Index* jCol, Number* values)
  183. {
  184. if (values == NULL) {
  185. Index ihes=0;
  186. for (Index i=0; i<N_/2; i++) {
  187. iRow[ihes] = 2*i;
  188. jCol[ihes] = 2*i;
  189. ihes++;
  190. iRow[ihes] = 2*i;
  191. jCol[ihes] = 2*i+1;
  192. ihes++;
  193. iRow[ihes] = 2*i;
  194. jCol[ihes] = 2*i+3;
  195. ihes++;
  196. iRow[ihes] = 2*i+1;
  197. jCol[ihes] = 2*i+1;
  198. ihes++;
  199. iRow[ihes] = 2*i+1;
  200. jCol[ihes] = 2*i+2;
  201. ihes++;
  202. }
  203. iRow[ihes] = N_;
  204. jCol[ihes] = N_;
  205. ihes++;
  206. iRow[ihes] = N_;
  207. jCol[ihes] = N_+1;
  208. ihes++;
  209. iRow[ihes] = N_+1;
  210. jCol[ihes] = N_+1;
  211. ihes++;
  212. DBG_ASSERT(ihes == nele_hess);
  213. }
  214. else {
  215. Index ihes=0;
  216. values[0] = 0.;
  217. values[1] = 0.;
  218. values[3] = 0.;
  219. for (Index i=0; i<N_/2-1; i++) {
  220. Number a3 = x[2*i+1] - 2.*x[2*i+2];
  221. Number a4 = x[2*i] - x[2*i+3];
  222. // x[2*i] x[2*i]
  223. values[ihes] += obj_factor*(2. + 120.*a4*a4);
  224. ihes++;
  225. // x[2*i] x[2*i+1]
  226. values[ihes] += obj_factor*20.;
  227. ihes++;
  228. // x[2*i] x[2*i+3]
  229. values[ihes] = -obj_factor*120.*a4*a4;
  230. ihes++;
  231. // x[2*i+1] x[2*i+1]
  232. values[ihes] += obj_factor*(200. + 12.*a3*a3);
  233. ihes++;
  234. // x[2*i+1] x[2*i+2]
  235. values[ihes] = -obj_factor*24.*a3*a3;
  236. ihes++;
  237. // x[2*i+2] x[2*i+2]
  238. values[ihes] = obj_factor*(10. + 48.*a3*a3);
  239. // x[2*i+2] x[2*i+3]
  240. values[ihes+1] = -obj_factor*10.;
  241. // x[2*i+3] x[2*i+3]
  242. values[ihes+3] = obj_factor*(10. + 120.*a4*a4);
  243. }
  244. {
  245. Index i = N_/2-1;
  246. Number a3 = x[2*i+1] - 2.*x[2*i+2];
  247. Number a4 = x[2*i] - x[2*i+3];
  248. // x[2*i] x[2*i]
  249. values[ihes] += obj_factor*(2. + 120.*a4*a4);
  250. ihes++;
  251. // x[2*i] x[2*i+1]
  252. values[ihes] += obj_factor*20.;
  253. ihes++;
  254. // x[2*i] x[2*i+3]
  255. values[ihes] = -obj_factor*120.*a4*a4;
  256. ihes++;
  257. // x[2*i+1] x[2*i+1]
  258. values[ihes] += obj_factor*(200. + 12.*a3*a3);
  259. ihes++;
  260. // x[2*i+1] x[2*i+2]
  261. values[ihes] = -obj_factor*24.*a3*a3;
  262. ihes++;
  263. // x[2*i+2] x[2*i+2]
  264. values[ihes] = obj_factor*(10. + 48.*a3*a3);
  265. // x[2*i+2] x[2*i+3]
  266. values[ihes+1] = -obj_factor*10.;
  267. // x[2*i+3] x[2*i+3]
  268. values[ihes+2] = obj_factor*(10. + 120.*a4*a4);
  269. }
  270. // Now the constraints
  271. ihes = 0;
  272. Number d1 = x[0] - x[1];
  273. Number d2 = x[0] + x[1];
  274. values[ihes] += lambda[0]*(18.*x[0]
  275. -2.*sin(d1)*sin(d2)
  276. +2.*cos(d1)*cos(d2));
  277. ihes+=3;
  278. values[ihes] += lambda[0]*(-2.*sin(d1)*sin(d2)
  279. -2.*cos(d1)*cos(d2));
  280. d1 = x[n-4]-x[n-3];
  281. // x[n-4] x[n-4]
  282. ihes = nele_hess - 8;
  283. values[ihes] += -lambda[1]*(2.+x[n-4])*exp(d1);
  284. // x[n-4] x[n-3]
  285. ihes++;
  286. values[ihes] += lambda[1]*(1.+x[n-4])*exp(d1);
  287. // x[n-3] x[n-3]
  288. ihes += 2;
  289. values[ihes] += -lambda[1]*x[n-4]*exp(d1);
  290. }
  291. return true;
  292. }
  293. void LuksanVlcek3::finalize_solution(SolverReturn status,
  294. Index n, const Number* x, const Number* z_L, const Number* z_U,
  295. Index m, const Number* g, const Number* lambda,
  296. Number obj_value,
  297. const IpoptData* ip_data,
  298. IpoptCalculatedQuantities* ip_cq)
  299. {}