# HG changeset patch
# User Minh Van Nguyen
# Date 1260580510 28800
# Node ID 63d8e7ebcef853e3ad181c252039d9cdf1a80145
# Parent 1245120e8f9755ada808b0618ad14abff5b8122f
trac 7652: linear programming; reviewer patch
diff r 1245120e8f97 r 63d8e7ebcef8 doc/en/constructions/linear_programming.rst
 a/doc/en/constructions/linear_programming.rst
+++ b/doc/en/constructions/linear_programming.rst
@@ 1,215 +1,223 @@
Linear Programming
==================
+
Basics

What is a Linear Program ?
""""""""""""""""""""""""""
+What is a linear program?
+"""""""""""""""""""""""""
A linear program consists of the following two pieces of information :
+A linear program consists of the following two pieces of information:
 * A linear function, called the objective, which is
 to be maximized or minimized (for example `2 x + y`)
 * Linear constraints on the variables (for example,
 `3 x + y \leq 2` and `2 x + 3 y \leq 8`)
+* A linear function, called the objective function, which is
+ to be maximized or minimized, e.g. `2 x + y`.
The solver will then try to find a solution to the system of
constraints such that the objective function is optimized, and
return the values of the variables.
+* Linear constraints on the variables, e.g. `3 x + y \leq 2` and
+ `2 x + 3 y \leq 8`.
+A linear program solver would then try to find a solution to the
+system of constraints such that the objective function is optimized, and
+return specific values for the variables.
+What is a mixed integer linear program?
+"""""""""""""""""""""""""""""""""""""""
What is a Mixed Integer Linear Program ?
+A mixed integer linear program is a linear program such that some
+variables are forced to take integer values instead of real
+values. This difference affects the time required to solve a
+particular linear program. Indeed, solving a linear program can be
+done in polynomial time while solving a general mixed integer linear
+program is usually `NP`complete, i.e. it can take exponential time,
+according to a widelyheld belief that `P \neq NP`.
+
+Why is linear programming so useful?
+""""""""""""""""""""""""""""""""""""
+
+Linear programming is very useful in many optimization and
+graphtheoretic problems because of its wide range of expression.
+A linear program can be written to solve a problem whose
+solution could be obtained within reasonable time using the wealth of
+heuristics already contained in linear program solvers. It is often
+difficult to theoretically determine the execution time of a linear
+program, though it could produce very interesting results in
+practice.
+
+For more information, consult the Wikipedia page dedicated to
+linear programming: http://en.wikipedia.org/wiki/Linear_programming
+
+
+How can I solve a linear program using Sage?
+
+
+Sage can solve linear programs or mixed integer linear programs
+through the class ``MixedIntegerLinearProgram`` defined in
+``sage.numerical.mip``. To illustrate how it can be used, we will try
+to solve the following problem:
+
+.. MATH::
+
+ \text{Maximize: } & 2 x_1 + x_2 \\
+ \text{Such that: } & 3 x_1 + 4 x_2 \leq 2.5 \\
+ & 0.5 \leq 1.2 x_1 + 0.5 x_2 \leq 4
+
+First, we need to discuss ``MIPVariable`` and how to read the optimal
+values when the solver has finished its job.
+
+Variables in ``MixedIntegerLinearProgram``
""""""""""""""""""""""""""""""""""""""""""
It is simply a Linear Program such that some variables are forced
to take integer values instead of real values. This difference becomes
very important when one learns that solving a Linear Program can be done
in polynomial time while solving a general Mixed Integer Linear Program
is `NP`Complete (= there is no polynomial algorithm to solve it,
according to a widelyspread belief that `P\neq NP`)
+A variable linked to an instance of ``MixedIntegerLinearProgram``
+behaves exactly as a dictionary would. It is declared as follows::
Why is Linear Programming so useful ?
""""""""""""""""""""""""""""""""""""""

Linear Programming is very useful in many Optimization and
GraphTheoretical problems because of its wide range of expression.
Most of the time, a natural Linear Program can be easily written
to solve a problem whose solution will be quickly computed thanks
to the wealth of heuristics already contained in Linear Program
Solvers. It is often hard to theoretically find out the execution
time of a Linear Program, though they give very interesting results
in practice.

For more information, you can consult the Wikipedia page dedicated to
Linear Programming : http://en.wikipedia.org/wiki/Linear_programming

How can I solve a linear program using Sage ?


Sage can solve Linear Programs or Mixed Integer Linear Programs through
the class ``MixedIntegerLinearProgram`` defined in ``sage.numerical.mip``. To illustrate how it can be
used, we will try to solve the following problem :

.. MATH::

 \mbox{Maximize : }&2 x_1 + x_2\\
 \mbox{Such that : }&3 x_1 + 4 x_2\leq 2.5\\
 &0.5\leq 1.2 x_1 + 0.5 x_2 \leq 4

First, we need a few informations about ``MIPVariable`` and
how to read the optimal values when the solver has finished its job.

Variables in ``MixedIntegerLinearProgram``
""""""""""""""""""""""""""""""""""""""""""""

A variable linked to an instance of ``MixedIntegerLinearProgram`` behaves exactly as
a dictionary would. It is declared the following way ::

 sage: p=MixedIntegerLinearProgram()
 sage: variable=p.new_variable()
+ sage: p = MixedIntegerLinearProgram()
+ sage: variable = p.new_variable()
The variable ``variable`` can contain as many keys as you
would like, each of them being formally `unique`. For example
the following constraint (where `P` denotes the pressure,
and `T` the temperature) :
+like, where each key must be unique. For example, the following
+constraint (where `P` denotes pressure and `T` temperature)
.. MATH::
 2 T_{\mbox{Madrid}} + 3 T_{\mbox{London}} 
 P_{\mbox{Seattle}} + \mbox{flow}_{3,5} +
 8 \mbox{cost}_{(1,3)} + x_3 < 5\\
... can be expressed in Sage (quite naturally, I hope !) this way ::
+ 2 T_{\text{Madrid}} + 3 T_{\text{London}}  P_{\text{Seattle}} + \text{flow}_{3, 5} + 8 \text{cost}_{(1, 3)} + x_3 < 5
 sage: p=MixedIntegerLinearProgram()
 sage: temperature=p.new_variable()
 sage: pressure=p.new_variable()
 sage: x=p.new_variable()
 sage: cost=p.new_variable()
 sage: flow=p.new_variable(dim=2)
 sage: p.add_constraint(2*temperature["Madrid"]+3*temperature["London"]pressure["Seattle"]+flow[3][5]+8*cost[(1,3)]+x[3],max=5)
+can be written as::
This example is just meant to show you the different possibilities
offered to you when you use the ``MixedIntegerLinearProgram`` class. You will not need
to declare so many variables in usual applications.
+ sage: p = MixedIntegerLinearProgram()
+ sage: temperature = p.new_variable()
+ sage: pressure = p.new_variable()
+ sage: x = p.new_variable()
+ sage: cost = p.new_variable()
+ sage: flow = p.new_variable(dim=2)
+ sage: p.add_constraint(2*temperature["Madrid"] + 3*temperature["London"]  pressure["Seattle"] + flow[3][5] + 8*cost[(1, 3)] + x[3], max=5)
Notice how the variable ``flow`` is defined : you can use any hashable
+This example shows different possibilities for using the
+``MixedIntegerLinearProgram`` class. You would not need to declare so
+many variables in some common applications of linear programming.
+
+Notice how the variable ``flow`` is defined: you can use any hashable
object as a key for a ``MIPVariable``, but if you think you need
more than one dimension, you need to explicitely say it when
calling ``MixedIntegerLinearProgram.new_variable()``
+more than one dimension, you need to explicitly specify it when
+calling ``MixedIntegerLinearProgram.new_variable()``.
For the user's convenience, however, there is a default variable
attached to a Linear Program : indeed, the previous implementation
means that each "variable" actually represents a property of
a set of objects (these objects are strings in the case of ``temperature``
or a pair in the case of ``cost``). In some cases, though it is useful to
define an absolute variable which will not be indexed on anything. This can
be done through the following notation ::
+For the user's convenience, there is a default variable
+attached to a linear program. The above code listing means that each
+``variable`` actually represents a property of a set of objects
+(these objects are strings in the case of ``temperature`` or a pair in
+the case of ``cost``). In some cases, it is useful to define an
+absolute variable which will not be indexed on anything. This can be
+done as follows::
sage: p = MixedIntegerLinearProgram()
sage: B = p.new_variable()
 sage: p.set_objective( p["first unique variable"] + B[2] + p[3] )
+ sage: p.set_objective(p["first unique variable"] + B[2] + p[3])
In this case, two of these "unique" variables are defined through
``p["first unique variable"]`` and ``p[3]``.

Let us solve this system !
""""""""""""""""""""""""""
Now that we know what are variables,
we are only several lines away from solving our system ::
+Let's solve this system
+"""""""""""""""""""""""
 sage: # First, we define our MixedIntegerLinearProgram object, setting maximization=True
 sage: p=MixedIntegerLinearProgram( maximization = True )
 sage: x=p.new_variable()
