      A PRELIMINARY IMPLEMENTATION OF THE BRANCH-AND-CUT FRAMEWORK
                         FOR GLPK VERSION 3.2.1

            Andrew Makhorin <mao@mai2.rcnet.ru, mao@gnu.org>

                      (Draft Edition, August 2002)



CONTENTS
========

1. INTRODUCTION
   1.1. Workspace
   1.2. Implicit enumeration tree
   1.3. Current subproblem
   1.4. Branch-and-cut driver
   1.5. Application procedure
   1.6. Framework routines
2. BRANCH-AND-CUT DRIVER
   2.1. bcs_driver - branch-and-cut driver
   2.2. Event codes
3. FRAMEWORK ROUTINES
   3.1. bcs_get_event - determine current event code
   3.2. bcs_add_var - add variable to the branch-and-cut workspace
   3.3. bcs_add_con - add constraint to the branch-and-cut workspace
   3.4. bcs_set_var_appl - store application information to variable
   3.5. bcs_set_con_appl - store application information to constraint
   3.6. bcs_get_var_appl - retrieve application information from
                           variable
   3.7. bcs_get_con_appl - retrieve application information from
                           constraint
   3.8. bcs_get_next_var - get pointer to the next variable
   3.9. bcs_get_next_con - get pointer to the next constraint
   3.10. bcs_get_num_rows - determine number of rows
   3.11. bcs_get_num_cols - determine number of columns
   3.12. bcs_get_ith_con - determine pointer to i-th constraint
   3.13. bcs_get_jth_var - determine pointer to j-th variable
   3.14. bcs_get_var_info - obtain solution information for variable
   3.15. bcs_get_con_info - obtain solution information for constraint
   3.16. bcs_which_var - determine which variable is meant
   3.17. bcs_which_con - determine which constraint is meant
   3.18. bcs_get_lp_object - get pointer to internal LP object
Appendix. AN EXAMPLE: TSP SOLVER



This document is a supplement to GLPK Reference Manual. It describes
a preliminary implementation of the branch-and-cut framework for GLPK
version 3.2.1.

This document is not intended to be used as a tutorial. It is assumed
that the reader has basic knowledges in the theory of linear and integer
programming, polyhedral analysis, and combinatorial optimization.



1. INTRODUCTION
===============

The GLPK branch-and-cut framework is a set of data structures and
routines included in the GLPK package and intended for implementing
branch-and-cut methods for solving mixed-integer and combinatorial
optimization problems.

The branch-and-cut framework consists of the following components:

* workspace;

* implicit enumeration tree;

* current subproblem;

* branch-and-cut driver;

* application procedure;

* framework routines.



1.1. Workspace
--------------

The workspace contains variables and constraints, which are components
of a particular optimization problem.

In the current version of the framework neither generic nor application
specific seperation algorithms are implemented, so all variables and
constraints are generated by the application only.

Variables can be entered into the workspace only during initialization
phase (i.e. generation of variables for subproblems is not allowed).
All variables are considered as globally valid and inherited by all
subproblems derived from the root subproblem. All variables are kept in
the workspace until the problem has been completely solved.

Unlike variables constraints can be entered into the workspace during
initialization phase, in which case they are considered as globally
valid and inherited by all subproblems derived from the root subproblem,
as well as on constraints or cutting planes generation phases, in which
case they are considered as locally valid and inherited by subproblems
derived from the current subproblem. Globally valid constraints are kept
in the workspace until the problem has been completely solved, and
locally valid constraints are automatically removed from the workspace
once the subproblem, for which they were generated, has been pruned.
(However, actually there is no difference between these cases in the
current implementation.) Should note that in the current implementation
it is impossible to generate globally valid constraints for subproblems
(except the root subproblem).

Variables and constraints have the following attributes:

* pointer;

* symbolic name (1 to 255 arbitrary graphic characters);

* continuous or integer (for variables only);

* static or dynamic (for variables only);

* type (free, lower bound, upper bound, double bound, fixed);

* lower and upper bounds;

