Solving general linear programming problems: lpsolve

### 4.44.2 Solving general linear programming problems: lpsolve

Linear programming problems where a multivariate linear function should be maximized or minimized subject to linear equality or inequality constraints, as well as mixed integer problems, can be solved with the function lpsolve. It takes (at most) four arguments, in the following order :

- obj : symbolic expression representing the objective function
- constr (optional) : list of linear constraints which may be equalities or inequalities or bounded expressions entered as expr=a..b
- bd (optional) : sequence of expressions of type var=a..b specifying that the variable var is bounded with a below and with b above
- opts (optional) : sequence of option=value parameters, where option may be one of assume, lp_maximize, lp_variables, lp_integervariables, lp_binaryvariables, lp_nodelimit, lp_depthlimit, lp_method, lp_initialpoint or lp_integertolerance

The return value is in the form [optimum,soln] where optimum is the minimum/maximum value of the objective function and soln is a list of coordinates corresponding to the point at which the optimal value is attained. If there is no feasible solution, an empty list is returned. When the objective function is unbounded, optimum is returned as +∞ (for maximization problems) or −∞ (for minimization problems). In these cases soln is generally meaningless.

If obj is given as constant (for example, zero) then only a feasible point is returned as a list, if one exists. If the problem is infeasible, an empty list is returned. This may be used as a test to check whether a set of linear constraints is feasible or not.

The given objective function is minimized by default. To maximize it, include the option lp_maximize[=true].

By default, all variables are considered continuous and unrestricted in sign.

#### Problems with continuous variables

For example, to solve the problem specified in (1), input :

constr:=[x<=1,y>=2,x+3y-z=2,3x-y+z<=8,-x+y<=5];
lpsolve(2x+y-z+4,constr)

Output :

[-4,[x=0,y=5,z=13]]

Therefore, the minimum value of f(x,y,z)=2 x+y−z+4 is equal to −4 under the given constraints. The optimal value is attained at point (x,y,z)=(0,5,13) .

Constraints may also take the form expr=a..b for bounded linear expressions.

Input :

lpsolve(x+2y+3z,[x+y=1..5,y+z+1=2..4,x>=0,y>=0])

Output :

[-2,[x=0,y=5,z=-4]]

Use the assume=lp_nonnegative option to specify that all variables are nonnegative. That is easier than entering the nonnegativity constraints explicitly.

Input:

lpsolve(-x-y,[y<=3x+1/2,y<=-5x+2],
assume=lp_nonnegative)

Output:

[-5/4,[x=3/16,y=17/16]]

Bounds can be added separately for some variables. They are entered after the list of constraints.

Input :

constr:=[5x-10y<=20,2z-3y=6,-x+3y<=3];
lpsolve(-6x+4y+z,constr,x=1..20,y=0..inf)

Output :

[-133/2,[x=18,y=7,z=27/2]]

##### Choosing a suitable solving method.

The method used by solver can be specified using the option :

lp_method=lp_simplex or lp_interiorpoint

Simplex method, specified by lp_simplex, is exact. lp_interiorpoint specifies interior point method, which is inexact. More precisely, the method used in this case is primal-dual affine scaling method. By default, simplex method is used.

The initial point for affine scaling algorithm is computed automatically by default. If a specific point is required, use the option :

lp_initialpoint=<list of coordinates>

Be aware that affine scaling method may fail due to rounding errors or an ill-chosen initial point. Simplex method is much more reliable, especially for (mixed) integer problems which are discussed in the next section. However, interior point method is useful for larger problems and problems with inexact coefficients, because simplex method may fail to find initial feasible solution due to rounding errors. For example, consider the following problem :

minimize | 1.06 x1+0.56 x2+3.0 x3+2703.5 x4+4368.23 x5 |  |  |  |  |  |  |  |  |
subject to | 1.06 x1+0.015 x3 ≥ 729824.87 |  |  |  |  |  |  |  |  |
| 0.56 x2+0.649 x3≥ 1522188.03 |  |  |  |  |  |  |  |  |
| x3≥ 1680.05 |  |  |  |  |  |  |  |  |
| x4≥ 60.0 |  |  |  |  |  |  |  |  |
| x5≥ 4.0 |  |  |  |  |  |  |  |  |

Trying to solve using simplex method fails, but switching to affine scaling leads to the correct solution.

Input :