+Now that we know what variables are, we are only several steps away
+from solving our system::
+
+ sage: # First, we define our MixedIntegerLinearProgram object,
+ sage: # setting maximization=True.
+ sage: p = MixedIntegerLinearProgram(maximization=True)
+ sage: x = p.new_variable()
sage: # Definition of the objective function
 sage: p.set_objective( 2*x[1]+x[2] )
+ sage: p.set_objective(2*x[1] + x[2])
sage: # Next, the two constraints
 sage: p.add_constraint( 3*x[1]+4*x[2], max=2.5 )
 sage: p.add_constraint( 1.5*x[1]+0.5*x[2], max=4,min=0.5 )
 sage: p.solve() # optional  requires Glpk or COINOR/CBC
+ sage: p.add_constraint(3*x[1] + 4*x[2], max=2.5)
+ sage: p.add_constraint(1.5*x[1]+0.5*x[2], max=4, min=0.5)
+ sage: p.solve() # optional  requires GLPK or COINOR/CBC
1.6666666666666667
 sage: x_sol=p.get_values(x)
 sage: print x_sol
+ sage: x_sol = p.get_values(x) # optional  requires GLPK or COINOR/CBC
+ sage: print x_sol # optional  requires GLPK or COINOR/CBC
{1: 0.83333333333333337, 2: 0.0}
+The value returned by ``MixedIntegerLinearProgram.solve()`` is the
+optimal value of the objective function. To read the values taken by
+the variables, one needs to call the method
+``MixedIntegerLinearProgram.get_values()`` which can return multiple
+values at the same time if needed (type
+``MixedIntegerLinearProgram.get_values?`` for more information
+on this function).
The value returned by ``MixedIntegerLinearProgram.solve()`` is the optimal value of
the objective function. To read the values taken by the variables
one needs to call the method ``MixedIntegerLinearProgram.get_values`` which can return
multiple values at the same time if needed (type
``sage: MixedIntegerLinearProgram.get_values?`` for more information on this function)
Some famous examples