* objective coefficient (for variables only);

* constraint coefficients;

* application extension.

Pointers are intended for referencing variables and constraints. Being
created and brought into the workspace each variable and each constraint
is uniquely identified by its pointer, which is assigned by the creation
routine. These pointers should be used in all subsequent operations on
the corresponding objects.

Symbolic names are intended for informational purposes. They cannot be
used for referencing variables and constraints.

Each variable can be stated as continuous or integer. These attributes
have their usual meaning.

If a variable is stated as static, it is included in the root subproblem
and inherited by all subproblems derived from the root subproblem. If
a variable is stated as dynamic, it is included in a subproblem only if
it is required by its reduced cost. Being included in some subproblem
a dynamic variable is kept there until this subproblem has been pruned
and inherited by all subproblems derived from this subproblem.

Type and bounds of variables and constraints have the same meaning as
type and bounds of rows and columns in the LP problem object (see the
GLPK Reference Manual). Note that type and bounds of some variables can
be locally changed for particular subproblems.

Objective coefficient of a variable has its usual meaning.

Constraint coefficients of a variable is a set of coefficients at this
variable in all (including all locally valid) constraints presented in
the workspace. Constraint coefficients of a constraint is a set of
coefficients at all variables included in the constraint. Note that
constraint coefficients are stored in the workspace using sparse format,
so zero coefficients are never stored.

Application extension includes two special values for each variable and
each constraint: discriminant, an integer value, which allows the
application to distinguish between variables or constraints of different
sorts, and a pointer to some extended information, which the application
may assign to a variable or constraint.



1.2. Implicit enumeration tree
------------------------------

The implicit enumeration tree (sometimes called the search tree or the
branch-and-bound tree) is a k-nary tree (in the current implementation
it is a binary tree), where each node corresponds to some (pure) LP
problem (LP relaxation) called node problem or subproblem in the sequel.

All node problems in the tree are based on the same set of variables
and constraints presented in the workspace. A particular node problem is
defined by some subset of these variables and constraints.

The implicit enumeration tree is maintained by the branch-and-cut
driver, so the application needn't to explicitly deal with this object.



1.3. Current subproblem
-----------------------

Current subproblem is a node problem, which is currently being solved.

The application may need to access the current subproblem, for example,
to obtain values of variables for the current basic solution in order
to generate constraints or cutting planes, or to save the current
solution, or to know which variables and constraints are presented in
the current subproblem and which are not.

The branch-and-cut framework includes some routines, which can be used
by the application to deal with the current subproblem. Besides, the
current subproblem is available as the LPX object (for details see GLPK
Reference Manual), so the application can obtain all information from
the LPX object by using GLPK API routines. However, in the latter case
the application cannot directly modify the LPX object.



1.4. Branch-and-cut driver
--------------------------

Branch-and-cut driver is a principal component of the framework, which
manages the process of solving the optimization problem.



1.5. Application procedure
--------------------------

Application procedure is an event-driven procedure, which is called by
the branch-and-cut driver at certain points of the optimization process
in order to perform application specific actions (such as generation of
variables and constraints, etc.)

The current event, due to which the application procedure is called by
the branch-and-cut driver, is identified by its code. For example, the
event code BCS_V_GENCUT means that a basic solution of the current LP
relaxation is integer infeasible, so the application procedure can
generate some generic or application specific cutting planes to cut off
the integer infeasible point from the polytope. Another example is the
event code BCS_V_BINGO, which means that a basic solution of the current
subproblem being integer feasible is better than the best known one, so
the application procedure can obtain this solution from the internal LP
problem object for further processing.

Note that the application procedure is not a part of the branch-and-cut
framework. It needs to be separately programmed by the user.



1.6. Framework routines
-----------------------

Framework routines are a part of the branch-and-cut framework. They are
intended for using in the application procedure to perform all necessary
actions. Detailed description of these routines is given below.



2. BRANCH-AND-CUT DRIVER
========================

2.1. bcs_driver - branch-and-cut driver
---------------------------------------

*Synopsis*

