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.
		
		
		
		
		
			
		
			
				
					
					
						
							283 lines
						
					
					
						
							9.4 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							283 lines
						
					
					
						
							9.4 KiB
						
					
					
				
								@.@ LP/MIP PREPROCESSING ROUTINES
							 | 
						|
								=================================
							 | 
						|
								
							 | 
						|
								@.@.1 Introduction
							 | 
						|
								
							 | 
						|
								GLPK has a set of routines that constitute so called the LP/MIP
							 | 
						|
								preprocessor. Its main purpose is to improve a given formulation of the
							 | 
						|
								LP or MIP problem instance provided by the user.
							 | 
						|
								
							 | 
						|
								As a rule the LP/MIP preprocessor is used internally (if enabled) in
							 | 
						|
								the LP or MIP solver. However, for various reasons the user may need
							 | 
						|
								to call the preprocessing routines directly in his/her application
							 | 
						|
								program, in which case he/she may use API routines described in this
							 | 
						|
								section.
							 | 
						|
								
							 | 
						|
								The preprocessing of an LP/MIP problem instance and recovering its
							 | 
						|
								solution include several steps, which are performed in the following
							 | 
						|
								order.
							 | 
						|
								
							 | 
						|
								1. Allocating the workspace. The preprocessor allocates the workspace,
							 | 
						|
								   an internal data structure used on all subsequent steps.
							 | 
						|
								
							 | 
						|
								2. Loading the original problem instance. The preprocessor copies all
							 | 
						|
								   the problem components from the original problem object (glp_prob)
							 | 
						|
								   specified by the user into the workspace. On this step the user also
							 | 
						|
								   should specify the solution type: basic solution (assumes the
							 | 
						|
								   primal or dual simplex solver), interior-point solution (assumes the
							 | 
						|
								   interior-point solver), or MIP solution (assumes the MIP solver).
							 | 
						|
								   This is needed, because some preprocessing transformations depend on
							 | 
						|
								   the solution type.
							 | 
						|
								
							 | 
						|
								3. Preprocessing. The user calls preprocessing routines that transform
							 | 
						|
								   the problem instance residing in the workspace.
							 | 
						|
								
							 | 
						|
								4. Building the resultant problem instance. The preprocessor converts
							 | 
						|
								   the problem instance from an internal workspace representation
							 | 
						|
								   to the standard problem object (glp_prob) and returns that object to
							 | 
						|
								   the user.
							 | 
						|
								
							 | 
						|
								5. Solving the resultant problem instance. The user calls an
							 | 
						|
								   appropriate solver routine to obtain a solution to the resultant
							 | 
						|
								   problem instance.
							 | 
						|
								
							 | 
						|
								6. Postprocessing. The user provides the solution to the resultant
							 | 
						|
								   problem instance found on the previous step, and the preprocessor
							 | 
						|
								   performs inverse transformations to recover the solution to the
							 | 
						|
								   original problem instance. Should note that only optimal or integer
							 | 
						|
								   feasible (for MIP) solutions can be recovered.
							 | 
						|
								
							 | 
						|
								7. Obtaining original solution. The preprocessor copies the solution
							 | 
						|
								   to the original problem instance recovered on the previous step from
							 | 
						|
								   the workspace to the original problem object (glp_prob). The effect
							 | 
						|
								   is the same as if the solution were computed by a solver. Note that
							 | 
						|
								   steps 6 and 7 can be performed multiple times (for example, to
							 | 
						|
								   recover intermediate integer feasible solutions during the integer
							 | 
						|
								   optimization).
							 | 
						|
								
							 | 
						|
								8. Freeing the workspace. The preprocessor frees all the memory
							 | 
						|
								   allocated to the workspace.
							 | 
						|
								
							 | 
						|
								EXAMPLE
							 | 
						|
								
							 | 
						|
								In this example the program reads the LP problem data from input file
							 | 
						|
								murtagh.mps\footnote{This is an example model included in the GLPK
							 | 
						|
								distribution.}, performs standard preprocessing, solves the resultant
							 | 
						|
								LP with the primal simplex method, and then recovers the solution to
							 | 
						|
								the original LP.
							 | 
						|
								
							 | 
						|
								/* nppsamp.c */
							 | 
						|
								
							 | 
						|
								#include <stdio.h>
							 | 
						|
								#include <stdlib.h>
							 | 
						|
								#include <glpk.h>
							 | 
						|
								
							 | 
						|
								int main(void)
							 | 
						|
								{     glp_prep *npp;
							 | 
						|
								      glp_prob *P, *Q;
							 | 
						|
								      int ret;
							 | 
						|
								      npp = glp_npp_alloc_wksp();
							 | 
						|
								      P = glp_create_prob();
							 | 
						|
								      ret = glp_read_mps(P, GLP_MPS_DECK, NULL, "murtagh.mps");
							 | 
						|
								      if (ret != 0)
							 | 
						|
								      {  printf("Error on reading problem data\n");
							 | 
						|
								         goto skip;
							 | 
						|
								      }
							 | 
						|
								      glp_set_obj_dir(P, GLP_MAX);
							 | 
						|
								      glp_npp_load_prob(npp, P, GLP_SOL, GLP_ON);
							 | 
						|
								      ret = glp_npp_preprocess1(npp, 0);
							 | 
						|
								      switch (ret)
							 | 
						|
								      {  case 0:
							 | 
						|
								            break;
							 | 
						|
								         case GLP_ENOPFS:
							 | 
						|
								            printf("LP has no primal feasible solution\n");
							 | 
						|
								            goto skip;
							 | 
						|
								         case GLP_ENODFS:
							 | 
						|
								            printf("LP has no dual feasible solution\n");
							 | 
						|
								            goto skip;
							 | 
						|
								         default:
							 | 
						|
								            xassert(ret != ret);
							 | 
						|
								      }
							 | 
						|
								      Q = glp_create_prob();
							 | 
						|
								      glp_npp_build_prob(npp, Q);
							 | 
						|
								      ret = glp_simplex(Q, NULL);
							 | 
						|
								      if (ret == 0 && glp_get_status(Q) == GLP_OPT)
							 | 
						|
								      {  glp_npp_postprocess(npp, Q);
							 | 
						|
								         glp_npp_obtain_sol(npp, P);
							 | 
						|
								      }
							 | 
						|
								      else
							 | 
						|
								         printf("Unable to recover non-optimal solution\n");
							 | 
						|
								      glp_delete_prob(Q);
							 | 
						|
								skip: glp_npp_free_wksp(npp);
							 | 
						|
								      glp_delete_prob(P);
							 | 
						|
								      return 0;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								/* eof */
							 | 
						|
								------------------------------------------------------------------------
							 | 
						|
								@.@.2 glp_npp_alloc_wksp - allocate the preprocessor workspace
							 | 
						|
								
							 | 
						|
								SYNOPSIS
							 | 
						|
								
							 | 
						|
								glp_prep *glp_npp_alloc_wksp(void);
							 | 
						|
								
							 | 
						|
								DESCRIPTION
							 | 
						|
								
							 | 
						|
								The routine glp_npp_alloc_wksp allocates the preprocessor workspace.
							 | 
						|
								(Note that multiple instances of the workspace may be allocated, if
							 | 
						|
								necessary.)
							 | 
						|
								
							 | 
						|
								RETURNS
							 | 
						|
								
							 | 
						|
								The routine returns a pointer to the workspace, which should be used in
							 | 
						|
								all subsequent operations.
							 | 
						|
								------------------------------------------------------------------------
							 | 
						|
								@.@.3 glp_npp_load_prob - load original problem instance
							 | 
						|
								
							 | 
						|
								SYNOPSIS
							 | 
						|
								
							 | 
						|
								void glp_npp_load_prob(glp_prep *prep, glp_prob *P, int sol,
							 | 
						|
								      int names);
							 | 
						|
								
							 | 
						|
								DESCRIPTION
							 | 
						|
								
							 | 
						|
								The routine glp_npp_load_prob loads the original problem instance from
							 | 
						|
								the specified problem object P into the preprocessor workspace. (Note
							 | 
						|
								that this operation can be performed only once.)
							 | 
						|
								
							 | 
						|
								The parameter sol specifies which solution is required:
							 | 
						|
								
							 | 
						|
								GLP_SOL - basic solution;
							 | 
						|
								
							 | 
						|
								GLP_IPT - interior-point solution;
							 | 
						|
								
							 | 
						|
								GLP_MIP - mixed integer solution.
							 | 
						|
								
							 | 
						|
								The parameter names is a flag. If it is GLP_ON, the symbolic names of
							 | 
						|
								original rows and columns are also loaded into the workspace. Otherwise,
							 | 
						|
								if the flag is GLP_OFF, the row and column names are not loaded.
							 | 
						|
								------------------------------------------------------------------------
							 | 
						|
								@.@.4 glp_npp_preprocess1 - perform basic LP/MIP preprocessing
							 | 
						|
								
							 | 
						|
								SYNOPSIS
							 | 
						|
								
							 | 
						|
								int glp_npp_preprocess1(glp_prep *prep, int hard);
							 | 
						|
								
							 | 
						|
								DESCRIPTION
							 | 
						|
								
							 | 
						|
								The routine glp_npp_preprocess1 performs basic LP/MIP preprocessing
							 | 
						|
								that currently includes:
							 | 
						|
								
							 | 
						|
								-- removing free rows;
							 | 
						|
								
							 | 
						|
								-- replacing double-sided constraint rows with almost identical bounds,
							 | 
						|
								   by equality constraint rows;
							 | 
						|
								
							 | 
						|
								-- removing fixed columns;
							 | 
						|
								
							 | 
						|
								-- replacing double-bounded columns with almost identical bounds by
							 | 
						|
								   fixed columns and removing those columns;
							 | 
						|
								
							 | 
						|
								-- removing empty rows;
							 | 
						|
								
							 | 
						|
								-- removing equality constraint row singletons and corresponding
							 | 
						|
								   columns;
							 | 
						|
								
							 | 
						|
								-- removing inequality constraint row singletons and corresponding
							 | 
						|
								   columns;
							 | 
						|
								
							 | 
						|
								-- performing general row analysis;
							 | 
						|
								
							 | 
						|
								-- removing redundant row bounds;
							 | 
						|
								
							 | 
						|
								-- removing forcing rows and corresponding columns;
							 | 
						|
								
							 | 
						|
								-- removing rows which become free due to redundant bounds;
							 | 
						|
								
							 | 
						|
								-- computing implied bounds for all columns and using them to
							 | 
						|
								   strengthen current column bounds (MIP only, optional, performed if
							 | 
						|
								   the flag hard is on);
							 | 
						|
								
							 | 
						|
								-- fixing and removing empty columns;
							 | 
						|
								
							 | 
						|
								-- removing column singletons, which are implied slack variables, and
							 | 
						|
								   corresponding rows;
							 | 
						|
								
							 | 
						|
								-- removing bounds of columns, which are implied free variables, and
							 | 
						|
								   replacing corresponding rows by equality constraints.
							 | 
						|
								
							 | 
						|
								If the flag hard is GLP_ON, the routine attempts to improve current
							 | 
						|
								column bounds multiple times within the main processing loop, in which
							 | 
						|
								case this feature may take a time. Otherwise, if the flag hard is
							 | 
						|
								GLP_OFF, improving column bounds is performed only once at the end of
							 | 
						|
								the main loop. (Note that this feature is used for MIP only.)
							 | 
						|
								
							 | 
						|
								RETURNS
							 | 
						|
								
							 | 
						|
								0          - the problem instance has been successfully preprocessed;
							 | 
						|
								
							 | 
						|
								GLP_ENOPFS - primal/integer infeasibility has been detected;
							 | 
						|
								
							 | 
						|
								GLP_ENODFS - dual infeasibility has been detected.
							 | 
						|
								------------------------------------------------------------------------
							 | 
						|
								@.@.5 glp_npp_build_prob - build resultant problem instance
							 | 
						|
								
							 | 
						|
								SYNOPSIS
							 | 
						|
								
							 | 
						|
								void glp_npp_build_prob(glp_prep *prep, glp_prob *Q);
							 | 
						|
								
							 | 
						|
								DESCRIPTION
							 | 
						|
								
							 | 
						|
								The routine glp_npp_build_prob obtains all necessary information from
							 | 
						|
								the preprocessor workspace to build the resultant (preprocessed)
							 | 
						|
								problem instance, and stores it in the specified problem object Q. Note
							 | 
						|
								that before building the current content of this problem object is
							 | 
						|
								erased with the routine glp_erase_prob.
							 | 
						|
								------------------------------------------------------------------------
							 | 
						|
								@.@.6 glp_npp_postprocess - postprocess solution to resultant problem
							 | 
						|
								
							 | 
						|
								SYNOPSIS
							 | 
						|
								
							 | 
						|
								void glp_npp_postprocess(glp_prep *prep, glp_prob *Q);
							 | 
						|
								
							 | 
						|
								DESCRIPTION
							 | 
						|
								
							 | 
						|
								The routine glp_npp_postprocess performs postprocessing of a solution
							 | 
						|
								to the resultant (preprocessed) problem instance specified by the
							 | 
						|
								problem object Q and recovers corrseponding solution to the original
							 | 
						|
								problem instance. The recovered solution is stored in the preprocessor
							 | 
						|
								workspace and can be obtained with the routine glp_npp_obtain_sol.
							 | 
						|
								
							 | 
						|
								It is assumed that the resultant problem instance Q has been solved
							 | 
						|
								with an appropriate solver depending on the solution type previously
							 | 
						|
								passed to the routine glp_npp_load_prob (the parameter sol). Note that
							 | 
						|
								only optimal or integer feasible (for MIP) solution can be recovered,
							 | 
						|
								so the calling program should use the routine glp_status to make sure
							 | 
						|
								that this condition is met.
							 | 
						|
								------------------------------------------------------------------------
							 | 
						|
								@.@.7 glp_npp_obtain_sol - obtain solution to original problem
							 | 
						|
								
							 | 
						|
								SYNOPSIS
							 | 
						|
								
							 | 
						|
								void glp_npp_obtain_sol(glp_prep *prep, glp_prob *P);
							 | 
						|
								
							 | 
						|
								DESCRIPTION
							 | 
						|
								
							 | 
						|
								The routine glp_npp_obtain_sol copies the solution to the original
							 | 
						|
								problem instance previously recovered by the routine
							 | 
						|
								glp_npp_postorocess from the preprocessor workspace to the problem
							 | 
						|
								object P. The effect is the same as if the solution were computed by an
							 | 
						|
								appropriate solver.
							 | 
						|
								------------------------------------------------------------------------
							 | 
						|
								@.@.8 glp_npp_free_wksp - free the preprocessor workspace
							 | 
						|
								
							 | 
						|
								SYNOPSIS
							 | 
						|
								
							 | 
						|
								void glp_npp_free_wksp(glp_prep *prep);
							 | 
						|
								
							 | 
						|
								DESCRIPTION
							 | 
						|
								
							 | 
						|
								The routine glp_npp_free_wksp frees all the memory allocated to the
							 | 
						|
								preprocessor workspace.
							 | 
						|
								
							 | 
						|
								===EOF===
							 |