hs71c.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /* Copyright (C) 2005, 2011 International Business Machines and others.
  2. * All Rights Reserved.
  3. * This code is published under the Eclipse Public License.
  4. *
  5. * $Id: hs071_c.c 1996 2011-05-05 19:28:44Z andreasw $
  6. *
  7. * Authors: Carl Laird, Andreas Waechter IBM 2005-08-17
  8. */
  9. #include "IpStdCInterface.h"
  10. #include <stdlib.h>
  11. #include <assert.h>
  12. #include <stdio.h>
  13. /* Function Declarations */
  14. Bool eval_f(Index n, Number* x, Bool new_x,
  15. Number* obj_value, UserDataPtr user_data);
  16. Bool eval_grad_f(Index n, Number* x, Bool new_x,
  17. Number* grad_f, UserDataPtr user_data);
  18. Bool eval_g(Index n, Number* x, Bool new_x,
  19. Index m, Number* g, UserDataPtr user_data);
  20. Bool eval_jac_g(Index n, Number *x, Bool new_x,
  21. Index m, Index nele_jac,
  22. Index *iRow, Index *jCol, Number *values,
  23. UserDataPtr user_data);
  24. Bool eval_h(Index n, Number *x, Bool new_x, Number obj_factor,
  25. Index m, Number *lambda, Bool new_lambda,
  26. Index nele_hess, Index *iRow, Index *jCol,
  27. Number *values, UserDataPtr user_data);
  28. Bool intermediate_cb(Index alg_mod, Index iter_count, Number obj_value,
  29. Number inf_pr, Number inf_du, Number mu, Number d_norm,
  30. Number regularization_size, Number alpha_du,
  31. Number alpha_pr, Index ls_trials, UserDataPtr user_data);
  32. /* This is an example how user_data can be used. */
  33. struct MyUserData
  34. {
  35. Number g_offset[2]; /* This is an offset for the constraints. */
  36. };
  37. /* Main Program */
  38. int main2()
  39. {
  40. Index n=-1; /* number of variables */
  41. Index m=-1; /* number of constraints */
  42. Number* x_L = NULL; /* lower bounds on x */
  43. Number* x_U = NULL; /* upper bounds on x */
  44. Number* g_L = NULL; /* lower bounds on g */
  45. Number* g_U = NULL; /* upper bounds on g */
  46. IpoptProblem nlp = NULL; /* IpoptProblem */
  47. enum ApplicationReturnStatus status; /* Solve return code */
  48. Number* x = NULL; /* starting point and solution vector */
  49. Number* mult_g = NULL; /* constraint multipliers
  50. at the solution */
  51. Number* mult_x_L = NULL; /* lower bound multipliers
  52. at the solution */
  53. Number* mult_x_U = NULL; /* upper bound multipliers
  54. at the solution */
  55. Number obj; /* objective value */
  56. Index i; /* generic counter */
  57. /* Number of nonzeros in the Jacobian of the constraints */
  58. Index nele_jac = 8;
  59. /* Number of nonzeros in the Hessian of the Lagrangian (lower or
  60. upper triangual part only) */
  61. Index nele_hess = 10;
  62. /* indexing style for matrices */
  63. Index index_style = 0; /* C-style; start counting of rows and column
  64. indices at 0 */
  65. /* our user data for the function evalutions. */
  66. struct MyUserData user_data;
  67. /* set the number of variables and allocate space for the bounds */
  68. n=4;
  69. x_L = (Number*)malloc(sizeof(Number)*n);
  70. x_U = (Number*)malloc(sizeof(Number)*n);
  71. /* set the values for the variable bounds */
  72. for (i=0; i<n; i++) {
  73. x_L[i] = 1.0;
  74. x_U[i] = 5.0;
  75. }
  76. /* set the number of constraints and allocate space for the bounds */
  77. m=2;
  78. g_L = (Number*)malloc(sizeof(Number)*m);
  79. g_U = (Number*)malloc(sizeof(Number)*m);
  80. /* set the values of the constraint bounds */
  81. g_L[0] = 25;
  82. g_U[0] = 2e19;
  83. g_L[1] = 40;
  84. g_U[1] = 40;
  85. /* create the IpoptProblem */
  86. nlp = CreateIpoptProblem(n, x_L, x_U, m, g_L, g_U, nele_jac, nele_hess,
  87. index_style, &eval_f, &eval_g, &eval_grad_f,
  88. &eval_jac_g, &eval_h);
  89. /* We can free the memory now - the values for the bounds have been
  90. copied internally in CreateIpoptProblem */
  91. free(x_L);
  92. free(x_U);
  93. free(g_L);
  94. free(g_U);
  95. /* Set some options. Note the following ones are only examples,
  96. they might not be suitable for your problem. */
  97. AddIpoptNumOption(nlp, "tol", 1e-7);
  98. AddIpoptStrOption(nlp, "mu_strategy", "adaptive");
  99. AddIpoptStrOption(nlp, "output_file", "ipopt.out");
  100. /* allocate space for the initial point and set the values */
  101. x = (Number*)malloc(sizeof(Number)*n);
  102. x[0] = 1.0;
  103. x[1] = 5.0;
  104. x[2] = 5.0;
  105. x[3] = 1.0;
  106. /* allocate space to store the bound multipliers at the solution */
  107. mult_g = (Number*)malloc(sizeof(Number)*m);
  108. mult_x_L = (Number*)malloc(sizeof(Number)*n);
  109. mult_x_U = (Number*)malloc(sizeof(Number)*n);
  110. /* Initialize the user data */
  111. user_data.g_offset[0] = 0.;
  112. user_data.g_offset[1] = 0.;
  113. /* Set the callback method for intermediate user-control. This is
  114. * not required, just gives you some intermediate control in case
  115. * you need it. */
  116. /* SetIntermediateCallback(nlp, intermediate_cb); */
  117. /* solve the problem */
  118. status = IpoptSolve(nlp, x, NULL, &obj, mult_g, mult_x_L, mult_x_U, &user_data);
  119. if (status == Solve_Succeeded) {
  120. printf("\n\nSolution of the primal variables, x\n");
  121. for (i=0; i<n; i++) {
  122. printf("x[%d] = %e\n", i, x[i]);
  123. }
  124. printf("\n\nSolution of the ccnstraint multipliers, lambda\n");
  125. for (i=0; i<m; i++) {
  126. printf("lambda[%d] = %e\n", i, mult_g[i]);
  127. }
  128. printf("\n\nSolution of the bound multipliers, z_L and z_U\n");
  129. for (i=0; i<n; i++) {
  130. printf("z_L[%d] = %e\n", i, mult_x_L[i]);
  131. }
  132. for (i=0; i<n; i++) {
  133. printf("z_U[%d] = %e\n", i, mult_x_U[i]);
  134. }
  135. printf("\n\nObjective value\n");
  136. printf("f(x*) = %e\n", obj);
  137. }
  138. else {
  139. printf("\n\nERROR OCCURRED DURING IPOPT OPTIMIZATION.\n");
  140. }
  141. /* Now we are going to solve this problem again, but with slightly
  142. modified constraints. We change the constraint offset of the
  143. first constraint a bit, and resolve the problem using the warm
  144. start option. */
  145. user_data.g_offset[0] = 0.2;
  146. if (status == Solve_Succeeded) {
  147. /* Now resolve with a warmstart. */
  148. AddIpoptStrOption(nlp, "warm_start_init_point", "yes");
  149. /* The following option reduce the automatic modification of the
  150. starting point done my Ipopt. */
  151. AddIpoptNumOption(nlp, "bound_push", 1e-5);
  152. AddIpoptNumOption(nlp, "bound_frac", 1e-5);
  153. status = IpoptSolve(nlp, x, NULL, &obj, mult_g, mult_x_L, mult_x_U, &user_data);
  154. if (status == Solve_Succeeded) {
  155. printf("\n\nSolution of the primal variables, x\n");
  156. for (i=0; i<n; i++) {
  157. printf("x[%d] = %e\n", i, x[i]);
  158. }
  159. printf("\n\nSolution of the ccnstraint multipliers, lambda\n");
  160. for (i=0; i<m; i++) {
  161. printf("lambda[%d] = %e\n", i, mult_g[i]);
  162. }
  163. printf("\n\nSolution of the bound multipliers, z_L and z_U\n");
  164. for (i=0; i<n; i++) {
  165. printf("z_L[%d] = %e\n", i, mult_x_L[i]);
  166. }
  167. for (i=0; i<n; i++) {
  168. printf("z_U[%d] = %e\n", i, mult_x_U[i]);
  169. }
  170. printf("\n\nObjective value\n");
  171. printf("f(x*) = %e\n", obj);
  172. }
  173. else {
  174. printf("\n\nERROR OCCURRED DURING IPOPT OPTIMIZATION WITH WARM START.\n");
  175. }
  176. }
  177. /* free allocated memory */
  178. FreeIpoptProblem(nlp);
  179. free(x);
  180. free(mult_g);
  181. free(mult_x_L);
  182. free(mult_x_U);
  183. return (int)status;
  184. }
  185. /* Function Implementations */
  186. Bool eval_f(Index n, Number* x, Bool new_x,
  187. Number* obj_value, UserDataPtr user_data)
  188. {
  189. assert(n == 4);
  190. *obj_value = x[0] * x[3] * (x[0] + x[1] + x[2]) + x[2];
  191. return TRUE;
  192. }
  193. Bool eval_grad_f(Index n, Number* x, Bool new_x,
  194. Number* grad_f, UserDataPtr user_data)
  195. {
  196. assert(n == 4);
  197. grad_f[0] = x[0] * x[3] + x[3] * (x[0] + x[1] + x[2]);
  198. grad_f[1] = x[0] * x[3];
  199. grad_f[2] = x[0] * x[3] + 1;
  200. grad_f[3] = x[0] * (x[0] + x[1] + x[2]);
  201. return TRUE;
  202. }
  203. Bool eval_g(Index n, Number* x, Bool new_x,
  204. Index m, Number* g, UserDataPtr user_data)
  205. {
  206. struct MyUserData* my_data = user_data;
  207. assert(n == 4);
  208. assert(m == 2);
  209. g[0] = x[0] * x[1] * x[2] * x[3] + my_data->g_offset[0];
  210. g[1] = x[0]*x[0] + x[1]*x[1] + x[2]*x[2] + x[3]*x[3] + my_data->g_offset[1];
  211. return TRUE;
  212. }
  213. Bool eval_jac_g(Index n, Number *x, Bool new_x,
  214. Index m, Index nele_jac,
  215. Index *iRow, Index *jCol, Number *values,
  216. UserDataPtr user_data)
  217. {
  218. if (values == NULL) {
  219. /* return the structure of the jacobian */
  220. /* this particular jacobian is dense */
  221. iRow[0] = 0;
  222. jCol[0] = 0;
  223. iRow[1] = 0;
  224. jCol[1] = 1;
  225. iRow[2] = 0;
  226. jCol[2] = 2;
  227. iRow[3] = 0;
  228. jCol[3] = 3;
  229. iRow[4] = 1;
  230. jCol[4] = 0;
  231. iRow[5] = 1;
  232. jCol[5] = 1;
  233. iRow[6] = 1;
  234. jCol[6] = 2;
  235. iRow[7] = 1;
  236. jCol[7] = 3;
  237. }
  238. else {
  239. /* return the values of the jacobian of the constraints */
  240. values[0] = x[1]*x[2]*x[3]; /* 0,0 */
  241. values[1] = x[0]*x[2]*x[3]; /* 0,1 */
  242. values[2] = x[0]*x[1]*x[3]; /* 0,2 */
  243. values[3] = x[0]*x[1]*x[2]; /* 0,3 */
  244. values[4] = 2*x[0]; /* 1,0 */
  245. values[5] = 2*x[1]; /* 1,1 */
  246. values[6] = 2*x[2]; /* 1,2 */
  247. values[7] = 2*x[3]; /* 1,3 */
  248. }
  249. return TRUE;
  250. }
  251. Bool eval_h(Index n, Number *x, Bool new_x, Number obj_factor,
  252. Index m, Number *lambda, Bool new_lambda,
  253. Index nele_hess, Index *iRow, Index *jCol,
  254. Number *values, UserDataPtr user_data)
  255. {
  256. Index idx = 0; /* nonzero element counter */
  257. Index row = 0; /* row counter for loop */
  258. Index col = 0; /* col counter for loop */
  259. if (values == NULL) {
  260. /* return the structure. This is a symmetric matrix, fill the lower left
  261. * triangle only. */
  262. /* the hessian for this problem is actually dense */
  263. idx=0;
  264. for (row = 0; row < 4; row++) {
  265. for (col = 0; col <= row; col++) {
  266. iRow[idx] = row;
  267. jCol[idx] = col;
  268. idx++;
  269. }
  270. }
  271. assert(idx == nele_hess);
  272. }
  273. else {
  274. /* return the values. This is a symmetric matrix, fill the lower left
  275. * triangle only */
  276. /* fill the objective portion */
  277. values[0] = obj_factor * (2*x[3]); /* 0,0 */
  278. values[1] = obj_factor * (x[3]); /* 1,0 */
  279. values[2] = 0; /* 1,1 */
  280. values[3] = obj_factor * (x[3]); /* 2,0 */
  281. values[4] = 0; /* 2,1 */
  282. values[5] = 0; /* 2,2 */
  283. values[6] = obj_factor * (2*x[0] + x[1] + x[2]); /* 3,0 */
  284. values[7] = obj_factor * (x[0]); /* 3,1 */
  285. values[8] = obj_factor * (x[0]); /* 3,2 */
  286. values[9] = 0; /* 3,3 */
  287. /* add the portion for the first constraint */
  288. values[1] += lambda[0] * (x[2] * x[3]); /* 1,0 */
  289. values[3] += lambda[0] * (x[1] * x[3]); /* 2,0 */
  290. values[4] += lambda[0] * (x[0] * x[3]); /* 2,1 */
  291. values[6] += lambda[0] * (x[1] * x[2]); /* 3,0 */
  292. values[7] += lambda[0] * (x[0] * x[2]); /* 3,1 */
  293. values[8] += lambda[0] * (x[0] * x[1]); /* 3,2 */
  294. /* add the portion for the second constraint */
  295. values[0] += lambda[1] * 2; /* 0,0 */
  296. values[2] += lambda[1] * 2; /* 1,1 */
  297. values[5] += lambda[1] * 2; /* 2,2 */
  298. values[9] += lambda[1] * 2; /* 3,3 */
  299. }
  300. return TRUE;
  301. }
  302. Bool intermediate_cb(Index alg_mod, Index iter_count, Number obj_value,
  303. Number inf_pr, Number inf_du, Number mu, Number d_norm,
  304. Number regularization_size, Number alpha_du,
  305. Number alpha_pr, Index ls_trials, UserDataPtr user_data)
  306. {
  307. printf("Testing intermediate callback in iteration %d\n", iter_count);
  308. if (inf_pr < 1e-4) return FALSE;
  309. return TRUE;
  310. }