#include "glpk.h"
int bcs_driver(char *name, int dir,
      void *info, void (*appl)(void *info, BCS *bcs));

*Description*

The routine bcs_driver is a branch-and-cut driver, which manages the
process of solving the optimization problem.

The character string name is a symbolic name (1 to 255 arbitrary graphic
characters) assigned to the problem. If this parameter NULL, no name is
assigned.

The parameter dir specifies the optimization direction:

LPX_MIN - the objective function should be minimized;
LPX_MAX - the objective function should be maximized.

The parameter info is a transit pointer passed to the application
procedure.

The parameter appl should specify an entry point to the event-driven
application procedure supplied by the user. This procedure is called by
the branch-and-cut driver at certain points of the optimization process
in order to perform application specific actions (variables and
constraints generation, etc.). The first parameter passed to this
procedure is the transit pointer passed to the branch-and-cut driver
routine. The second parameter passed to this procedure is a pointer to
the branch-and-cut workspace. It should be used by the application
procedure on subsequent calls to the framework routines.

*Returns*

In the current implementation the routine bcs_driver always returns
zero code.



2.2. Event codes
----------------

This subsection contains detailed description of all events (i.e.
certain points of the optimization process), when the branch-and-cut
driver calls the application procedure.

Each event has its own distinct code, which is an integer number
suitable for using in the switch statement. All event codes have the
corresponding symbolic names defined in the header 'glpk.h'. The
application procedure can obtain the current event code using the
routine bcs_get_event.

Note that in the future implementations of the branch-and-cut framework
new events may be introduced.

BCS_V_INIT (initializing)

   The event BCS_V_INIT is raised only once before any other events and
   corresponds to the initialization phase.

   On processing this event the application procedure should bring in
   the workspace all variables using the routine bcs_add_var. Some of
   these variables (with the attribute BCS_STATIC) are included in the
   root subproblem, others (with the attribute BCS_DYNAMIC) are kept in
   the workspace and can be included in derived subproblems. Besides,
   the application procedure should bring in the workspace constraints,
   which are included in the root subproblem, using the routine
   bcs_add_con.

BCS_V_GENCON (constraints generation required)

   The event BCS_V_GENCON is raised every time after the current
   subproblem has been solved and means that additional constraints
   should be generated for the current subproblem.

   On processing this event the application procedure should analyzes
   a basic solution of the current subproblem and bring in the
   workspace additional application specific constraints, which are
   essential for the current subproblem, using the routine bcs_add_con.

   Arbitrary number of constraints can be generated on processing this
   event. Note that all generated constraints are not immediately
   included in the current subproblem. Instead they are accumulated in
   the workspace and included in the subproblem after the application
   procedure has returned to the branch-and-cut driver.

   If at least one constraint has been generated, the branch-and-cut
   driver repeats the loop to re-optimize the current subproblem, so the
   event BCS_V_GENCON can be raised once again for the same subproblem.
   If no constraint has been generated, the optimization process is
   continued.

BCS_V_GENCUT (cutting planes generation required)

   The event BCS_V_GENCUT is raised every time after the current
   subproblem has been solved and means that cutting planes should be
   generated for the current subproblem, because its basic solution is
   integer infeasible (i.e. current values of some integer variables
   are fractional).

   On processing this event the application procedure should analyzes
   the basic solution of the current subproblem and bring in the
   workspace additional generic or application specific cutting planes,
   which cuts off the fractional point from the polytope.

   Arbitrary number of constraints can be generated on processing this
   event. Note that all generated constraints are not immediately
   included in the current subproblem. Instead they are accumulated in
   the workspace and included in the subproblem after the application
   procedure has returned to the branch-and-cut driver.

   If at least one constraint has been generated, the branch-and-cut
   driver repeats the loop to re-optimize the current subproblem, so the
   event BCS_V_GENCUT can be raised once again for the same subproblem.
   If no constraint has been generated and the solution is still integer
   infeasible, the branch-and-cut driver performs branching.

