When faced with a complex problem to solve, the first thing we do is we take it apart and try to get a feel for the underlying structure. With a little practice and a little luck, insights into the structure of the problem enable us to apply a well known algorithmic technique to it and come out on the other end sailing smoothly.
So it’s important that our toolbox of problem solving skills is well rounded, and we are equipped with diverse knowledge about how to handle a problem that looks like it fits a pattern. This blog discusses a technique called linear programming that solves optimization problems and is nothing short of spectacular.
An optimization problem is one where something is being minimized or maximized. Here are some examples:
These examples are underspecified in that the constraints that apply to the problem aren’t clearly stated. In real-life scenarios, optimization problems can have literally thousands of constraints.
Many optimization problems can be expressed precisely and cleanly as a mathematical model called a linear program, or LP for short.
Note: Once a problem is formulated as an LP, it can be solved using one of the many well-known algorithms designed to solve linear programs.
The quantity being minimized or maximized is written out as a math function called the linear objective function.
Linear objective function: A linear objective function is a linear function with some variables. Suppose and are two unknown quantities. Here’s an example of a linear objective function with the unknowns and :
The qualifier ‘linear’ means the power of each variable is one.
Linear constraints: Each problem constraint is written out, typically, as a linear inequality or equality. For example,
A linear program expresses an optimization problem in terms of a linear objective function that needs to be maximized or minimized subject to linear constraints.
Let’s look at a short example to understand how to represent a problem mathematically as a linear program.
Suppose a small business manufactures two liquid chemicals and . Also, suppose the following facts:
The goal is to maximize the company’s profit.
Let’s say, we use two variables and so that
The objective function for the problem is . Is it apparent why?
The following two constraints apply to this problem. Is it apparent why?
Is there any other information in the problem statement that can be expressed as a linear constraint?
Putting together our answers to the question above, we can express this problem concisely in the following form. This is an example of a linear program:
The above linear program would be read as “Maximize subject to the constraints.” In other words, maximize the profit subject to the given constraints.
Our goal then is to find values of and for which the value of the objective function is maximized and all problem constraints are satisfied.
Each of the three constraints is satisfied for many values of and . These are called the solutions to the constraint. For example, the values and constitute a solution to all three constraints because they’re both non-negative and their sum is at most .
When working with two or three variables, it’s helpful to get a geometric view of a linear program. The solutions to each of the above constraints corresponds to a half-plane, as shown by the shaded areas below against each constraint. A half-plane, as the name suggests, includes the points on a line and the points that fall to one of its sides.
The set of values taken by variables that satisfy all the constraints of a linear program is called a feasible solution to the linear program.
Geometrically, the feasible solution to the given linear program corresponds to the following shaded polygon resulting from the intersection of the three half-planes:
Now a theorem gives us this important insight:
Given a feasible region of a linear program, there’s a corner of the feasible region where the objective function of the linear program is maximized (or minimized).
Take a look at the dotted graph of the objective function as it takes different values for points in the feasible region, taking its maximum value at the corner of the feasible region.
The value taken by an objective function on a particular solution is called an objective value.
In a short example, such as this one, it’s easy to find the solution algebraically, or by taking the geometric view and looking for a corner of the feasible region where the objective value is optimized. But in reality, a linear program can have many variables and constraints. The geometric view in two or three dimensions is helpful for building our intuition, but we need good tools to solve bigger problems.
Let’s see what a linear program in its standard form would look like.
A linear program in unknowns, say , is expressed in the standard form with these characteristics:
It is written as a maximization of a linear objective function in variables of the form
where are constants.
It has linear constraints of the type so that the constraint looks like
where , are all constants.
It’s also subject to non-negativity constraints of the kind , for each variable .
So the general form is precisely the following:
This is written out more compactly in the matrix form as:
where
So, the dot product of vectors and gets us the objective function. Similarly, multiplying the first row of matrix with the column vector gets us the first constraint. And so on.
Note: The standard form of a linear program defined here also applies to minimization problems.
There is an uncomplicated systematic way of converting an arbitrary linear program to its standard form. Here are some hints for the readers who are interested:
Depending on the constraints, the feasible region may also be unbounded (not closed off by boundaries on all sides.) For instance, if the only constraints in a linear program are and , then the feasible region is unbounded. In a case like that, an objective value can continue to increase in one direction forever, and the optimum value simply does not exist.
A linear program may also happen to have constraints that are not mutually satisfied. For instance, there’s no way to satisfy both of the constraints and . A linear program such as this with no solution is said to be infeasible.
Note: With variables, solutions satisfying each constraint forms a half-space (a generalization of a half-plane) in dimensions. And the feasible region is a
polytope, which is a generalization of a polygon in dimensions. convex A region is convex if the line segment between any two points in the region is contained within that region.
Once we have modeled an optimization problem as a linear program, we can solve it.
There are many algorithms for solving a linear program. The simplex algorithm and the interior-point algorithms are widely used in practice. (There are others of a greater theoretical interest.)
The simplex algorithm works by iteratively going along the edges of the feasible region toward a corner that yields an improved objective value. The interior-point method, on the other hand, moves through the interior of the feasible region.
Implementations of well-known linear programming algorithms and their variations are available for free as well as in the form of paid-use libraries called solvers.
A really important idea in linear programming is that every LP (the primal LP) can be used for obtaining a different LP called its dual. The dual can be found in a systematic way.
Here’s a standard way these two are expressed. Note that in the dual form below is the transpose of .
Primal
Dual
Interestingly, the dual of a dual is the primal again.
So for a pair of primal and dual LPs, we are looking at two closely related problems — a maximization and a minimization. The primal-dual relationship is a rich source of contributions towards developments in algorithmics where one problem in the primal-dual pair is solved using an algorithm for the other.
Two core insights into the primal-dual relationship come from the weak-duality and strong-duality theorems.
Weak duality: Suppose the primal LP is a maximization problem with an objective value , then is bounded from above by the objective value of the dual .
Strong duality: If an optimum objective value exists for any one of the primal-dual LP problems, it is guaranteed to exist for the other. And not just that, but in a case like this, the optimum objective values for the two problems are exactly the same.
The maximum-flow and minimum-cut problems are famous for illustrating how linear programming duality is effective for arriving simultaneously at solutions for both problems. Approximation algorithms also make effective use of the primal-dual LP relationship for solving other hard problems.
A linear program with additional constraints that require variables to be integers is called an integer linear programs (ILP). Even though, polynomial-time algorithms for solving LP problems are well-known, integer linear programming is NP-hard and polynomial-time algorithms for it aren’t known to exist. One way to deal with problems like these efficiently is to devise approximation algorithms for them.
An approximation algorithm is an algorithm that gives a ‘good enough’ solution (and not necessarily the best solution,) but that solution is accompanied by some kind of mathematical guarantee of how good it is.
In short, linear programming is immensely useful for increasing efficiency and cost-effectiveness across a variety of systems and processes. For this reason, it is used heavily in disciplines like agriculture, finance, operation research, transport, military, engineering, and technology. It is also applied beautifully in areas of active theoretical research.
If you’d like to learn how to use the Python library PuLP for linear programming, the following course on the Educative platform can help:
We make optimization decisions every day. To improve the performance of your applications, computers need to do the same. This course will help you optimize computing functions through the open-source Python library PuLP. In this course, you’ll learn about linear programming, an optimization approach that maximizes or minimizes functions through defined algebra, and the PuLP library along with its various optimizers available via APIs. You’ll identify the variables and constraints of computing functions and define the optimization goals. You’ll then learn and practice common linear programming algorithms. Finally, you’ll be introduced to potential applications in the real world. By the end of the course, you will be able to optimize computing functions using Python and PuLP.
Free Resources