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

@.@ 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===