BCS_V_BINGO (better solution found)

   The event BCS_V_BINGO is raised every time after the current
   subproblem has been solved and means that a basic solution of the
   current subproblem being integer feasible is better than the best
   known one.

   On processing this event the application procedure can obtain the
   basic solution of the current subproblem.

BCS_V_DELVAR (some variable is being deleted)

   The event BCS_V_DELVAR means that some variable is being removed
   from the branch-and-cut workspace.

   On processing this event the application procedure can obtain a
   pointer to the variable, which is being removed, using the routine
   bcs_which_var in order to free an application extension assigned to
   this variable.

BCS_V_DELCON (some constraint is being deleted)

   The event BCS_V_DELCON means that some constraint is being removed
   from the branch-and-cut workspace.

   On processing this event the application procedure can obtain a
   pointer to the constraint, which is being removed, using the routine
   bcs_which_con in order to free an application extension assigned to
   this constraint.

BCS_V_TERM (terminating)

   The event BCS_V_TERM is the final event, which corresponds to the
   termination phase. This event is raised only once immediately before
   the branch-and-cut driver returns to the calling program.



3. FRAMEWORK ROUTINES
=====================

3.1. bcs_get_event - determine current event code
-------------------------------------------------

*Synopsis*

#include "glpk.h"
int bcs_get_event(BCS *bcs);

*Returns*

The routine bcs_get_event returns a code of the current event, due to
which the application procedure is being called.

The parameter bcs is the second parameter passed to the application
procedure. It specifies the branch-and-cut workspace.



3.2. bcs_add_var - add variable to the branch-and-cut workspace
---------------------------------------------------------------

*Synopsis*

#include "glpk.h"
BCSVAR *bcs_add_var(BCS *bcs, char *name, int attr, int typx,
      double lb, double ub, double coef, int len, BCSCON *con[],
      double val[]);

*Description*

The routine bcs_add_var should be used by the application procedure to
add a new variable to the branch-and-cut workspace.

NOTE that in the current version of the branch-and-cut framework
variables can be added to the workspace only during initialization phase
(BCS_V_INIT). All variables are considered as globally valid and
inherited by all subproblems derived from the root subproblem.

The parameter bcs is the second parameter passed to the application
procedure. It specifies the branch-and-cut workspace.

The parameter name is a symbolic name (1 to 255 graphic characters)
assigned to the variable. If this parameter is NULL, no symbolic name is
assigned.

The parameter attr specifies attributes of the variable:

BCS_CONTIN     continuous variable (default);

BCS_INTEGER    integer variable;

BCS_STATIC     static variable (default). Variable marked as static is
               always included in every subproblem;

BCS_DYNAMIC    dynamic variable (should have zero lower bound). Variable
               marked as dynamic is included in subproblem only if it is
               required by the reduced cost.

The parameters typx, lb, and ub specify, respectively, type, lower
bound, and upper bound of the variable:

    Type          Bounds            Note
   -------------------------------------------
   LPX_FR   -inf <  x <  +inf   free variable
   LPX_LO     lb <= x <  +inf   lower bound
   LPX_UP   -inf <  x <=  ub    upper bound
   LPX_DB     lb <= x <=  ub    double bound
   LPX_FX           x  =  lb    fixed variable

The parameter coef specifies a coefficient of the objective function at
the variable.

The parameters len, con, and val specify constraint coefficients for the
variable. Pointers to constraints should be placed in locations con[1],
..., con[len], and numerical values of the corresponding constraint
coefficients should be placed in locations val[1], ..., val[len]. Zero
coefficients and multiplets (i.e. coefficients that refer to the same
constraint) are not allowed. If the parameter len is zero, the
parameters con and val are ignored.

*Returns*

The routine returns a pointer to the added variable, which should be
used in subsequent operations on this variable.



3.3. bcs_add_con - add constraint to the branch-and-cut workspace
-----------------------------------------------------------------

*Synopsis*

#include "glpk.h"
BCSCON *bcs_add_con(BCS *bcs, char *name, int attr, int typx,
   double lb, double ub, int len, BCSVAR *var[], double val[]);