lpsolve(1.06x1+0.56x2+3x3+2703.50x4+4368.23x5, [1.06x1+0.015x3>=729824.87,0.56x2+0.649x3>=1522188.03, x3>=1680.05,x4>=60,x5>=4],assume=lp_nonnegative, method=lp_interiorpoint)

Output :

[2435620.4168,[x1=688490.25401,x2=2716245.85277, x3=1680.05000032,x4=60.0000000003,x5=4.00000000017]]

#### Integer programming

Use the assume=integer or assume=lp_integer option to solve integer programming problems. The function lpsolve uses branch and bound method and applies suitable Gomory mixed integer (GMI) cuts in such cases. The numbers of investigated subproblems and added GMI cuts is printed out before the function returns. To limit branch and bound tree depth, use the option :

lp_depthlimit=<positive integer>

To limit number of subproblems to be investigated, use the option :

lp_nodelimit=<positive integer>

If one of these options is enabled, the solution is not guaranteed to be optimal.

Input :

lpsolve(-5x-7y,[7x+y<=35,-x+3y<=6],assume=integer)

Output :

[-41,[x=4,y=3]]

Use the option assume=lp_binary to specify that all variables are binary, i.e. the only allowed values are 0 and 1. Binary variables usually represent true and false values, giving them a certain meaning in logical context.

Input :

lpsolve(8x1+11x2+6x3+4x4,[5x1+7x2+4x3+3x4<=14],
assume=lp_binary,lp_maximize)

Output :

[21,[x1=0,x2=1,x3=1,x4=1]]

Options

lp_integervariables=<list of integer variables>

and

lp_binaryvariables=<list of binary variables>

are used for specifying mixed integer/binary programming problems. Also, the

lp_variables=<list of continuous variables>

option may be used, which overrides integer and binary settings. For example, a linear programming problem with mostly integer variables may be specified using the option assume=integer and specifying continuous variables with lp_variables, which overrides the global integer setting.

Input :

lpsolve(x+3y+3z,[x+3y+2z<=7,2x+2y+z<=11],
assume=lp_nonnegative,lp_maximize, lp_integervariables=[x,z])

Output:

[10,[x=0,y=1/3,z=3]]

Use the assume=lp_nonnegint or assume=nonnegint option to get nonnegative integer values.

Input :

lpsolve(2x+5y,[3x-y=1,x-y<=5],assume=nonnegint)

Output :

[12,[x=1,y=2]]

The option lp_integertolerance=<positive number> can be used to specify the precision of integer variables. Letting ε denote the integer tolerance, every value x such that |x−k|<ε for some k∈ℤ is treated as an integer.

Note that (currently) only simplex method is used in combination with branch and bound method.

#### Entering linear programs in matrix form

The function lpsolve supports entering linear programming problems in matrix form, which is convenient for problems with relatively large number of variables and/or constraints.

To enter a problem in matrix form, obj must be a vector of coefficients c and constr, which is mandatory this case, must be a list [A,b,Aeq,beq] , where A,Aeq are matrices and b,beq are vectors of reals. By default, the function minimizes cT x subject to A x≤b and Aeq x=beq . If a problem does not contain equality constraints, parameters Aeq and beq may be omitted. For a problem that does not contain inequality constraints, empty lists must be passed as A and b .

The parameter bd is entered as a list of two vectors bl and bu of the same length as the vector c such that bl≤x≤bu . For unbounded variables use +infinity or -infinity.

When specifying mixed problems in matrix form, variables are entered as the corresponding indexes, which are 1-based, i.e. the first variable has index 1, the second variable has index 2 and so on. Other options for lpsolve are passed to a problem in matrix form in the same way as if it was in symbolic form.

Input :

c:=[-2,1];A:=[[-1,1],[1,1],[-1,0],[0,-1]];
b:=[3,5,0,0];lpsolve(c,[A,b])

Output :

[-10,[5,0]]

Input :

c:=[-2,5,-3];bl:=[2,3,1];bu:=[6,10,3.5];
lpsolve(c,[],[bl,bu])

Output :

[-7.5,[6.0,3.0,3.5]]

Input :

c:=[4,5];Aeq:=[[-1,1.5],[-3,2]];beq:=[2,3];
lpsolve(c,[[],[],Aeq,beq])

Output :

[5.2,[-0.2,1.2]]

Input :

c:=[2,-3,-5];A:=[[-5,4,-5],[2,5,7],[2,-3,4]];
b:=[3,1,-2];lpsolve(c,[A,b],lp_integervariables=[1,3])

Output :

[19,[1,3/4,-1]]