LuksanVlcek4.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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: LuksanVlcek4.cpp 2005 2011-06-06 12:55:16Z stefan $
  6. //
  7. // Authors: Andreas Waechter IBM 2005-10-127
  8. #include "LuksanVlcek4.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. LuksanVlcek4::LuksanVlcek4(Number g_l, Number g_u)
  34. {
  35. g_l_ = g_l;
  36. g_u_ = g_u;
  37. }
  38. bool LuksanVlcek4::InitializeProblem(Index N)
  39. {
  40. N_=N;
  41. if (N_<=1 || 4*((N_+2)/4)!=N_+2) {
  42. printf("N needs to be at least 2 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 LuksanVlcek4::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 LuksanVlcek4.hpp has 4 variables, x[0] through x[3]
  52. n = N_+2;
  53. m = N_-2;
  54. nnz_jac_g = 3 * m;
  55. nnz_h_lag = n + n-1;
  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 LuksanVlcek4::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 LuksanVlcek4::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] = 1.;
  88. x[4*i+1] = 2.;
  89. x[4*i+2] = 2.;
  90. x[4*i+3] = 2.;
  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 LuksanVlcek4::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 e0 = exp(x[2*i]);
  106. Number e0mx1 = e0 - x[2*i+1];
  107. Number x1mx2 = x[2*i+1] - x[2*i+2];
  108. Number x2mx3 = x[2*i+2] - x[2*i+3];
  109. Number t = tan(x2mx3);
  110. Number x3m1 = x[2*i+3] - 1.;
  111. obj_value += pow(e0mx1,4) + 100.*pow(x1mx2,6) + pow(t,4)
  112. + pow(x[2*i],8) + x3m1*x3m1;
  113. }
  114. return true;
  115. }
  116. // return the gradient of the objective function grad_{x} f(x)
  117. bool LuksanVlcek4::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
  118. {
  119. grad_f[0] = 0.;
  120. grad_f[1] = 0.;
  121. for (Index i=0; i<N_/2; i++) {
  122. Number e0 = exp(x[2*i]);
  123. Number e0mx1 = e0 - x[2*i+1];
  124. Number x1mx2 = x[2*i+1] - x[2*i+2];
  125. Number x2mx3 = x[2*i+2] - x[2*i+3];
  126. Number x3m1 = x[2*i+3] - 1.;
  127. Number dt = 4.*pow(tan(x2mx3),3)/pow(cos(x2mx3),2);
  128. grad_f[2*i] += 4.*e0*pow(e0mx1,3) + 8.*pow(x[2*i],7);
  129. grad_f[2*i+1] += -4.*pow(e0mx1,3) + 600.*pow(x1mx2,5);
  130. grad_f[2*i+2] = -600.*pow(x1mx2,5) + dt;
  131. grad_f[2*i+3] = -dt + 2.*x3m1;
  132. }
  133. return true;
  134. }
  135. // return the value of the constraints: g(x)
  136. bool LuksanVlcek4::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
  137. {
  138. for (Index i=0; i<N_-2; i++) {
  139. g[i] = 8.*x[i+1]*(x[i+1]*x[i+1]-x[i]) - 2.*(1-x[i+1])
  140. + 4.*(x[i+1]-x[i+2]*x[i+2]);
  141. }
  142. return true;
  143. }
  144. // return the structure or values of the jacobian
  145. bool LuksanVlcek4::eval_jac_g(Index n, const Number* x, bool new_x,
  146. Index m, Index nele_jac, Index* iRow, Index *jCol,
  147. Number* values)
  148. {
  149. if (values == NULL) {
  150. // return the structure of the jacobian
  151. Index ijac = 0;
  152. for (Index i=0; i<N_-2; i++) {
  153. iRow[ijac] = i;
  154. jCol[ijac] = i;
  155. ijac++;
  156. iRow[ijac] = i;
  157. jCol[ijac] = i+1;
  158. ijac++;
  159. iRow[ijac] = i;
  160. jCol[ijac] = i+2;
  161. ijac++;
  162. }
  163. DBG_ASSERT(ijac == nele_jac);
  164. }
  165. else {
  166. // return the values of the jacobian of the constraints
  167. Index ijac = 0;
  168. for (Index i=0; i<N_-2; i++) {
  169. values[ijac] = -8.*x[i+1];
  170. ijac++;
  171. values[ijac] = 6. - 8.*x[i] + 24.*x[i+1]*x[i+1];
  172. ijac++;
  173. values[ijac] = -8.*x[i+2];
  174. ijac++;
  175. }
  176. }
  177. return true;
  178. }
  179. //return the structure or values of the hessian
  180. bool LuksanVlcek4::eval_h(Index n, const Number* x, bool new_x,
  181. Number obj_factor, Index m, const Number* lambda,
  182. bool new_lambda, Index nele_hess, Index* iRow,
  183. Index* jCol, Number* values)
  184. {
  185. if (values == NULL) {
  186. Index ihes=0;
  187. for (Index i=0; i<n-1; i++) {
  188. iRow[ihes] = i;
  189. jCol[ihes] = i;
  190. ihes++;
  191. iRow[ihes] = i;
  192. jCol[ihes] = i+1;
  193. ihes++;
  194. }
  195. iRow[ihes] = n-1;
  196. jCol[ihes] = n-1;
  197. ihes++;
  198. DBG_ASSERT(ihes == nele_hess);
  199. }
  200. else {
  201. // First the objective
  202. Index ihes=0;
  203. values[0] = 0.;
  204. values[1] = 0.;
  205. values[2] = 0.;
  206. for (Index i=0; i<N_/2; i++) {
  207. Number e0 = exp(x[2*i]);
  208. Number e0mx1 = e0 - x[2*i+1];
  209. Number x1mx2 = x[2*i+1] - x[2*i+2];
  210. Number x2mx3 = x[2*i+2] - x[2*i+3];
  211. Number s = sin(x2mx3);
  212. Number ss = s*s;
  213. Number c = cos(x2mx3);
  214. Number ddt = 4.*(3.*ss*c*c + 5.*ss*ss)/pow(c,6);
  215. // x[2*i] x[2*i]
  216. values[ihes] += obj_factor*(4.*e0*pow(e0mx1,3)
  217. + 12*e0*e0*e0mx1*e0mx1
  218. + 56.*pow(x[2*i],6));
  219. ihes++;
  220. // x[2*i] x[2*i+1]
  221. values[ihes] += obj_factor*(-12*e0*e0mx1*e0mx1);
  222. ihes++;
  223. // x[2*i+1] x[2*i+1]
  224. values[ihes] += obj_factor*(3000.*pow(x1mx2,4) + 12.*e0mx1*e0mx1);
  225. ihes++;
  226. // x[2*i+1] x[2*i+2]
  227. values[ihes] = -obj_factor*(3000.*pow(x1mx2,4));
  228. ihes++;
  229. // x[2*i+2] x[2*i+2]
  230. values[ihes] = obj_factor*(3000.*pow(x1mx2,4) + ddt);
  231. // x[2*i+2] x[2*i+3]
  232. values[ihes+1] = -obj_factor*ddt;
  233. // x[2*i+3] x[2*i+3]
  234. values[ihes+2] = obj_factor*(2. + ddt);
  235. }
  236. // Now the constraints
  237. ihes = 0;
  238. for (Index i=0; i<N_-2; i++) {
  239. // x[i] x[i+1]
  240. values[2*i+1] -= lambda[i]*8.;
  241. // x[i+1] x[i+1]
  242. values[2*i+2] += lambda[i]*48.*x[i+1];
  243. // x[i+2] x[i+2]
  244. values[2*i+4] -= lambda[i]*8.;
  245. }
  246. }
  247. return true;
  248. }
  249. void LuksanVlcek4::finalize_solution(SolverReturn status,
  250. Index n, const Number* x, const Number* z_L, const Number* z_U,
  251. Index m, const Number* g, const Number* lambda,
  252. Number obj_value,
  253. const IpoptData* ip_data,
  254. IpoptCalculatedQuantities* ip_cq)
  255. {}