*Description*

The routine bcs_add_con should be used by the application procedure to
add a new constraint to the branch-and-cut workspace.

NOTE that in the current version of the branch-and-cut framework
constraints can be added to the workspace only during initialization
phase (BCS_V_INIT) or constraints generation phase (BCS_V_GENCON) or
cutting planes generation phase (BCS_V_GENCUT). In the first case the
constraints are considered as globally valid and inherited by all
subproblems derived from the root subproblem. In the second and third
cases constraints are considered as locally valid; they are added to the
current subproblem and inherited by subproblems derived from the current
subproblem. Actually there is no difference between these cases in the
current implementation.

The parameter bcs is the second parameter passed to the application
procedure. It specifies the branch-and-cut workspace.

The parameter name is a symbolic name (1 to 255 graphic characters)
assigned to the constraint. If this parameter is NULL, no symbolic name
is assigned.

The parameter attr specifies attributes of the constraint. It should be
zero in the current implementation of the branch-and-cut framework.

The parameters typx, lb, and ub specify, respectively, type, lower
bound, and upper bound of the constraint (linear form):

    Type          Bounds            Note
   -------------------------------------------
   LPX_FR   -inf <  x <  +inf   free variable
   LPX_LO     lb <= x <  +inf   lower bound
   LPX_UP   -inf <  x <=  ub    upper bound
   LPX_DB     lb <= x <=  ub    double bound
   LPX_FX           x  =  lb    fixed variable

where x is an auxiliary variable associated with the constraint.

The parameters len, var, and val should specify coefficients for the
constraint. Pointers to variables should be placed in locations var[1],
..., var[len], and numerical values of the corresponding coefficients
should be placed in locations val[1], ..., val[len]. Zero coefficients
and multiplets (i.e. coefficients that refer to the same constraint) are
not allowed. If the parameter len is zero, the parameters var and val
are ignored.

*Returns*

The routine returns a pointer to the added constraint, which should be
used in subsequent operations on this constraint.



3.4. bcs_set_var_appl - store application information to variable
-----------------------------------------------------------------

*Synopsis*

#include "glpk.h"
void bcs_set_var_appl(BCS *bcs, BCSVAR *var, int disc, void *link);

*Description*

The routine bcs_set_var_appl stores application specific information to
the specified variable.

The parameter disc is a discriminant, which allows the application to
distinguish between variables of different sorts.

The parameter link is a pointer to some extended information, which the
application may assign to the variable.



3.5. bcs_set_con_appl - store application information to constraint
-------------------------------------------------------------------

*Synopsis*

#include "glpk.h"
void bcs_set_con_appl(BCS *bcs, BCSCON *con, int disc, void *link);

*Description*

The routine bcs_set_con_appl stores application specific information to
the specified constraint.

The parameter disc is a discriminant, which allows the application to
distinguish between constraints of different sorts.

The parameter link is a pointer to some extended information, which the
application may assign to the constraint.



3.6. bcs_get_var_appl - retrieve application information from variable
----------------------------------------------------------------------

*Synopsis*

#include "glpk.h"
void bcs_get_var_appl(BCS *bcs, BCSVAR *var, int *disc, void **link);

*Description*

The routine bcs_get_var_appl retrieves application specific information
(previously stored by the routine bcs_set_var_appl) from the specified
variable.

A discriminant value and a pointer to an extended information are stored
to the locations, which the parameters disc and link point to,
respectively. If some of the parameters disc or link is NULL, the
corresponding value is not stored.



3.7. bcs_get_con_appl - retrieve application information from constraint
------------------------------------------------------------------------

*Synopsis*

#include "glpk.h"
void bcs_get_con_appl(BCS *bcs, BCSCON *con, int *disc, void **link);

*Description*

The routine bcs_get_con_appl retrieves application specific information
(previously stored by the routine bcs_set_con_appl) from the specified
constraint.

A discriminant value and a pointer to an extended information are stored
to the locations, which the parameters disc and link point to,
respectively. If some of the parameters disc or link is NULL, the
corresponding value is not stored.