+
Vertex Cover in a graph
""""""""""""""""""""""""
+Vertex cover in a graph
+"""""""""""""""""""""""
In the Vertex Cover problem, we are given a graph `G` and we want to find
a subset `S` of its vertices of minimal cardinality such that each edge
`e` is incident to at least one vertex of `S`. In order to achieve it, we
define a binary variable `b_v` for each vertex `v`.
+Let `G = (V, E)` be a graph with vertex set `V` and edge set `E`. In
+the vertex cover problem, we are given `G` and we want to find
+a subset `S \subseteq V` of minimal cardinality such that each
+edge `e` is incident to at least one vertex in `S`. In order to
+achieve this, we define a binary variable `b_v` for each vertex
+`v`. The vertex cover problem can be expressed as the following linear
+program:
.. MATH::
+.. MATH::
 \mbox{Maximize : }& \sum_{v\in G.vertices()} b_v\\
 \mbox{Such that : }&\forall (u,v)\in G.edges(), b_u + b_v \geq 1\\
 &\forall v,b_v \mbox{ is a binary variable}
+ \text{Maximize: } & \sum_{v \in V} b_v \\
+ \text{Such that: } & \forall (u, v) \in E, b_u + b_v \geq 1 \\
+ & \forall v, b_v \text{ is a binary variable}
In the linear program, the syntax is exactly the same ::
+In the linear program, the syntax is exactly the same::
 sage: g=graphs.PetersenGraph()
 sage: p=MixedIntegerLinearProgram(maximization=False)
 sage: b=p.new_variable()
 sage: for (u,v) in g.edges(labels=None):
 ... p.add_constraint(b[u]+b[v],min=1)
+ sage: g = graphs.PetersenGraph()
+ sage: p = MixedIntegerLinearProgram(maximization=False)
+ sage: b = p.new_variable()
+ sage: for u, v in g.edges(labels=None):
+ ... p.add_constraint(b[u] + b[v], min=1)
sage: p.set_binary(b)

And you but have to type ``p.solve()`` to see the result !
Maximum matching in a Graph
""""""""""""""""""""""""""""
+And you need to type ``p.solve()`` to see the result.
In the maximum matching problem, we are given a graph `G`, and we are
looking for a set of edges `M` of maximum cardinality such
that no two edges from `M` are adjacent :
+Maximum matching in a graph
+"""""""""""""""""""""""""""
.. MATH::
+In the maximum matching problem, we are given a graph `G = (V, E)`
+and we want a set of edges `M \subseteq E` of maximum cardinality such
+that no two edges from `M` are adjacent:
 \mbox{Maximize : }& \sum_{e\in G.edges()} b_e\\
 \mbox{Such that : }&\forall v\in G.vertices(), \sum_{(v,w)\in G}b_{uv} \leq 1\\
 &\forall e\in G.edges(),b_e \mbox{ is a binary variable}
+.. MATH::
Here is how this is solved through Sage on a Petersen Graph ::
+ \text{Maximize: } & \sum_{e \in E} b_e \\
+ \text{Such that: } & \forall v \in V, \sum_{(v,u) \in E} b_{vu} \leq 1 \\
+ & \forall e \in E, b_e \text{ is a binary variable}
 sage: g=graphs.PetersenGraph()
 sage: p=MixedIntegerLinearProgram()
 sage: b=p.new_variable(dim=2)
+Here, we use Sage to solve the maximum matching problem for the case
+of the Petersen graph::
+
+ sage: g = graphs.PetersenGraph()
+ sage: p = MixedIntegerLinearProgram()
+ sage: b = p.new_variable(dim=2)
sage: for u in g.vertices():
 ... p.add_constraint(sum([b[u][v] for v in g.neighbors(u)]),max=1)
 sage: for (u,v) in g.edges(labels=None):
 ... p.add_constraint(b[u][v]+b[v][u],min=1,max=1)
+ ... p.add_constraint(sum([b[u][v] for v in g.neighbors(u)]), max=1)
+ sage: for u, v in g.edges(labels=None):
+ ... p.add_constraint(b[u][v] + b[v][u], min=1, max=1)
And the next step is ``p.solve()`` !
+And the next step is ``p.solve()``.
Solvers

Sage solves linear programs by calling specific libraries. Two are available
for the moment :
+Sage solves linear programs by calling specific libraries. The
+following libraries are currently supported as optional packages:
 * `GLPK `_ : A Linear Program solver
 from `GNU `_
 * `CBC `_ : Mixed
 Integer Linear Program solver from
 `COINOR `_
+* `GLPK `_: A linear program solver
+ from `GNU `_
To install them if they are not available on your installation of Sage, type ::
+* `CBC `_: Mixed integer
+ linear program solver from `COINOR `_
 sage: # To install GLPK
 sage: install_package('glpk') # not tested
 sage: # To install CoinOR Branch and Cut (CBC)
 sage: install_package('cbc') # not tested
+Each of these packages can be installed as follows::
+
+ sage: # To install GLPK
+ sage: install_package("glpk") # not tested
+ sage: # To install COINOR Branch and Cut (CBC)
+ sage: install_package("cbc") # not tested