1 /* npp.c (LP/MIP preprocessing) */
2 
3 /***********************************************************************
4 *  This code is part of GLPK (GNU Linear Programming Kit).
5 *  Copyright (C) 2017 Free Software Foundation, Inc.
6 *  Written by Andrew Makhorin <mao@gnu.org>.
7 *
8 *  GLPK is free software: you can redistribute it and/or modify it
9 *  under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation, either version 3 of the License, or
11 *  (at your option) any later version.
12 *
13 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
14 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 *  License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
20 ***********************************************************************/
21 
22 #include "env.h"
23 #include "npp.h"
24 
glp_npp_alloc_wksp(void)25 glp_prep *glp_npp_alloc_wksp(void)
26 {     /* allocate the preprocessor workspace */
27       glp_prep *prep;
28       prep = npp_create_wksp();
29       return prep;
30 }
31 
glp_npp_load_prob(glp_prep * prep,glp_prob * P,int sol,int names)32 void glp_npp_load_prob(glp_prep *prep, glp_prob *P, int sol, int names)
33 {     /* load original problem instance */
34       if (prep->sol != 0)
35          xerror("glp_npp_load_prob: invalid call sequence (original ins"
36             "tance already loaded)\n");
37       if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP))
38          xerror("glp_npp_load_prob: sol = %d; invalid parameter\n",
39             sol);
40       if (!(names == GLP_ON || names == GLP_OFF))
41          xerror("glp_npp_load_prob: names = %d; invalid parameter\n",
42             names);
43       npp_load_prob(prep, P, names, sol, GLP_OFF);
44       return;
45 }
46 
glp_npp_preprocess1(glp_prep * prep,int hard)47 int glp_npp_preprocess1(glp_prep *prep, int hard)
48 {     /* perform basic LP/MIP preprocessing */
49       if (prep->sol == 0)
50          xerror("glp_npp_preprocess1: invalid call sequence (original i"
51             "nstance not loaded yet)\n");
52       if (prep->pool == NULL)
53          xerror("glp_npp_preprocess1: invalid call sequence (preprocess"
54             "ing already finished)\n");
55       if (!(hard == GLP_ON || hard == GLP_OFF))
56          xerror("glp_npp_preprocess1: hard = %d; invalid parameter\n",
57             hard);
58       return npp_process_prob(prep, hard);
59 }
60 
glp_npp_build_prob(glp_prep * prep,glp_prob * Q)61 void glp_npp_build_prob(glp_prep *prep, glp_prob *Q)
62 {     /* build resultant problem instance */
63       if (prep->sol == 0)
64          xerror("glp_npp_build_prob: invalid call sequence (original in"
65             "stance not loaded yet)\n");
66       if (prep->pool == NULL)
67          xerror("glp_npp_build_prob: invalid call sequence (resultant i"
68             "nstance already built)\n");
69       npp_build_prob(prep, Q);
70       return;
71 }
72 
glp_npp_postprocess(glp_prep * prep,glp_prob * Q)73 void glp_npp_postprocess(glp_prep *prep, glp_prob *Q)
74 {     /* postprocess solution to resultant problem */
75       if (prep->pool != NULL)
76          xerror("glp_npp_postprocess: invalid call sequence (resultant "
77             "instance not built yet)\n");
78       if (!(prep->m == Q->m && prep->n == Q->n && prep->nnz == Q->nnz))
79          xerror("glp_npp_postprocess: resultant instance mismatch\n");
80       switch (prep->sol)
81       {  case GLP_SOL:
82             if (glp_get_status(Q) != GLP_OPT)
83                xerror("glp_npp_postprocess: unable to recover non-optim"
84                   "al basic solution\n");
85             break;
86          case GLP_IPT:
87             if (glp_ipt_status(Q) != GLP_OPT)
88                xerror("glp_npp_postprocess: unable to recover non-optim"
89                   "al interior-point solution\n");
90             break;
91          case GLP_MIP:
92             if (!(glp_mip_status(Q) == GLP_OPT || glp_mip_status(Q) ==
93                GLP_FEAS))
94                xerror("glp_npp_postprocess: unable to recover integer n"
95                   "on-feasible solution\n");
96             break;
97          default:
98             xassert(prep != prep);
99       }
100       npp_postprocess(prep, Q);
101       return;
102 }
103 
glp_npp_obtain_sol(glp_prep * prep,glp_prob * P)104 void glp_npp_obtain_sol(glp_prep *prep, glp_prob *P)
105 {     /* obtain solution to original problem */
106       if (prep->pool != NULL)
107          xerror("glp_npp_obtain_sol: invalid call sequence (resultant i"
108             "nstance not built yet)\n");
109       switch (prep->sol)
110       {  case GLP_SOL:
111             if (prep->p_stat == 0 || prep->d_stat == 0)
112                xerror("glp_npp_obtain_sol: invalid call sequence (basic"
113                   " solution not provided yet)\n");
114             break;
115          case GLP_IPT:
116             if (prep->t_stat == 0)
117                xerror("glp_npp_obtain_sol: invalid call sequence (inter"
118                   "ior-point solution not provided yet)\n");
119             break;
120          case GLP_MIP:
121             if (prep->i_stat == 0)
122                xerror("glp_npp_obtain_sol: invalid call sequence (MIP s"
123                   "olution not provided yet)\n");
124             break;
125          default:
126             xassert(prep != prep);
127       }
128       if (!(prep->orig_dir == P->dir && prep->orig_m == P->m &&
129             prep->orig_n == P->n && prep->orig_nnz == P->nnz))
130          xerror("glp_npp_obtain_sol: original instance mismatch\n");
131       npp_unload_sol(prep, P);
132       return;
133 }
134 
glp_npp_free_wksp(glp_prep * prep)135 void glp_npp_free_wksp(glp_prep *prep)
136 {     /* free the preprocessor workspace */
137       npp_delete_wksp(prep);
138       return;
139 }
140 
141 /* eof */
142