3.8. bcs_get_next_var - get pointer to the next variable
--------------------------------------------------------

*Synopsis*

#include "glpk.h"
BCSVAR *bcs_get_next_var(BCS *bcs, BCSVAR *var);

*Returns*

If the parameter var is NULL, the routine returns a pointer to the first
variable, which was added into the workspace before any other variables,
or NULL, if there are no variables in the workspace. Otherwise the
parameter var should specify some variable, in which case the routine
returns a pointer to the next variable, which was added into the
workspace later than the specified one, or NULL, if there is no next
variable in the workspace.



3.9. bcs_get_next_con - get pointer to the next constraint
----------------------------------------------------------

*Synopsis*

#include "glpk.h"
BCSCON *bcs_get_next_con(BCS *bcs, BCSCON *con);

*Returns*

If the parameter con is NULL, the routine returns a pointer to the first
constraint, which was added into the workspace before any other
constraints, or NULL, if there are no constraints in the workspace.
Otherwise the parameter con should specify some constraint, in which
case the routine returns a pointer to the next constraint, which was
added into the workspace later than the specified one, or NULL, if there
is no next constraint in the workspace.



3.10. bcs_get_num_rows - determine number of rows
-------------------------------------------------

*Synopsis*

#include "glpk.h"
int bcs_get_num_rows(BCS *bcs);

*Returns*

The routine bcs_get_num_rows returns number of rows in the current
subproblem, which should exist.



3.11. bcs_get_num_cols - determine number of columns
----------------------------------------------------

*Synopsis*

#include "glpk.h"
int bcs_get_num_cols(BCS *bcs);

*Returns*

The routine bcs_get_num_cols returns number of columns in the current
subproblem, which should exist.



3.12. bcs_get_ith_con - determine pointer to i-th constraint
------------------------------------------------------------

*Synopsis*

#include "glpk.h"
BCSCON *bcs_get_ith_con(BCS *bcs, int i);

*Returns*

The routine bcs_get_ith_con returns a pointer to a constraint, which
corresponds to the i-th row in the current subproblem.

*Note*

Due to dynamic nature of subproblems the correspondence between
constraints and rows may be changed in the next reincarnation of the
current subproblem. In particular, some constraints may enter and some
may leave the current subproblem.



3.13. bcs_get_jth_var - determine pointer to j-th variable
----------------------------------------------------------

*Synopsis*

#include "glpk.h"
BCSVAR *bcs_get_jth_var(BCS *bcs, int j);

*Returns*

The routine bcs_get_jth_var returns a pointer to a variable, which
corresponds to the j-th column in the current subproblem.

*Note*

Due to dynamic nature of subproblems the correspondence between
variables and columns may be changed in the next reincarnation of the
current subproblem. In particular, some variables may enter and some may
leave the current subproblem.



3.14. bcs_get_var_info - obtain solution information for variable
-----------------------------------------------------------------

*Synopsis*

#include "glpk.h"
void bcs_get_var_info(BCS *bcs, BCSVAR *var, int *tagx, double *vx,
      double *dx);

*Description*

The routine bcs_get_var_info stores status, primal and dual values,
which the specified variable has in a basic solution of the current
subproblem, to locations, which the parameters tagx, vx, and dx point
to, respectively.

The status code has the following meaning:

LPX_BS - basic variable;
LPX_NL - non-basic variable on its lower bound;
LPX_NU - non-basic variable on its upper bound;
LPX_NF - non-basic free (unbounded) variable;
LPX_NS - non-basic fixed variable.

If some of pointers tagx, vx, or dx is NULL, the corresponding value is
not stored.



3.15. bcs_get_con_info - obtain solution information for constraint
-------------------------------------------------------------------

*Synopsis*

#include "glpk.h"
void bcs_get_con_info(BCS *bcs, BCSCON *con, int *tagx, double *vx,
   double *dx);

*Description*

