The source code and dockerfile for the GSW2024 AI Lab.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

283 lines
9.4 KiB

2 months ago
  1. @.@ LP/MIP PREPROCESSING ROUTINES
  2. =================================
  3. @.@.1 Introduction
  4. GLPK has a set of routines that constitute so called the LP/MIP
  5. preprocessor. Its main purpose is to improve a given formulation of the
  6. LP or MIP problem instance provided by the user.
  7. As a rule the LP/MIP preprocessor is used internally (if enabled) in
  8. the LP or MIP solver. However, for various reasons the user may need
  9. to call the preprocessing routines directly in his/her application
  10. program, in which case he/she may use API routines described in this
  11. section.
  12. The preprocessing of an LP/MIP problem instance and recovering its
  13. solution include several steps, which are performed in the following
  14. order.
  15. 1. Allocating the workspace. The preprocessor allocates the workspace,
  16. an internal data structure used on all subsequent steps.
  17. 2. Loading the original problem instance. The preprocessor copies all
  18. the problem components from the original problem object (glp_prob)
  19. specified by the user into the workspace. On this step the user also
  20. should specify the solution type: basic solution (assumes the
  21. primal or dual simplex solver), interior-point solution (assumes the
  22. interior-point solver), or MIP solution (assumes the MIP solver).
  23. This is needed, because some preprocessing transformations depend on
  24. the solution type.
  25. 3. Preprocessing. The user calls preprocessing routines that transform
  26. the problem instance residing in the workspace.
  27. 4. Building the resultant problem instance. The preprocessor converts
  28. the problem instance from an internal workspace representation
  29. to the standard problem object (glp_prob) and returns that object to
  30. the user.
  31. 5. Solving the resultant problem instance. The user calls an
  32. appropriate solver routine to obtain a solution to the resultant
  33. problem instance.
  34. 6. Postprocessing. The user provides the solution to the resultant
  35. problem instance found on the previous step, and the preprocessor
  36. performs inverse transformations to recover the solution to the
  37. original problem instance. Should note that only optimal or integer
  38. feasible (for MIP) solutions can be recovered.
  39. 7. Obtaining original solution. The preprocessor copies the solution
  40. to the original problem instance recovered on the previous step from
  41. the workspace to the original problem object (glp_prob). The effect
  42. is the same as if the solution were computed by a solver. Note that
  43. steps 6 and 7 can be performed multiple times (for example, to
  44. recover intermediate integer feasible solutions during the integer
  45. optimization).
  46. 8. Freeing the workspace. The preprocessor frees all the memory
  47. allocated to the workspace.
  48. EXAMPLE
  49. In this example the program reads the LP problem data from input file
  50. murtagh.mps\footnote{This is an example model included in the GLPK
  51. distribution.}, performs standard preprocessing, solves the resultant
  52. LP with the primal simplex method, and then recovers the solution to
  53. the original LP.
  54. /* nppsamp.c */
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <glpk.h>
  58. int main(void)
  59. { glp_prep *npp;
  60. glp_prob *P, *Q;
  61. int ret;
  62. npp = glp_npp_alloc_wksp();
  63. P = glp_create_prob();
  64. ret = glp_read_mps(P, GLP_MPS_DECK, NULL, "murtagh.mps");
  65. if (ret != 0)
  66. { printf("Error on reading problem data\n");
  67. goto skip;
  68. }
  69. glp_set_obj_dir(P, GLP_MAX);
  70. glp_npp_load_prob(npp, P, GLP_SOL, GLP_ON);
  71. ret = glp_npp_preprocess1(npp, 0);
  72. switch (ret)
  73. { case 0:
  74. break;
  75. case GLP_ENOPFS:
  76. printf("LP has no primal feasible solution\n");
  77. goto skip;
  78. case GLP_ENODFS:
  79. printf("LP has no dual feasible solution\n");
  80. goto skip;
  81. default:
  82. xassert(ret != ret);
  83. }
  84. Q = glp_create_prob();
  85. glp_npp_build_prob(npp, Q);
  86. ret = glp_simplex(Q, NULL);
  87. if (ret == 0 && glp_get_status(Q) == GLP_OPT)
  88. { glp_npp_postprocess(npp, Q);
  89. glp_npp_obtain_sol(npp, P);
  90. }
  91. else
  92. printf("Unable to recover non-optimal solution\n");
  93. glp_delete_prob(Q);
  94. skip: glp_npp_free_wksp(npp);
  95. glp_delete_prob(P);
  96. return 0;
  97. }
  98. /* eof */
  99. ------------------------------------------------------------------------
  100. @.@.2 glp_npp_alloc_wksp - allocate the preprocessor workspace
  101. SYNOPSIS
  102. glp_prep *glp_npp_alloc_wksp(void);
  103. DESCRIPTION
  104. The routine glp_npp_alloc_wksp allocates the preprocessor workspace.
  105. (Note that multiple instances of the workspace may be allocated, if
  106. necessary.)
  107. RETURNS
  108. The routine returns a pointer to the workspace, which should be used in
  109. all subsequent operations.
  110. ------------------------------------------------------------------------
  111. @.@.3 glp_npp_load_prob - load original problem instance
  112. SYNOPSIS
  113. void glp_npp_load_prob(glp_prep *prep, glp_prob *P, int sol,
  114. int names);
  115. DESCRIPTION
  116. The routine glp_npp_load_prob loads the original problem instance from
  117. the specified problem object P into the preprocessor workspace. (Note
  118. that this operation can be performed only once.)
  119. The parameter sol specifies which solution is required:
  120. GLP_SOL - basic solution;
  121. GLP_IPT - interior-point solution;
  122. GLP_MIP - mixed integer solution.
  123. The parameter names is a flag. If it is GLP_ON, the symbolic names of
  124. original rows and columns are also loaded into the workspace. Otherwise,
  125. if the flag is GLP_OFF, the row and column names are not loaded.
  126. ------------------------------------------------------------------------
  127. @.@.4 glp_npp_preprocess1 - perform basic LP/MIP preprocessing
  128. SYNOPSIS
  129. int glp_npp_preprocess1(glp_prep *prep, int hard);
  130. DESCRIPTION
  131. The routine glp_npp_preprocess1 performs basic LP/MIP preprocessing
  132. that currently includes:
  133. -- removing free rows;
  134. -- replacing double-sided constraint rows with almost identical bounds,
  135. by equality constraint rows;
  136. -- removing fixed columns;
  137. -- replacing double-bounded columns with almost identical bounds by
  138. fixed columns and removing those columns;
  139. -- removing empty rows;
  140. -- removing equality constraint row singletons and corresponding
  141. columns;
  142. -- removing inequality constraint row singletons and corresponding
  143. columns;
  144. -- performing general row analysis;
  145. -- removing redundant row bounds;
  146. -- removing forcing rows and corresponding columns;
  147. -- removing rows which become free due to redundant bounds;
  148. -- computing implied bounds for all columns and using them to
  149. strengthen current column bounds (MIP only, optional, performed if
  150. the flag hard is on);
  151. -- fixing and removing empty columns;
  152. -- removing column singletons, which are implied slack variables, and
  153. corresponding rows;
  154. -- removing bounds of columns, which are implied free variables, and
  155. replacing corresponding rows by equality constraints.
  156. If the flag hard is GLP_ON, the routine attempts to improve current
  157. column bounds multiple times within the main processing loop, in which
  158. case this feature may take a time. Otherwise, if the flag hard is
  159. GLP_OFF, improving column bounds is performed only once at the end of
  160. the main loop. (Note that this feature is used for MIP only.)
  161. RETURNS
  162. 0 - the problem instance has been successfully preprocessed;
  163. GLP_ENOPFS - primal/integer infeasibility has been detected;
  164. GLP_ENODFS - dual infeasibility has been detected.
  165. ------------------------------------------------------------------------
  166. @.@.5 glp_npp_build_prob - build resultant problem instance
  167. SYNOPSIS
  168. void glp_npp_build_prob(glp_prep *prep, glp_prob *Q);
  169. DESCRIPTION
  170. The routine glp_npp_build_prob obtains all necessary information from
  171. the preprocessor workspace to build the resultant (preprocessed)
  172. problem instance, and stores it in the specified problem object Q. Note
  173. that before building the current content of this problem object is
  174. erased with the routine glp_erase_prob.
  175. ------------------------------------------------------------------------
  176. @.@.6 glp_npp_postprocess - postprocess solution to resultant problem
  177. SYNOPSIS
  178. void glp_npp_postprocess(glp_prep *prep, glp_prob *Q);
  179. DESCRIPTION
  180. The routine glp_npp_postprocess performs postprocessing of a solution
  181. to the resultant (preprocessed) problem instance specified by the
  182. problem object Q and recovers corrseponding solution to the original
  183. problem instance. The recovered solution is stored in the preprocessor
  184. workspace and can be obtained with the routine glp_npp_obtain_sol.
  185. It is assumed that the resultant problem instance Q has been solved
  186. with an appropriate solver depending on the solution type previously
  187. passed to the routine glp_npp_load_prob (the parameter sol). Note that
  188. only optimal or integer feasible (for MIP) solution can be recovered,
  189. so the calling program should use the routine glp_status to make sure
  190. that this condition is met.
  191. ------------------------------------------------------------------------
  192. @.@.7 glp_npp_obtain_sol - obtain solution to original problem
  193. SYNOPSIS
  194. void glp_npp_obtain_sol(glp_prep *prep, glp_prob *P);
  195. DESCRIPTION
  196. The routine glp_npp_obtain_sol copies the solution to the original
  197. problem instance previously recovered by the routine
  198. glp_npp_postorocess from the preprocessor workspace to the problem
  199. object P. The effect is the same as if the solution were computed by an
  200. appropriate solver.
  201. ------------------------------------------------------------------------
  202. @.@.8 glp_npp_free_wksp - free the preprocessor workspace
  203. SYNOPSIS
  204. void glp_npp_free_wksp(glp_prep *prep);
  205. DESCRIPTION
  206. The routine glp_npp_free_wksp frees all the memory allocated to the
  207. preprocessor workspace.
  208. ===EOF===