The routine bcs_get_con_info stores status, primal and dual values,
which the specified constraint (more exactly, an auxiliary variable for
the corresponding constraint) has in a basic solution of the current
subproblem, to locations, which the parameters tagx, vx, and dx point
to, respectively.

The status code has the following meaning:

LPX_BS - non-active constraint;
LPX_NL - active inequality constraint on its lower bound;
LPX_NU - active inequiality constraint on its upper bound;
LPX_NF - free linear form, whose auxiliary variable is non-basic;
LPX_NS - active equiality constraint.

If some of pointers tagx, vx, or dx is NULL, the corresponding value is
not stored.



3.16. bcs_which_var - determine which variable is meant
-------------------------------------------------------

*Synopsis*

#include "glpk.h"
BCSVAR *bcs_which_var(BCS *bcs);

*Returns*

The routine bcs_which_var returns a pointer to a variable, if the
current event is related to this variable.



3.17. bcs_which_con - determine which constraint is meant
---------------------------------------------------------

*Synopsis*

#include "glpk.h"
BCSCON *bcs_which_con(BCS *bcs);

*Returns*

The routine bcs_which_con returns a pointer to a constraint, if the
current event is related to this constraint.



3.18. bcs_get_lp_object - get pointer to internal LP object
-----------------------------------------------------------

*Synopsis*

#include "glpk.h"
LPX *bcs_get_lp_object(BCS *bcs);

*Returns*

The routine bcs_get_lp_object returns a pointer to the internal LP
object for the specified branch-and-cut workspace.

The internal LP object is a representation of the linear programming
problem, which corresponds to the current subproblem (LP relaxation).

The internal LP object *must not* be modified directly by using any API
routines with the prefix 'lpx'. All necessary modifications of the
current subproblem should be performed only by using the 'bcs' routines.
However, the 'lpx' API routines can be used for obtaining information
from this LP object.



Appendix. AN EXAMPLE: TSP SOLVER
================================

In order to illustrate how the GLPK branch-and-cut framework can be
used to solve a particular optimization problem there is an example,
the program TSPSOL. This program is intended for solving to optimality
the symmetric Traveling Salesman Problem (TSP), which is a classical
combinatorial optimization problem.

The complete source code of TSPSOL is included in the GLPK distribution
(see the file 'tspsol.c' in the subdirectory 'sample').

Should note that this program is only an illustrative example. It is
*not* a state-of-the-art code. Therefore only TSP instances of small
size (not more than 100 cities) are able to be solved using this code.

To run this program the following command line should be used:

   tspsol tsp-file

where tsp-file is the name of an input text file, which contains TSP
instance data.

Detailed description of the input format recognized by this program is
given in the report: Gerhard Reinelt, "TSPLIB 95". This report as well
as TSPLIB, a library of sample TSP instances (and other related
problems), are freely available for research purposes at the address
<http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/>.
See also the file 'sample.tsp' (included in the subdirectory 'sample').

The initial (root) subproblem includes variables from the initial tour
found by the greedy heuristic and degree constraints. However, all
variables are included in the branch-and-cut workspace, so they are not
generated during the search. For each subproblem additional subtour
elimination constraints are generated.

Variables have symbolic names like 'i-j', where i and j are numbers of
nodes, which are incident to the corresponding edge. If an edge belongs
to the initial tour, the corresponding variable name ends with the
asterisk. Degree constraints have symbolic names like 'Vi', where i is
number of the corresponding node. Subtour elimination constraints have
no symbolic names.

Every time when a basic solution of some subproblem is a valid tour,
whose length is better than the best known one, the program writes the
corresponding LP relaxation to the file 'MPS' using MPS format, and its
optimal solution to the file 'SOL' using plain text format.

------------------------------------------------------------------------

The GLPK package is a part of the GNU project, released under the aegis
of GNU.

Copyright (C) 2000, 2001, 2002 Andrew Makhorin,
              Department for Applied Informatics, Moscow Aviation
              Institute, Moscow, Russia. All rights reserved.

Free Software Foundation, Inc., 59 Temple Place -- Suite 330, Boston,
MA 02111, USA.

Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that the
entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions.
