Introduction

Introduction to lp_solve 5.1.1.2

What is lp_solve and what is it not? The simple answer is, lp_solve is a Mixed Integer Linear Programming (MILP) solver.

It is a free (see LGPL for the GNU lesser general public license) linear (integer) programming solver based on the revised simplex method and the Branch-and-bound method for the integers.
It contains full source, examples and manuals.
lp_solve solves pure linear, (mixed) integer/binary, semi-continuous and special ordered sets (SOS) models. Note the word linear. This means that equations must be of the first order. 5 * x - 3 * y is an example. However x * y is not linear and cannot be handled by lp_solve. Both the objective function and the constraints have this restriction. Also see Ratios.
Via the Branch-and-bound algorithm, it can handle integer variables (see integer variables), semi-continuous variables (see semi-continuous variables) and Special Ordered Sets (see Special Ordered Sets (SOS)).
lp_solve has no limit on model size and accepts standard both lp or mps input files, but even that can be extended. Note however that some models could give lp_solve a hard time and will even fail to solve. The larger the model the likely the chance for that. But even commercial solvers have problems with that.
It can also be called as a library from different languages like C, VB, .NET, Delphi, Excel, Java, ...
It can also be called from AMPL via the lpsolve driver program. It can also be called from MATLAB, O-Matrix and Scilab via the a driver program. lp_solve is written in ANSI C and can be compiled on many different platforms like linux and WINDOWS.

lp_solve has its own community via the Yahoo group http://groups.yahoo.com/group/lp_solve/. There you can find the latest sources, executables for the common platforms, examples, manuals and a message board where people can share their thoughts on lp_solve.

lp_solve was originally developed by Michel Berkelaar at Eindhoven University of Technology. The work of Jeroen Dirks made the transition from the basic version 1.5 to the full version 2.0 possible. He contributed the procedural interface, a built-in MPS reader, and many fixes and enhancements to the code. At that point there was also a Java port of lp_solve 2.0. This was not a Java native interface (JNI) to the C library, but rather a translation of the algorithm (ver 2.0) from C into Java. It was also very limited This meant that it did not keep up with lp_solve as it evolved. Starting at version 3.0, lp_solve is released under the LGPL license. Before the code could only be used for non-commercial purposes. Many other people also contributed to lp_solve, but there was no track of them. Sorry if you are not mentioned. Development was stagnated for some time at version 3.2, but now it is again alive and well via the new developers Kjell Eikland and Peter Notebaert. But also other people help to improve the product. For example the new Java interface to lp_solve was made by Juergen Ebert. It is a JNI interface that supports the full functionality of lp_solve. He did a great job. We encourage other people to participate in the development of lp_solve.
First a version 4 was introduced that had already several enhancements and improvements and now with version 5 this enhancement continues resulting is faster solving times, more stability and able to solver larger models and new functionality. See Changes compared to version 4 for the changes done in version 5.

Basically, lp_solve is a library, a set of routines, called the API that can be called from almost any programming language to solve MILP problems. There are two ways to pass the data to the library:

  • Via the API
  • Via input files
  • Via an IDE

Via the API

The API is a set of routines that can be called from a programming language to build the model in memory, solve it and return the results. There are many API routines to perform many possible tasks and set several options. See lp_solve API reference for an overview.

Via input files

Standard, lp_solve supports several input files types. The common known MPS format (see mps-format) is supported by most solvers, but it is not very readable for humans. Another format is the lp format (see lp-format) that is more readable. lp_solve has the unique ability to use user-written routines to input the model (see External Language Interface). See read_mps, read_freemps, read_MPS, read_freeMPS and read_lp, read_LP for the API calls to read the model from file.

There is also a driver program called lp_solve that uses the API to provide a command line application to solve models. See lp_solve for its usage. With this program you don't have to know anything of API or computer programming languages. You can just provide your model via file to the program and it will solve the model and give you the result.

Via an IDE

Thanks to Henri Gourvest, there is now also an IDE program called LPSolve IDE that uses the API to provide a Windows application to solve models. See LPSolve IDE for its usage. With this program you don't have to know anything of API or computer programming languages. You can just provide your model to the program and it will solve the model and give you the result.

As already stated, lp_solve can be called from many programming language. Among them are C, C++, Pascal, Delphi, Java, VB, C#, VB.NET, Excel. But let this list not be a limitation. Any programming language capable of calling external libraries (DLLs under Windows, Shared libraries (.so) under Unix/Linux) can call lp_solve.

Here is a list of some key features of lp_solve:

  • Mixed Integer Linear Programming (MILP) solver
  • Basically no limit on model size
  • It is free and with sources
  • Supports Integer variables, Semi-continuous variables and Special Ordered Sets
  • Can read model from MPS, LP or user written format
  • Models can be build in-memory without the use of files
  • Has a powerful API interface
  • Easy callable from other programming languages
  • Advanced pricing using Devex and Steepest Edge for both primal and dual simplexes
  • Provides different scaling methods to make the model more numerical stable
  • Has presolve capabilities to tighten constraints/make the model smaller and faster to solve
  • Has a base crashing routine to determine a starting point
  • Allows restart after making changes to the model. Solve continues from the last found solution
  • Possible to select desired combinations of primal and dual phases 1 and 2
  • Possible to set several solver parameters like tolerances
  • Alternative (and faster) inverse/re-factorisation libraries are provided for. See Basis Factorization Packages
  • Alternative model readers and writers possible via the XLI implementation. See External Language Interfaces
  • Has the possibility to convert one model format to another format
  • Provides post-optimal sensitivity analysis. See Sensitivity
  • ...


lp_solve API reference

Alfabetical index

add_column, add_columnex, str_add_column
add_constraint, add_constraintex, str_add_constraint
add_lag_con, str_add_lag_con
add_SOS
column_in_lp
default_basis
del_column
del_constraint
delete_lp
free_lp
get_anti_degen
get_basis
get_basiscrash
get_bb_depthlimit
get_bb_floorfirst
get_bb_rule
get_bounds_tighter
get_break_at_value
get_col_name, get_origcol_name
get_column
get_constr_type
get_constraints, get_ptr_constraints
get_epsb
get_epsd
get_epsel
get_epsint
get_epsperturb
get_epspivot
get_improve
get_infinite
get_lambda, get_ptr_lambda, get_lambda, get_ptr_lambda
get_lowbo
get_lp_index
get_lp_name
get_Lrows
get_mat
get_max_level, get_max_level
get_maxpivot
get_mip_gap
get_Ncolumns
get_nameindex
get_negrange
get_nonzeros
get_Norig_columns
get_Norig_rows
get_Nrows
get_obj_bound
get_objective
get_orig_index
get_pivoting
get_presolve
get_primal_solution, get_ptr_primal_solution, get_var_primalresult
get_print_sol
get_rh
get_rh_range
get_row
get_row_name, get_origrow_name
get_scalelimit
get_scaling
get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex
get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult
get_simplextype
get_solutioncount
get_solutionlimit
get_status
get_statustext
get_timeout
get_total_iter
get_total_nodes
get_upbo
get_var_branch
get_var_priority, get_var_priority
get_variables, get_ptr_variables
get_verbose
get_working_objective
has_BFP
has_XLI
is_add_rowmode
is_anti_degen
is_binary
is_break_at_first
is_constr_type
is_debug
is_feasible
is_free
is_infinite
is_int
is_integerscaling
is_lag_trace
is_maxim
is_nativeBFP
is_nativeXLI
is_negative
is_piv_mode
is_piv_rule
is_presolve
is_scalemode
is_scaletype
is_semicont
is_SOS_var
is_trace
lag_solve
lp_solve_version
make_lp
print_constraints
print_debugdump
print_duals
print_lp
print_objective
print_scales
print_solution
print_str
print_tableau
put_abortfunc
put_logfunc
put_msgfunc
read_lp, read_LP
read_mps, read_freemps, read_MPS, read_freeMPS
read_XLI
reset_basis
set_add_rowmode
set_anti_degen, get_anti_degen
set_basis
set_basiscrash
set_bb_depthlimit
set_bb_floorfirst
set_bb_rule
set_BFP
set_XLI
set_binary
set_bounds
set_bounds_tighter
set_break_at_first
set_break_at_value
set_column, set_columnex
set_col_name
set_constr_type
set_debug
set_epsb
set_epsd
set_epsel
set_epsint
set_epsperturb
set_epspivot
set_free
set_improve
set_infinite
set_int
set_lag_trace
set_lowbo
set_lp_name
set_mat
set_maxim
set_maxpivot
set_minim
set_mip_gap
set_negrange
set_obj_bound
set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj
set_outputstream, set_outputfile
set_pivoting
set_preferdual
set_presolve
set_print_sol
set_rh
set_rh_range
set_rh_vec, str_set_rh_vec
set_row, set_rowex
set_row_name
set_scalelimit
set_scaling
set_semicont
set_sense
set_simplextype
set_solutionlimit
set_timeout
set_trace
set_upbo
set_var_branch
set_var_weights
set_verbose
solve
time_elapsed
unscale
write_lp, write_LP
write_mps, write_freemps, write_MPS, write_freeMPS
write_XLI

Functional index

Create/destroy model

make_lp
read_lp, read_LP
read_mps, read_freemps, read_MPS, read_freeMPS
read_XLI
delete_lp
free_lp

Build model

add_column, add_columnex, str_add_column, set_column, set_columnex, get_column
add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex
add_lag_con, str_add_lag_con
add_SOS, is_SOS_var
del_column
del_constraint, get_row
get_nameindex
is_infinite
is_negative
set_add_rowmode, is_add_rowmode
set_binary, is_binary
set_bounds
set_bounds_tighter, get_bounds_tighter
set_col_name, get_col_name, get_origcol_name
set_constr_type, get_constr_type, is_constr_type
set_free, is_free
set_infinite, get_infinite
set_int, is_int
set_lowbo, get_lowbo
set_lp_name, get_lp_name
set_mat, get_mat
set_obj_bound, get_obj_bound
set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj
set_rh, get_rh
set_rh_range, get_rh_range
set_rh_vec, str_set_rh_vec
set_row_name, get_row_name, get_origrow_name
set_semicont, is_semicont
set_upbo, get_upbo
set_var_branch, get_var_branch
set_var_weights

Solver settings

default_basis
reset_basis
set_anti_degen, is_anti_degen
set_basis, get_basis
set_basiscrash, get_basiscrash
set_bb_depthlimit, get_bb_depthlimit
set_bb_floorfirst, get_bb_floorfirst
set_bb_rule, get_bb_rule
set_BFP, has_BFP, is_nativeBFP
set_break_at_first, is_break_at_first
set_break_at_value, get_break_at_value
set_epsb, get_epsb
set_epsd, get_epsd
set_epsel, get_epsel
set_epsint, get_epsint
set_epsperturb, get_epsperturb
set_epspivot, get_epspivot
set_improve, get_improve
set_maxim, is_maxim
set_maxpivot, get_maxpivot
set_minim
set_mip_gap, get_mip_gap
set_negrange, get_negrange
set_pivoting, get_pivoting, is_piv_mode, is_piv_rule
set_preferdual
set_presolve, get_presolve, is_presolve
set_scalelimit, get_scalelimit
set_scaling, get_scaling, is_integerscaling, is_scalemode, is_scaletype
set_sense
set_simplextype, get_simplextype
set_solutionlimit, get_solutionlimit
set_timeout, get_timeout
unscale

Callback routines

put_abortfunc
put_logfunc
put_msgfunc

Solve

solve
lag_solve

Solution

get_constraints, get_ptr_constraints
get_objective
get_primal_solution, get_ptr_primal_solution, get_var_primalresult
get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex
get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult
get_solutioncount
get_total_iter
get_total_nodes
get_variables, get_ptr_variables
get_working_objective
is_feasible

Debug/print settings

set_debug, is_debug
set_lag_trace, is_lag_trace
set_outputstream, set_outputfile
set_print_sol, get_print_sol
set_trace, is_trace
set_verbose, get_verbose

Debug/print

print_constraints
print_debugdump
print_duals
print_lp
print_objective
print_scales
print_solution
print_str
print_tableau

Write model to file

write_lp, write_LP
write_mps, write_freemps, write_MPS, write_freeMPS
write_XLI, set_XLI, has_XLI, is_nativeXLI

Miscellaneous routines

column_in_lp
get_lp_index
get_Lrows
get_Ncolumns
get_nonzeros
get_Norig_columns
get_Norig_rows
get_Nrows
get_orig_index
get_statustext
get_statustext
lp_solve_version
time_elapsed


add_column, add_columnex, str_add_column

Add a column to the lp.

unsigned char add_column(lprec *lp, REAL *column);

unsigned char add_columnex(lprec *lp, int count, REAL *column, int *rowno);

unsigned char str_add_column(lprec *lp, char *col_string);

Return Value

add_column, add_columnex, and str_add_column return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

count

Number of elements in column and rowno.

column

An array with 1+rows (count for add_columnex if rowno is different from NULL) elements that contains the values of the column.

rowno

An array with count elements that contains the row numbers of the column. However this variable can also be NULL. In that case element i in the variable column is row i.

col_string

A string with row elements that contains the values of the column. Each element must be separated by space(s).

Remarks

The add_column, add_columnex, str_add_column functions add a column to the model (at the end) and sets all values of the column at once.
Note that for add_column (and add_columnex when rowno is NULL) element 0 of the array is the value of the objective function for that column. Column 1 is element 1, column 2 is element 2, ...
add_columnex has the possibility to specify only the non-zero elements. In that case rowno specifies the row numbers of the non-zero elements. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value. Thus it is almost always better to use add_columnex instead of add_column. add_columnex is always at least as performant as add_column. One important note about add_columnex. str_add_column should only be used in small or demo code since it is not performant and uses more memory.
For add_columnex, column and rowno can both be NULL. In that case an empty column is added.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL column[1+2]; /* must be 1 more then number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  column[0] = 1.0; /* the objective value */
  column[1] = 2.0;
  column[2] = 3.0;
  add_column(lp, column);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, set_column, set_columnex, del_column, set_add_rowmode, is_add_rowmode, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, get_column, get_row, get_mat, column_in_lp


add_constraint, add_constraintex, str_add_constraint

Add a constraint to the lp.

unsigned char add_constraint(lprec *lp, REAL *row, int constr_type, REAL rh);

unsigned char add_constraintex(lprec *lp, int count, REAL *row, int *colno, int constr_type, REAL rh);

unsigned char str_add_constraint(lprec *lp, char *row_string, int constr_type, REAL rh);

Return Value

add_constraint, add_constraintex and str_add_constraint return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

count

Number of elements in row and colno.

row

An array with 1+column (count for add_constraintex if colno is different from NULL) elements that contains the values of the row.

colno

An array with count elements that contains the column numbers of the row. However this variable can also be NULL. In that case element i in the variable row is column i and values start at element 1.

row_string

A string with column elements that contains the values of the row. Each element must be separated by space(s).

constr_type

The type of the constraint. Can by any of the following values:

LE (1) | Less than or equal (<=)
EQ (3) | Equal (=)
GE (2) | Greater than or equal (>=)

rh

The value of the right hand side (RHS).

Remarks

The add_constraint, add_constraintex, str_add_constraint functions add a row to the model (at the end) and sets all values of the row at once.
Note that for add_constraint (and add_constraintex when colno is NULL) element 0 of the array is not considered (i.e. ignored). Column 1 is element 1, column 2 is element 2, ...
add_constraintex has the possibility to specify only the non-zero elements. In that case colno specifies the column numbers of the non-zero elements. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value. Thus it is almost always better to use add_constraintex instead of add_constraint. add_constraintex is always at least as performant as add_constraint. Note that these routines will perform much better when set_add_rowmode is called before adding constraints.
Note that it is advised to set the objective function (via set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj) before adding rows. This especially for larger models. This will be much more performant than adding the objective function afterwards.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_add_rowmode(lp, TRUE);
  row[1] = 1.0;
  row[2] = 2.0;
  add_constraint(lp, row, GE, 3.0); /* constructs the row: +v_1 +2 v_2 >= 3 */
  set_add_rowmode(lp, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, set_add_rowmode, is_add_rowmode, get_constr_type, is_constr_type, del_constraint, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_row, get_mat


add_lag_con, str_add_lag_con

Add a Lagrangian constraint to the lp.

unsigned char add_lag_con(lprec *lp, REAL *row, int con_type, REAL rhs);

unsigned char str_add_lag_con(lprec *lp, char *row_string, int con_type, REAL rhs);

Return Value

add_lag_con and str_add_lag_con returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

An array with column elements that contains the values of the row.

row_string

A string with column elements that contains the values of the row. Each element must be separated by space(s).

con_type

The type of the constraint. Can by any of the following values:

LE (1) | Less than or equal (<=)
EQ (3) | Equal (=)
GE (2) | Greater than or equal (>=)

rhs

The value of the right hand side (RHS).

Remarks

The add_lag_con, str_add_lag_con functions adds a Lagrangian row to the model (at the end) and sets all values of the row at once.
Note that element 0 of the array is not considered (i.e. ignored). Column 1 is element 1, column 2 is element 2, ...

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 1.0;
  add_lag_con(lp, row, LE, 1.0); /* constructs the Lagrangian row: +v_1 +v_2 <= 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, get_con_type, del_constraint, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_row, get_mat, lag_solve, get_Lrows


add_SOS

Add a SOS (Special Ordered Sets) constraint.

int add_SOS(lprec *lp, char *name, int sostype, int priority, int count, int *sosvars, REAL *weights);

Return Value

add_SOS returns the list index of the new SOS if the operation was successful. A return value of 0 indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

name

The name of the SOS constraint.

sostype

The type of the SOS constraint. Must be >= 1

priority

Priority of the SOS constraint in the SOS set.

count

The number of variables in the SOS list.

sosvars

An array specifying the count variables (their column numbers).

weights

An array specifying the count variable weights. May also be NULL. In that case, lp_solve will weight the variables in the order they are specified.

Remarks

The add_SOS function adds an SOS constraint.
See Special Ordered Sets for a description about SOS variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int vars[2];
  double weights[2];

  /* Create a new LP model */
  lp = make_lp(0, 4);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  vars[0] = 2; vars[1] = 3;
  weights[0] = 1.0; weights[1] = 2.0;
  add_SOS(lp, "SOS", 1, 1, sizeof(vars)/sizeof(*vars), vars, weights);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_SOS_var


column_in_lp

Check if a column is already present in the lp.

int column_in_lp(lprec *lp, REAL *column);

Return Value

column_in_lp returns the (first) column number if the column is already in the lp and 0 if not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

An array with 1+row elements that are checked against the existing columns in the lp.

Remarks

The column_in_lp functions checks if a column is already present in the lp.
It does not look at bounds and types, only at matrix values.
The first matched column is returned. If there is no column match, then 0 is returned.
Note that element 0 is the objective function value. Element 1 is column 1, and so on.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL column[1+2]; /* must be 1 more then number of rows ! */
  int ret;

  /* Create a new LP model */
  lp = make_lp(2, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  column[0] = 0.0;
  column[1] = 0.0;
  column[2] = 0.0;
  ret = column_in_lp(lp, column); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_column, add_columnex, str_add_column, set_column, set_columnex, del_column


default_basis

Sets the starting base to an all slack basis (the default simplex starting basis).

void default_basis(lprec *lp);

Return Value

None

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The default_basis function sets the starting base to an all slack basis (the default simplex starting basis).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  default_basis(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basiscrash, set_basiscrash, get_basis, set_basis


del_column

Remove a column from the lp.

unsigned char del_column(lprec *lp, int column);

Return Value

del_column returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
An error occurs when column is not between 1 and the number of columns in the lp.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column to delete. Must be between 1 and the number of columns in the lp.

Remarks

The del_column function deletes a column from the model. The column is effectively deleted, so all columns after this column shift one left.
Note that column 0 (the right hand side (RHS)) cannot be deleted. There is always a RHS.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  del_column(lp, 1);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_column, add_columnex, str_add_column


del_constraint

Remove a constraint from the lp.

unsigned char del_constraint(lprec *lp, int del_row);

Return Value

del_constraint returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
An error occurs when del_row is not between 1 and the number of rows in the lp.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

del_row

The row to delete. Must be between 1 and the number of rows in the lp.

Remarks

The del_constraint function deletes a row from the model. The row is effectively deleted, so all rows after this row shift one up.
Note that row 0 (the objective function) cannot be deleted. There is always an objective function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  del_constraint(lp, 1);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_constraint, add_constraintex, str_add_constraint


delete_lp

Deletes an lprec structure.

void delete_lp(lprec *lp);

Return Value

None

Parameters

lp

lprec structure to delete.

Remarks

The delete_lp function frees all memory allocated to the lp structure.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI


free_lp

Deletes an lprec structure and initialise the plp variable.

void free_lp(lprec **plp);

Return Value

None

Parameters

plp

lprec structure to delete. After the call, *plp will be set to NULL.

Remarks

The free_lp function frees all memory allocated to the lp structure and initialises the *plp variable.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  free_lp(&lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI


get_anti_degen

Returns the used degeneracy rule.

int get_anti_degen(lprec *lp);

Return Value

get_anti_degen returns the used degeneracy rule. Can be a combination of any of the following values:

ANTIDEGEN_NONE (0) | No anti-degeneracy handling
ANTIDEGEN_FIXEDVARS (1) | Check if there are equality slacks in the basis and try to drive them out in order to reduce chance of degeneracy in Phase 1
ANTIDEGEN_COLUMNCHECK (2) |
ANTIDEGEN_STALLING (4) |
ANTIDEGEN_NUMFAILURE (8) |
ANTIDEGEN_LOSTFEAS (16) |
ANTIDEGEN_INFEASIBLE (32) |
ANTIDEGEN_DYNAMIC (64) |
ANTIDEGEN_DURINGBB (128) |

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_anti_degen function returns the used degeneracy rule.

Example

#include
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int anti_degen;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }
  anti_degen= get_anti_degen(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_anti_degen, is_anti_degen


get_basis

Returns the basis of the lp.

void get_basis(lprec *lp, int *bascolumn, unsigned char nonbasic);

Return Value

get_basis has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bascolumn

An array with 1+get_Nrows or 1+get_Nrows+get_Ncolumns elements that will contain the basis after the call.

nonbasic

If FALSE, then bascolumn must have 1+get_Nrows elements and only contains the basic variables. If TRUE, then bascolumn must have 1+get_Nrows+get_Ncolumns elements and will also contain the non-basic variables.

Remarks

The get_basis function returns the basis of the lp.
The array receives the basic variables and if nonbasic is TRUE, then also the non-basic variables. If an element is less then zero then it means on lower bound, else on upper bound.
Element 0 of the array is unused.
The default initial basis is bascolumn[x] = -x.
Each element represents a basis variable. If the absolute value is between 1 and get_Nrows, it represents a slack variable and if it is between get_Nrows+1 and get_Nrows+get_Ncolumns then it represents a regular variable. If the value is negative, then the variable is on its lower bound. If positive it is on its upper bound.
Setting an initial basis can speed up the solver considerably. It is the starting point from where the algorithm continues to find an optimal solution.
When a restart is done, lp_solve continues at the last basis, except if set_basis or default_basis is called.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int bascolumn[1+2]; /* must be 1 more then number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }
  get_basis(lp, bascolumn, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_basis, default_basis, get_basiscrash, set_basiscrash


get_basiscrash

Determines a starting base.

int get_basiscrash(lprec *lp);

Return Value

Specifies which basis crash mode is used. Can by any of the following values:

CRASH_NOTHING (0) | No basis crash
CRASH_MOSTFEASIBLE (2) | Most feasible basis

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_basiscrash function returns which basis crash mode must be used. This can influence the solving time considerly. Default it is CRASH_NOTHING.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int basiscrash;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  basiscrash = get_basiscrash(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_basiscrash, default_basis, get_basis, set_basis


get_bb_depthlimit

Returns the maximum branch-and-bound depth.

int get_bb_depthlimit(lprec *lp);

Return Value

get_bb_depthlimit returns the maximum branch-and-bound depth.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_bb_depthlimit function returns the maximum branch-and-bound depth.
This is only usefull if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algorithm must be used to solve them. The branch-and-bound algorithm will not go deeper than this level. When 0 then there is no limit to the depth. Limiting the depth will speed up solving time, but there is a chance that the found solution is not the most optimal one. Be aware of this. It can also result in not finding a solution at all. A positive value means that the depth is absoluut. A negative value means a relative B&B depth limit. The "order" of a MIP problem is defined to be 2x the number of binary variables plus the number of SC and SOS variables. A relative value of -x results in a maximum depth of x times the order of the MIP problem.
The default is -50.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int bb_maxlevel;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  bb_maxlevel = get_bb_depthlimit(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bb_depthlimit


get_bb_floorfirst

Returns which branch to take first in branch-and-bound algorithm.

int get_bb_floorfirst(lprec *lp);

Return Value

get_bb_floorfirst returns which branch to take first in branch-and-bound algorithm. Can by any of the following values:

BRANCH_CEILING (0) | Take ceiling branch first
BRANCH_FLOOR (1) | Take floor branch first
BRANCH_AUTOMATIC (2) | Algorithm decides which branch being taken first

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_bb_floorfirst function returns which branch to take first in branch-and-bound algorithm. This can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is BRANCH_FLOOR (1).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int floor_first;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  floor_first = get_bb_floorfirst(lp); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bb_floorfirst, set_var_branch, get_var_branch, set_var_weights, get_var_priority


get_bb_rule

Returns the branch-and-bound rule.

int get_bb_rule(lprec *lp);

Return Value

get_bb_rule returns the branch-and-bound rule. Can by any of the following values:

NODE_FIRSTSELECT (0) | Select lowest indexed non-integer column
NODE_GAPSELECT (1) | Selection based on distance from the current bounds
NODE_RANGESELECT (2) | Selection based on the largest current bound
NODE_FRACTIONSELECT (3) | Selection based on largest fractional value
NODE_PSEUDOCOSTSELECT (4) | Simple, unweighted pseudo-cost of a variable
NODE_PSEUDONONINTSELECT (5) | This is an extended pseudo-costing strategy based on minimizing the number of integer infeasibilities
NODE_PSEUDORATIOSELECT (6) | This is an extended pseudo-costing strategy based on maximizing the normal pseudo-cost divided by the number of infeasibilities. Effectively, it is similar to (the reciprocal of) a cost/benefit ratio
NODE_USERSELECT (7) |

One of these values may be or-ed with one or more of the following values:

NODE_WEIGHTREVERSEMODE (8) |
NODE_BRANCHREVERSEMODE (16) | In case when get_bb_floorfirst is BRANCH_AUTOMATIC, select the oposite direction (lower/upper branch) that BRANCH_AUTOMATIC had chosen.
NODE_GREEDYMODE (32) |
NODE_PSEUDOCOSTMODE (64) |
NODE_DEPTHFIRSTMODE (128) | Select the node that has already been selected before the most number of times
NODE_RANDOMIZEMODE (256) |
NODE_DYNAMICMODE (1024) | When NODE_DEPTHFIRSTMODE is selected, switch off this mode when a first solution is found.
NODE_RESTARTMODE (2048) |
NODE_BREADTHFIRSTMODE (4096) | Select the node that has been selected before the fewest number of times or not at all
NODE_AUTOORDER (8192) | Create an "optimal" B&B variable ordering. Can speed up B&B algorithm.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_bb_rule function returns the branch-and-bound rule for choosing which non-integer variable is to be selected. This rule can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is NODE_FIRSTSELECT (0).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int bb_rule;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  bb_rule = get_bb_rule(lp); /* will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bb_rule


get_bounds_tighter

Returns if set bounds may only be tighter or also less restrictive.

unsigned char get_bounds_tighter(lprec *lp);

Return Value

get_bounds_tighter returns if bounds may only be tighter or also less restrictive.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_bounds_tighter function returns if bounds may only be tighter or also less restrictive. If set to TRUE then bounds may only be tighter. This means that when set_lowbo or set_lowbo is used to set a bound and the bound is less restrictive than an already set bound, then this new bound will be ignored. If FALSE, the new bound is accepted. This functionality is useful when several bounds are set on a variable and at the end you want the most restrictive ones. By default, this setting is FALSE. Note that this setting does not affect set_bounds.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int tighter;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  tighter = get_bounds_tighter(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bounds_tighter, set_upbo, get_upbo, set_lowbo, get_lowbo, set_bounds, set_free, is_free, is_negative


get_break_at_value

Returns the value at which the branch-and-bound algorithm stops when the object value is better than this value.

REAL get_break_at_value(lprec *lp);

Return Value

get_break_at_value returns the value to break on.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_break_at_value function returns the value at which the branch-and-bound algorithm stops when the object value is better than this value. Stopping at a given object value can be useful if you are only interested for a solution that has an object value which is at least a given value, but not necessarily (and most probably) the most optimal solution.
The default value is (-) infinity.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL break_at_value;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  break_at_value = get_break_at_value(lp); /* Will return -1e30 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_break_at_value, set_break_at_first, is_break_at_first, set_obj_bound, get_obj_bound, set_mip_gap, get_mip_gap


get_col_name, get_origcol_name

Gets the name of a column in the lp.

char *get_col_name(lprec *lp, int column);

char *get_origcol_name(lprec *lp, int column);

Return Value

get_col_name and get_origcol_name return the name of the specified column. A return value of NULL indicates an error. The difference between get_col_name and get_origcol_name is only when a presolve (set_presolve) was done. Presolve can result in deletion of columns in the model. In get_col_name, column specifies the original column number before the presolve was done. In get_origcol_name, column specifies the new column number after the presolve was done. If presolve is not active then both functions are equal.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column for which the name must be retrieved. Must be between 1 and the number of columns in the lp. In get_col_name, column specifies the original column number before the presolve was done. In get_origcol_name, column specifies the new column number after the presolve was done.

Remarks

The get_col_name and get_origcol_name functions return the name of the column.
Column names are optional. If no column name was specified, the function returns Cx with x the column number.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  char *name;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  name = get_col_name(lp, 1); /* will be C1 since no column name was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_col_name, set_row_name, get_row_name, get_origrow_name, get_nameindex


get_column

Get all column elements from the matrix.

unsigned char get_column(lprec *lp, int col_nr, REAL *column);

Return Value

get_column returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
An error occurs when col_nr is not between 1 and the number of columns in the lp.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

col_nr

Column number of the matrix. Must be between 1 and number of columns in the lp.

column

Array in which the values are returned. The array must be dimensioned with at least 1 plus number of rows elements in the lp.

Remarks

This function retrieves all values for the given column.
Element 0 of the column array will contain the value of the objective function, element 1 will contain the value for column 1, Element 2 the value for column 2, ...

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL column[1+2]; /* must be 1 greater than number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  get_column(lp, 1, column);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_mat, get_row, set_row, set_rowex, set_rh, set_rh_vec, str_set_rh_vec, add_constraint, add_constraintex, str_add_constraint, add_column, add_columnex, str_add_column, set_column, set_columnex


get_constr_type

Gets the type of a constraint.

int get_constr_type(lprec *lp, int row);

Return Value

get_constr_type returns the type of the constraint on row row. Can by any of the following values:

LE (1) | Less than or equal (<=)
EQ (3) | Equal (=)
GE (2) | Greater than or equal (>=)

If there is an error then the function returns -1.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the constraint type must be retrieved. Must be between 1 and number of rows in the lp.

Remarks

The get_constr_type function returns the constraint type for the specified row.
The default constraint type is LE.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int constr;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  constr = get_constr_type(lp, 1); /* will be 1 (LE) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_constr_type, set_constr_type, add_constraint, add_constraintex, str_add_constraint, del_constraint


get_constraints, get_ptr_constraints

Returns the values of the constraints.

unsigned char get_constraints(lprec *lp, REAL *constr);

unsigned char get_ptr_constraints(lprec *lp, REAL **ptr_constr);

Return Value

get_constraints, get_ptr_constraints returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

constr

An array that will contain the values of the constraints.

ptr_constr

The address of a pointer that will point to an array that will contain the values of the constraints.

Remarks

The get_constraints, get_ptr_constraints functions retrieve the values of the constraints.
These values are only valid after a successful solve or lag_solve. Function get_constraints needs an array that is already dimensioned with get_Nrows elements. get_ptr_constraints returns a pointer to an array already dimensioned by lp_solve. Element 0 will contain the value of the first row, element 1 of the second row, ...
Note that when set_presolve was called with parameter PRESOLVE_LINDEP that this can result in deletion of rows (the linear dependent ones). get_constraints, get_ptr_constraints will then return only the values of the rows that are kept and the values of the deleted rows are not known anymore.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL constr[2], *ptr_constr;

  /* Create a new LP model */
  lp = make_lp(2, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  get_constraints(lp, constr);
  get_ptr_constraints(lp, &ptr_constr);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex,


get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult

Returns the sensitivity of the constraints and the variables.

unsigned char get_sensitivity_rhs(lprec *lp, REAL *duals, REAL *dualsfrom, REAL *dualstill);

unsigned char get_ptr_sensitivity_rhs(lprec *lp, REAL **ptr_duals, REAL **ptr_dualsfrom, REAL **ptr_dualstill);

unsigned char get_dual_solution(lprec *lp, REAL *duals);

unsigned char get_ptr_dual_solution(lprec *lp, REAL **ptr_duals);

REAL get_var_dualresult(lprec *lp, int index);

Return Value

get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
get_var_dualresult returns the reduced cost.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

duals

An array that will contain the values of the dual variables aka reduced costs.

ptr_duals

The address of a pointer that will point to an array that will contain the values of the dual variables aka reduced costs.

dualsfrom

An array that will contain the values of the lower limits on the dual variables aka reduced costs.

ptr_dualsfrom

The address of a pointer that will point to an array that will contain the values of the lower limits of the dual variables aka reduced costs.

dualstill

An array that will contain the values of the upper limits on the dual variables aka reduced costs.

ptr_dualstill

The address of a pointer that will point to an array that will contain the values of the upper limits of the dual variables aka reduced costs.

index

The column of the variable for which the reduced cost is required. Note that this is the column number before presolve was done, if active. If index is 0, then the value of the objective function is returned by get_var_dualresult

Remarks

The get_sensitivity_rhs, get_ptr_sensitivity_rhs functions return the values of the dual variables aka reduced costs and their limits.
The get_dual_solution, get_ptr_dual_solution, get_var_dualresult functions return only the value(s) of the dual variables aka reduced costs.
These values are only valid after a successful solve and if there are integer variables in the model then only if set_presolve is called before solve with parameter PRESOLVE_SENSDUALS.
Function get_sensitivity_rhs needs an array that is already dimensioned with get_Nrows+get_Ncolumns elements.
Function get_dual_solution needs an array that is already dimensioned with 1+get_Nrows+get_Ncolumns elements.
get_ptr_sensitivity_rhs and get_ptr_dual_solution return a pointer to an array already dimensioned by lp_solve.
For functions get_sensitivity_rhs and get_ptr_sensitivity_rhs, Element 0 will contain the value of the first row, element 1 of the second row, ... Element get_Nrows contains the value for the first variable, element get_Nrows+1 the value for the second variable and so on.
For functions get_dual_solution and get_ptr_dual_solution the index starts from 1 and element 0 is not used.
The dual values or reduced costs values indicate that the objective function will change with the value of the reduced cost if the restriction is changed with 1 unit. There will only be a reduced cost if the value is bounded by the restriction, else it is zero. Note that the sign indicates if the objective function will increase or decrease. The reduced costs remains constant as long as the restriction stays within the lower/upper range also provided with these functions (dualsfrom, dualstill). If there is no reduced cost, or no lower/upper limit, then these values are (-)infinity.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL duals[1+2], dualsfrom[1+2], dualstill[1+2], *ptr_duals, *ptr_dualsfrom, *ptr_dualstill;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  str_set_obj_fn(lp, "1 1");
  str_add_constraint(lp, "2 4", GE, 10);
  set_lowbo(lp, 1, 1);

  solve(lp);

  get_sensitivity_rhs(lp, duals, dualsfrom, dualstill);
  get_ptr_sensitivity_rhs(lp, &ptr_duals, &ptr_dualsfrom, &ptr_dualstill);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex,


get_epsb

Returns the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.

REAL get_epsb(lprec *lp);

Return Value

get_epsb returns the value of epsb.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epsb function returns the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.
The default value for epsb is 1e-10

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsb;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsb = get_epsb(lp); /* will return 1e-10 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsb, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap


get_epsd

Returns the value that is used as a tolerance for the reduced costs to determine whether a value should be considered as 0.

REAL get_epsd(lprec *lp);

Return Value

get_epsd returns the value of epsd.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epsd function returns the value that is used as a tolerance for the reduced costs to determine whether a value should be considered as 0.
The default value for epsd is 1e-9

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsd;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsd = get_epsd(lp); /* will return 1e-9 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsd, set_infinite, is_infinite, get_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap


get_epsel

Returns the value that is used as a tolerance for rounding values to zero.

REAL get_epsel(lprec *lp);

Return Value

get_epsel returns the value of epsel.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epsel function returns the value that is used for rounding values to zero.
epsel is used on all other places where epsint, epsb, epsd, epspivot, epsperturb are not used.
The default value for epsel is 1e-12

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsel;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsel = get_epsel(lp); /* will return 1e-12 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsel, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsb, get_epsb, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap


get_epsint

Returns the tolerance that is used to determine whether a floating-point number is in fact an integer.

REAL get_epsint(lprec *lp);

Return Value

get_epsint returns the value of epsint.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epsint function returns the tolerance that is used to determine whether a floating-point number is in fact an integer.
The default value for epsint is 1e-7

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsint;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsint = get_epsint(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsint, set_infinite, is_infinite, get_infinite, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb


get_epsperturb

Returns the value that is used as perturbation scalar for degenerative problems.

REAL get_epsperturb(lprec *lp);

Return Value

get_epsperturb returns the perturbation scalar.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The default epsperturb value is 1e-5

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsperturb;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsperturb = get_epsperturb(lp); /* Returns 1e-5 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsperturb, set_infinite, get_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_mip_gap, get_mip_gap


get_epspivot

Returns epspivot.

REAL get_epspivot(lprec *lp);

Return Value

get_epspivot returns the value of epspivot.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epspivot function returns the value that is used as a tolerance for the pivot element to determine whether a value should be considered as 0.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epspivot specifies the tolerance to determine if a pivot element should be considered as 0. If abs(value) is less than this epspivot value it is considered as 0 and at first instance rejected as pivot element. Only when no larger other pivot element can be found and the value is different from 0 it will be used as pivot element.
The default epspivot value is 2e-7

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epspivot;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epspivot = get_epspivot(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epspivot, set_infinite, get_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epsperturb, set_epsperturb, set_mip_gap, get_mip_gap


get_improve

Returns the iterative improvement level.

int get_improve(lprec *lp);

Return Value

get_improve returns the iterative improvement level. Can by any of the following values:

IMPROVE_NONE (0) | improve none
IMPROVE_FTRAN (1) | improve FTRAN. Should not be used. Experimantal, buggy and slower.
IMPROVE_BTRAN (2) | improve BTRAN. Should not be used. Experimantal, buggy and slower.
IMPROVE_SOLVE (3) | improve FTRAN + BTRAN. Should not be used. Experimantal, buggy and slower.
IMPROVE_INVERSE (4) | Triggers automatic inverse accuracy control in the dual simplex, and when an error gap is exceeded the basis is reinverted

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

improve

Remarks

The get_improve function returns the iterative improvement level.
The default is IMPROVE_NONE.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int improve;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  improve = get_improve(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_improve


get_infinite

Returns the value of "infinite".

REAL get_infinite(lprec *lp);

Return Value

get_infinite returns the value of "infinite".

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_infinite function returns the practical value for "infinite". This value is used for very big numbers. For example the upper bound of a variable without an upper bound.
The default is 1e30

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL infinite;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  infinite = get_infinite(lp); /* will return 1.0e30 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_infinite, is_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb


get_lambda, get_ptr_lambda

Returns the Lamdba vectors (Lagrangian optimization).

unsigned char get_lambda(lprec *lp, REAL *lambda);

unsigned char get_ptr_lambda(lprec *lp, REAL **ptr_lambda);

Return Value

get_lambda, get_ptr_lambda returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

lambda

An array that will contain the values of the Lamdba vectors.

ptr_lambda

The address of a pointer that will point to an array that will contain the values of the Lamdba vectors.

Remarks

The get_lambda, get_ptr_lambda functions retrieve the Lamdba vectors.
These values are only valid after a successful lag_solve. Function get_lambda needs an array that is already dimensioned with get_Lrows elements. get_ptr_lambda returns a pointer to an array already dimensioned by lp_solve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;
  REAL row[1+2]; /* must be 1 more then number of columns ! */
  REAL *ptr_lambda, lambda[1];

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 1.0;
  add_lag_con(lp, row, LE, 1.0);

  ret = lag_solve(lp, 0, 30, FALSE);

  get_lambda(lp, lambda);
  get_ptr_lambda(lp, &ptr_lambda);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex, get_constraints, get_ptr_constraints, lag_solve


get_lowbo

Gets the lower bound of a variable.

REAL get_lowbo(lprec *lp, int column);

Return Value

get_lowbo returns the lower bound on the specified variable. If no bound was set, it returns 0, the default lower bound.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable. It must be between 1 and the number of columns in the lp.

Remarks

The get_lowbo function returns the lower bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
Note that the default lower bound of each variable is 0. So variables will never take negative values if no negative lower bound is set.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_lowbo(lp, 1); /* will return 0 since no lower bound was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_lowbo, set_upbo, get_upbo, set_bounds, set_free, is_free, is_negative


get_lp_index

Returns the index in the lp of the original row/column.

int get_lp_index(lprec *lp, int orig_index);

Return Value

get_lp_index returns the index in the lp of the original row/column.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

orig_index

Original constraint or column number. If orig_index is between 1 and get_Norig_rows then the index is a constraint (row) number. If orig_index is between 1 + get_Norig_rows and get_Norig_rows + get_Norig_columns then the index is a column number.

Remarks

The get_lp_index function returns the index in the lp of the original row/column.
Note that the number of constraints (get_Nrows) and columns (get_Ncolumns) can change when a presolve is done or when negative variables are split in a positive and a negative part. get_lp_index returns the position of the constraint/variable in the lp. If orig_index is not a legal index or the constraint/column is deleted, the return value is 0.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int index;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  str_add_constraint(lp, "0 1", LE, 1.0);

  index = get_lp_index(lp, 1); /* Will return 1 */

  set_presolve(lp, PRESOLVE_COLS);
  solve(lp);

  index = get_lp_index(lp, 1); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_orig_index, get_Ncolumns, get_Norig_columns, get_Nrows, get_Norig_rows, get_Lrows, set_presolve


get_lp_name

Gets the name of the lp.

char *get_lp_name(lprec *lp);

Return Value

get_lp_name returns the name of the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_lp_name returns the name of the lp.
Giving the lp a name is optional. The default name is "Unnamed".

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  char *name;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  name = get_lp_name(lp); /* will be "Unnamed" since no name was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_lp_name


get_Lrows

Returns the number of Lagrangian rows in the lp.

int get_Lrows(lprec *lp);

Return Value

get_Lrows returns the number of Lagrangian rows in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Lrows function returns the number of Lagrangian rows in the lp.
A Lagrangian row is added via add_lag_con.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2];
  int Lrows;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 1.0;
  add_lag_con(lp, row, LE, 1.0);

  Lrows = get_Lrows(lp); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Nrows, get_Norig_rows, get_Ncolumns, get_Norig_columns, get_orig_index, get_lp_index, add_lag_con, lag_solve


get_mat

Get a single element from the matrix.

REAL get_mat(lprec *lp, int row, int column);

Return Value

get_mat returns the value of the element on row row, column column. If no value was set for this element, the function returns 0.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

Row number of the matrix. Must be between 0 and number of rows in the lp. Row 0 is objective function.

column

Column number of the matrix. Must be between 1 and number of columns in the lp.

Remarks

This function is not efficient if many values are to be retrieved. Consider to use get_row, get_column.
If row and/or column are outside the allowed range, the function returns 0.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(2, 3);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_mat(lp, 1, 2); /* will return 0 because this element isn't created */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_row, get_column, set_column, set_columnex, set_mat, set_row, set_rowex


get_max_level

Returns the deepest Branch-and-bound level of the last solution.

int get_max_level(lprec *lp);

Return Value

get_max_level returns the deepest Branch-and-bound level of the last solution.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_max_level function returns the deepest Branch-and-bound level of the last solution.
Is only applicable if the model contains integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int max_level;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  max_level = get_max_level(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI get_total_nodes, get_total_iter


get_maxpivot

Returns the maximum number of pivots between a re-inversion of the matrix.

int get_maxpivot(lprec *lp);

Return Value

get_maxpivot returns the maximum number of pivots between a re-inversion of the matrix.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_maxpivot function returns the maximum number of pivots between a re-inversion of the matrix.
For stability reasons, lp_solve re-inverts the matrix on regular times. max_num_inv determines how frequently this inversion is done. This can influence numerical stability. However, the more often this is done, the slower the solver becomes.
The default is 42.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int max_num_inv;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  max_num_inv = get_maxpivot(lp); /* Will return 42 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_max_num_inv


get_mip_gap

Returns the MIP gap value.

REAL get_mip_gap(lprec *lp, unsigned char absolute);

Return Value

get_mip_gap returns the MIP gap value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

absolute

If TRUE then the absolute MIP gap is returned, else the relative MIP gap.

Remarks

The get_mip_gap function returns the MIP gap that specifies a tolerance for the branch and bound algorithm. This tolerance is the difference between the best-found solution yet and the current solution. If the difference is smaller than this tolerance then the solution (and all the sub-solutions) is rejected. This can result in faster solving times, but results in a solution which is not the perfect solution. So be careful with this tolerance.
The default mip_gap value is 1e-9

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL mip_gap;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  mip_gap = get_mip_gap(lp, TRUE); /* Will return 1e-9 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_mip_gap, get_epsd, set_epsd, set_infinite, get_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb


get_nameindex

Gets the index of a given column or row name in the lp.

int get_nameindex(lprec *lp, char *name, MYBOOL isrow);

Return Value

get_nameindex returns the index (column/row number) of the given column/row name. A return value of -1 indicates that the name does not exist.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

name

The name of the column or row for which the index (column/row number) must be retrieved.

isrow

Set to FALSE (0) if column information is needed and TRUE (1) if row information is needed.

Remarks

The get_nameindex function returns the index (column/row number) of the given column/row name.
This routine is new from version 5.1.1.1.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int column;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_row_name(lp, 1, "col1");

  column = get_nameindex(lp, "col1", TRUE); /* will return 1 */
  column = get_nameindex(lp, "col", TRUE); /* will return -1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_row_name, get_row_name, get_origrow_name, set_col_name, get_col_name, get_origcol_name


get_Ncolumns

Returns the number of columns (variables) in the lp.

int get_Ncolumns(lprec *lp);

Return Value

get_Ncolumns returns the number of columns (variables) in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Ncolumns function returns the number of columns (variables) in the lp.
Note that the number of columns can change when a presolve is done or when negative variables are split in a positive and a negative part.
Therefore it is advisable to use this function to determine how many columns there are in the lp instead of relying on an own count.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int Ncolumns;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  Ncolumns = get_Ncolumns(lp); /* Will return 1 */

  set_presolve(lp, PRESOLVE_COLS);
  solve(lp);

  Ncolumns = get_Ncolumns(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Norig_columns, get_Nrows, get_Norig_rows, get_orig_index, get_lp_index, get_Lrows


get_negrange

Returns the negative value below which variables are split into a negative and a positive part.

REAL get_negrange(lprec *lp);

Return Value

get_negrange returns the negative value below which variables are split into a negative and a positive part.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_negrange function returns the negative value below which variables are split into a negative and a positive part. This value is always zero or negative.
In some cases, negative variables must be split in a positive part and a negative part. This is when a negative lower or upper bound is set on a variable. If a bound is less than this value, it is possibly split. The default is -1e6.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL negrange;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  negrange = get_negrange(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_negrange


get_nonzeros

Returns the number of non-zero elements in the matrix.

int get_nonzeros(lprec *lp);

Return Value

get_nonzeros returns the number of non-zero elements in the matrix.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_nonzeros function returns the number of non-zeros in the matrix.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int nonzeros;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  nonzeros = get_nonzeros(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI


get_Norig_columns

Returns the number of original columns (variables) in the lp.

int get_Norig_columns(lprec *lp);

Return Value

get_Norig_columns returns the number of original columns (variables) in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Norig_columns function returns the number of original columns (variables) in the lp.
Note that the number of columns (get_Ncolumns) can change when a presolve is done or when negative variables are split in a positive and a negative part. get_Norig_columns does not change and thus returns the original number of columns in the lp.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int Norig_columns;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  Norig_columns = get_Norig_columns(lp); /* Will return 1 */

  set_presolve(lp, PRESOLVE_COLS);
  solve(lp);

  Norig_columns = get_Norig_columns(lp); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Ncolumns, get_Nrows, get_Norig_rows, get_orig_index, get_lp_index, get_Lrows


get_Norig_rows

Returns the number of original rows (constraints) in the lp.

int get_Norig_rows(lprec *lp);

Return Value

get_Norig_rows returns the number of original rows (constraints) in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Norig_rows function returns the number of original rows (constraints) in the lp.
Note that the number of rows (get_Nrows) can change when a presolve is done. get_Norig_rows does not change and thus returns the original number of rows in the lp.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int Norig_rows;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  Norig_rows = get_Norig_rows(lp); /* Will return 1 */

  set_presolve(lp, PRESOLVE_ROWS);
  solve(lp);

  Norig_rows = get_Norig_rows(lp); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Nrows, get_Lrows, get_Ncolumns, get_Norig_columns, get_orig_index, get_lp_index


get_Nrows

Returns the number of rows (constraints) in the lp.

int get_Nrows(lprec *lp);

Return Value

get_Nrows returns the number of rows (constraints) in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Nrows function returns the number of rows (constraints) in the lp.
Note that the number of rows can change when a presolve is done.
Therefore it is advisable to use this function to determine how many rows there are in the lp instead of relying on an own count.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int Nrows;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  Nrows = get_Nrows(lp); /* Will return 1 */

  set_presolve(lp, PRESOLVE_ROWS);
  solve(lp);

  Nrows = get_Nrows(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Norig_rows, get_Lrows, get_Ncolumns, get_Norig_columns, get_orig_index, get_lp_index


get_obj_bound

Returns initial "at least better than" guess for objective function.

REAL get_obj_bound(lprec *lp);

Return Value

get_obj_bound returns the initial "at least better than" guess for objective function.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_obj_bound function returns the initial "at least better than" guess for objective function. This is only used in the branch-and-bound algorithm when integer variables exist in the model. All solutions with a worse objective value than this value are immediately rejected. This can result in faster solving times, but it can be difficult to predict what value to take for this bound. Also there is the chance that the found solution is not the most optimal one.
The default is infinite.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL obj_bound;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  obj_bound = get_obj_bound(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_obj_bound, set_break_at_value, get_break_at_value, set_mip_gap, get_mip_gap


get_objective

Returns the value of the objective function.

REAL get_objective(lprec *lp);

Return Value

get_objective returns the value of the objective.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_objective function returns the value of the objective of the last solve.
This value is only valid after a successful solve or lag_solve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL obj;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  obj = get_objective(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_variables, get_ptr_variables, get_working_objective, get_constraints, get_ptr_constraints, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex


get_orig_index

Returns the original row/column where a constraint/variable was before presolve.

int get_orig_index(lprec *lp, int lp_index);

Return Value

get_orig_index returns the original row/column where a constraint/variable was before presolve.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

lp_index

constraint or column number. If lp_index is between 1 and get_Nrows then the index is a constraint (row) number. If lp_index is between 1 + get_Nrows and get_Nrows + get_Ncolumns then the index is a column number.

Remarks

The get_orig_index function returns the original row/column where a constraint/variable was before presolve.
Note that the number of constraints (get_Nrows) and columns (get_Ncolumns) can change when a presolve is done or when negative variables are split in a positive and a negative part. get_orig_index returns the original position of the constraint/variable. If lp_index is not a legal index, the return value is 0.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int index;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  index = get_orig_index(lp, 1); /* Will return 1 */

  set_presolve(lp, PRESOLVE_COLS);
  solve(lp);

  index = get_orig_index(lp, 1); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_lp_index, get_Ncolumns, get_Norig_columns, get_Nrows, get_Norig_rows, get_Lrows, get_lp_index


get_row_name, get_origrow_name

Gets the name of a constraint (row) in the lp.

char *get_row_name(lprec *lp, int row);

char *get_origrow_name(lprec *lp, int row);

Return Value

get_row_name and get_origrow_name return the name of the specified row. A return value of NULL indicates an error. The difference between get_row_name and get_origrow_name is only when a presolve (set_presolve) was done. Presolve can result in deletion of rows in the model. In get_row_name, row specifies the original row number before the presolve was done. In get_origrow_name, column specifies the new row number after the presolve was done. If presolve is not active then both functions are equal.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the name must be retrieved. Must be between 0 and the number of rows in the lp. In get_row_name, row specifies the original row number before the presolve was done. In get_origrow_name, column specifies the new row number after the presolve was done.

Remarks

The get_row_name and get_origrow_name functions return the name of the row.
Row names are optional. If no row name was specified, the function returns Rx with x the row number. row 0 is the objective function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  char *name;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  name = get_row_name(lp, 1); /* will be R1 since no row name was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_row_name, set_col_name, get_col_name, get_origcol_name, get_nameindex


get_pivoting

Returns the pivot rule and mode.

int get_pivoting(lprec *lp);

Return Value

get_pivoting returns the pivot rule and mode. Can be one of the following rules:

PRICER_FIRSTINDEX (0) | Select first
PRICER_DANTZIG (1) | Select according to Dantzig
PRICER_DEVEX (2) | Devex pricing from Paula Harris
PRICER_STEEPESTEDGE (3) | Steepest Edge

Some of these values can be combined with any (ORed) of the following modes:

PRICE_PRIMALFALLBACK (4) | In case of Steepest Edge, fall back to DEVEX in primal
PRICE_MULTIPLE (8) | Preliminary implementation of the multiple pricing scheme. This means that attractive candidate entering columns from one iteration may be used in the subsequent iteration, avoiding full updating of reduced costs. In the current implementation, lp_solve only reuses the 2nd best entering column alternative
PRICE_PARTIAL (16) | Enable partial pricing
PRICE_ADAPTIVE (32) | Temporarily use First Index if cycling is detected
PRICE_RANDOMIZE (128) | Adds a small randomization effect to the selected pricer
PRICE_LOOPLEFT (1024) | Scan entering/leaving columns left rather than right
PRICE_LOOPALTERNATE (2048) | Scan entering/leaving columns alternatingly left/right

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_pivoting function returns the pivot rule (rule for selecting row and column entering/leaving) and mode. The rule is an exclusive option and the mode is a modifier to the rule. This rule/mode can influence solving times considerably. Depending on the model one rule/mode can be best and for another model another rule/mode.
The default is PRICER_DEVEX | PRICE_ADAPTIVE (34).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int pivoting;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  pivoting = get_pivoting(lp); /* will return 18 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_piv_rule, set_pivoting, is_piv_mode


get_presolve

Returns if a presolve must be done before solving.

int get_presolve(lprec *lp);

Return Value

get_presolve returns the current presolve setting. Can by the combination (OR) of any of the following values:

PRESOLVE_NONE (0) | No presolve at all
PRESOLVE_ROWS (1) | Presolve rows
PRESOLVE_COLS (2) | Presolve columns
PRESOLVE_LINDEP (4) | Eliminate linearly dependent rows
PRESOLVE_SOS (32) | Convert constraints to SOSes (only SOS1 handled)
PRESOLVE_REDUCEMIP (64) | If the phase 1 solution process finds that a constraint is redundant then this constraint is deleted
PRESOLVE_DUALS (128) | Calculate duals
PRESOLVE_SENSDUALS (256) | Calculate sensitivity

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_presolve function returns if a presolve must be done before solving. Presolve looks at the model and tries to simplify it so that solving times are shorter. For example a constraint on only one variable is converted to a bound on this variable (and the constraint is deleted). Note that the model dimensions can change because of this, so be careful with this. Both rows and columns can be deleted by the presolve.
The default is not (PRESOLVE_NONE) doing a presolve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int presolve;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  presolve = get_presolve(lp); /* returns the current presolve level */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_presolve, is_presolve


get_primal_solution, get_ptr_primal_solution, get_var_primalresult

Returns the solution of the model.

unsigned char get_primal_solution(lprec *lp, REAL *pv);

unsigned char get_ptr_primal_solution(lprec *lp, REAL **ptr_pv);

REAL get_var_primalresult(lprec *lp, int index);

Return Value

get_primal_solution, get_ptr_primal_solution return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
get_var_primalresult returns the value for index.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

pv

An array that will contain the value of the objective function (element 0), values of the constraints (elements 1 till Nrows), and the values of the variables (elements Nrows+1 till Nrows+NColumns).

ptr_pv

The address of a pointer that will point to an array that will contain the value of the objective function (element 0), values of the constraints (elements 1 till Nrows), and the values of the variables (elements Nrows+1 till Nrows+NColumns).

index

index of the constraint/variable.

Remarks

The get_primal_solution, get_ptr_primal_solution, get_var_primalresult functions retrieve the values of the objective function, constraints and variables.
These values are only valid after a successful solve or lag_solve. Function get_primal_solution needs an array that is already dimensioned with 1 + get_Nrows + get_Ncolumns elements. get_ptr_primal_solution returns a pointer to an array already dimensioned by lp_solve. Element 0 is the value of the objective function, elements 1 till Nrows the values of the constraints and elements Nrows+1 till Nrows+NColumns the values of the variables. get_var_primalresult requires no array. index is the array element number of the above functions and returns the value for this array element.
Special considerations when presolve was done. When set_presolve is called before solve, then presolve can have deleted both rows and columns from the model because they could be eliminated. This influences get_primal_solution and get_ptr_primal_solution. These functions only report the values of the remaining variables and constraints. However get_var_primalresult returns all values, also the deleted ones by presolve. So index is the original index number as known by the caller.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL pv[1+2+3], *ptr_pv;

  /* Create a new LP model */
  lp = make_lp(3, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  get_primal_solution(lp, pv);
  get_ptr_primal_solution(lp, &ptr_pv);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex


get_print_sol

Returns a flag if all intermediate valid solutions must be printed while solving.

int get_print_sol(lprec *lp);

Return Value

get_print_sol returns the debug print status. Can by any of following values: Can be any of the following values:

FALSE (0) | No printing
TRUE (1) | Print all values
AUTOMATIC (2) | Print only non-zero values

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_print_sol function returns a flag if all intermediate valid solutions must be printed while solving. Can give you useful solutions even if the total run time is too long. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int doprint;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  doprint = get_print_sol(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_print_sol


get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

Returns the sensitivity of the objective function.

unsigned char get_sensitivity_obj(lprec *lp, REAL *objfrom, REAL *objtill);

unsigned char get_sensitivity_objex(lprec *lp, REAL *objfrom, REAL *objtill, REAL *objfromvalue, REAL *objtillvalue);

unsigned char get_ptr_sensitivity_obj(lprec *lp, REAL **ptr_objfrom, REAL **ptr_objtill);

unsigned char get_ptr_sensitivity_objex(lprec *lp, REAL **ptr_objfrom, REAL **ptr_objtill, REAL *ptr_objfromvalue, REAL *ptr_objtillvalue);

Return Value

get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

objfrom

An array that will contain the values of the lower limits on the objective function.

ptr_objfrom

The address of a pointer that will point to an array that will contain the values of the lower limits of the objective function.

objtill

An array that will contain the values of the upper limits of the objective function.

ptr_objtill

The address of a pointer that will point to an array that will contain the values of the upper limits of the objective function.

objfromvalue

An array that will contain the values of the variables at their lower limit. Only applicable when the value of the variable is 0 (rejected).

objtillvalue

Not used at this time.

ptr_objfromvalue

The address of a pointer that will point to an array that will contain the values of the variables at their lower limit. Only applicable when the value of the variable is 0 (rejected).

ptr_objtillvalue

Not used at this time.

Remarks

The get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex functions return the sensitivity of the objective function.
These values are only valid after a successful solve and if there are integer variables in the model then only if set_presolve is called before solve with parameter PRESOLVE_SENSDUALS. Functions get_sensitivity_obj, get_sensitivity_objex need arrays that are already dimensioned with get_Ncolumns elements. get_ptr_sensitivity_obj, get_ptr_sensitivity_objex returns a pointer to an array already dimensioned by lp_solve. Element 0 will contain the value of the first variable, element 1 of the second variable, ...
The meaning of these limits are the following. As long as the value of the coefficient of the objective function stays between the lower limit (objfrom) and the upper limit (objtill), the solution stays the same. Only the objective value itself changes with a value equal to the difference multiplied by the amount of this variable. If there is no lower/upper limit, then these values are (-)infinity.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL objfrom[1+2], objtill[1+2], *ptr_objfrom, *ptr_objtill;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  str_set_obj_fn(lp, "1 1");
  str_add_constraint(lp, "2 4", GE, 10);
  set_lowbo(lp, 1, 1);

  solve(lp);

  get_sensitivity_obj(lp, objfrom, objtill);
  get_ptr_sensitivity_obj(lp, &ptr_objfrom, &ptr_objtill);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs,


get_variables, get_ptr_variables

Returns the values of the variables.

unsigned char get_variables(lprec *lp, REAL *var);

unsigned char get_ptr_variables(lprec *lp, REAL **ptr_var);

Return Value

get_variables, get_ptr_variables returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

var

An array that will contain the values of the variables.

ptr_var

The address of a pointer that will point to an array that will contain the values of the variables.

Remarks

The get_variables, get_ptr_variables functions retrieve the values of the variables.
These values are only valid after a successful solve or lag_solve. Function get_variables needs an array that is already dimensioned with get_Ncolumns elements. get_ptr_variables returns a pointer to an array already dimensioned by lp_solve. Element 0 will contain the value of the first variable, element 1 of the second variable, ...

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL var[2], *ptr_var;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  get_variables(lp, var);
  get_ptr_variables(lp, &ptr_var);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_constraints, get_ptr_constraints, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex


get_rh

Gets the value of the right hand side (RHS) vector (column 0) for one row.

REAL get_rh(lprec *lp, int row);

Return Value

get_rh returns the value of the RHS for the specified row. If row is out of range it returns 0. If no previous value was set, then it also returns 0, the default RHS value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the RHS value must be retrieved. Must be between 0 and number of rows in the lp.

value

The value of the RHS.

Remarks

The get_rh function returns the value of the RHS vector (column 0) for the specified row.
Note that row can also be 0 with this function. In that case it returns the initial value of the objective function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_rh(lp, 1); /* will return 0 since no value was previously set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_rh, set_rh_vec, str_set_rh_vec, add_constraint, add_constraintex, str_add_constraint, get_column, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_row, get_mat


get_rh_range

Gets the range on a constraint.

REAL get_rh_range(lprec *lp, int row);

Return Value

get_rh_range returns the range set on the constraint specified by row.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row number of the constraint from which the range must be retrieved. It must be between 1 and the number of rows in the lp.

Remarks

The get_rh_range function gets the range on the constraint (row) identified by row.
Setting a range on a row is the way to go instead of adding an extra constraint (row) to the model. Setting a range doesn't increase the model size that means that the model stays smaller and will be solved faster.
If the row has a less than constraint then the range means setting a minimum on the constraint that is equal to the RHS value minus the range. If the row has a greater than constraint then the range means setting a maximum on the constraint that is equal to the RHS value plus the range.
Note that the range value is the difference value and not the absolute value.
If no range was set then get_rh_range returns a very big number, the value of get_infinite.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_rh_range(lp, 1);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_rh_range


get_row

Get all row elements from the matrix.

unsigned char get_row(lprec *lp, int row_nr, REAL *row);

Return Value

get_row returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
An error occurs when row_nr is not between 0 and the number of rows in the lp.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row_nr

Row number of the matrix. Must be between 0 and number of rows in the lp. Row 0 is objective function.

row

Array in which the values are returned. The array must be dimensioned with at least 1 plus number of columns elements in the lp.

Remarks

This function retrieves all values for the given row.
Element 0 of the row array is not filled. Element 1 will contain the value for column 1, Element 2 the value for column 2, ...

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2]; /* must be 1 greater than number of columns ! */

  /* Create a new LP model */
  lp = make_lp(1, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  get_row(lp, 1, row);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_row, set_rowex, get_mat, get_column, set_column, set_columnex, set_mat, set_rh, set_rh_vec, str_set_rh_vec, add_constraint, add_constraintex, str_add_constraint, add_column, add_columnex, str_add_column


get_scalelimit

Sets the relative scaling convergence criterion for the active scaling mode.

REAL get_scalelimit(lprec *lp);

Return Value

get_scalelimit returns the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

scalelimit

maximum number of iterations

Remarks

The get_scalelimit function the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations (default is 5).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL scalelimit;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  scalelimit = get_scalelimit(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scalelimit, set_scaling, get_scaling, is_integerscaling


get_scaling

Specifies which scaling algorithm is used.

int get_scaling(lprec *lp);

Return Value

get_scaling returns which scaling algorithm is used. Can by any of the following values:

SCALE_EXTREME (1) | Scale to convergence using largest absolute value
SCALE_RANGE (2) | Scale based on the simple numerical range
SCALE_MEAN (3) | Numerical range-based scaling
SCALE_GEOMETRIC (4) | Geometric scaling
SCALE_CURTISREID (7) | Curtis-reid scaling

Additionally, the value can be OR-ed with any combination of one of the following values:

SCALE_QUADRATIC (8) |
SCALE_LOGARITHMIC (16) | Scale to convergence using logarithmic mean of all values
SCALE_USERWEIGHT (31) | User can specify scalars
SCALE_POWER2 (32) | also do Power scaling
SCALE_EQUILIBRATE (64) | Make sure that no scaled number is above 1
SCALE_INTEGERS (128) | also scaling integer variables
SCALE_DYNUPDATE (256) | dynamic update

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_scaling function returns which scaling algorithm is used. This can influence numerical stability considerably. It is advisable to always use some sort of scaling.
set_scaling must be called before solve is called.
SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC, SCALE_CURTISREID are the possible scaling algorithms. SCALE_QUADRATIC, SCALE_LOGARITHMIC, SCALE_USERWEIGHT, SCALE_POWER2, SCALE_EQUILIBRATE, SCALE_INTEGERS are possible additional scaling parameters.
SCALE_POWER2 results in creating a scalar of power 2. May improve stability.
SCALE_INTEGERS results also in scaling Integer columns. Default they are not scaled.
SCALE_DYNUPDATE is new from version 5.1.1.0
It has always been so that scaling is done only once on the original model. If a solve is done again (most probably after changing some data in the model), the scaling factors aren't computed again. The scalars of the original model are used. This is not always good, especially if the data has changed considerably. One way to solve this was/is call unscale before a next solve. In that case, scale factors are recomputed.
From version 5.1.1.0 on, there is another way to make sure that scaling factors are recomputed and this is by settings SCALE_DYNUPDATE. In that case, the scaling factors are recomputed also when a restart is done. Note that they are then always recalculated with each solve, even when no change was made to the model, or a change that doesn't influence the scaling factors like changing the RHS (Right Hand Side) values or the bounds/ranges. This can influence performance. It is up to you to decide if scaling factors must be recomputed or not for a new solve, but by default it still isn't so. It is possible to set/unset this flag at each next solve and it is even allowed to choose a new scaling algorithm between each solve. Note that the scaling done by the SCALE_DYNUPDATE is incremental and the resulting scalars are typically different from scalars recomputed from scratch.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int scalemode;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  scalemode = get_scaling(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scaling, set_scalelimit, get_scalelimit, is_integerscaling, is_scalemode, is_scaletype


get_simplextype

Returns the desired combination of primal and dual simplex algorithms.

int get_simplextype(lprec *lp);

Return Value

get_simplextype returns the desired combination of primal and dual simplex algorithms.
Can be any of the following values:

SIMPLEX_PRIMAL_PRIMAL (5) | Phase1 Primal, Phase2 Primal
SIMPLEX_DUAL_PRIMAL (6) | Phase1 Dual, Phase2 Primal
SIMPLEX_PRIMAL_DUAL (9) | Phase1 Primal, Phase2 Dual
SIMPLEX_DUAL_DUAL (10) | Phase1 Dual, Phase2 Dual

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_simplextype function returns the desired combination of primal and dual simplex algorithms. The default is SIMPLEX_DUAL_PRIMAL (6).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int primal_dual;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  primal_dual = get_simplextype(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_simplextype, set_preferdual


get_solutioncount

Returns the number of equal solutions.

int get_solutioncount(lprec *lp);

Return Value

get_solutioncount returns the number of equal solutions. This is only valid if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algoritm is used. This count gives the number of solutions with the same optimal objective value. If there is only one optimal solution, this value is 1.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_solutioncount function returns the number of equal solutions up to get_solutionlimit.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int solutioncount;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  solutioncount = get_solutioncount(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_solutionlimit, set_solutionlimit


get_solutionlimit

Returns the solution number that must be returned.

int get_solutionlimit(lprec *lp);

Return Value

get_solutionlimit returns the solution number that must be returned. This value gives the number of the solution that must be returned.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

This is only valid if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algoritm is used. If there are more solutions with the same objective value, then this number specifies which solution must be returned. This can be used to retrieve all possible solutions. Start with 1 till get_solutioncount

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int solutionlimit;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  solutionlimit = get_solutionlimit(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_solutionlimit, get_solutioncount


get_status

Returns an extra status after a call to a function.

int get_status(lprec *lp);

Return Value

Extra status which indicates type of problem after call to function.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_status function returns an extra status after a call to a function. Some functions return FALSE when they have failed. To have more information on the reason of the failure, this routine can be used to get an extended error code.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int spx_status;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  spx_status = get_status(lp);

  return(0);
}

lp_solve API reference

See Also free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI


get_statustext

Returns the description of a returncode of the solve function.

char *get_statustext(lprec *lp, int statuscode);

Return Value

The description of a returncode of the solve function

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

statuscode

Returncode of solve

Remarks

The get_statustext function returns a comprehensible description of a returncode of the solve function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  ret = solve(lp);

  printf("%s\n", get_statustext(lp, ret));
  return(0);
}

lp_solve API reference

See Also free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, solve


get_timeout

Gets the timeout.

long get_timeout(lprec *lp);

Return Value

get_timeout returns the number of seconds after which a timeout occurs.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_timeout function returns a timeout in seconds. The solve and lag_solve functions may not last longer than this time or the routines return with a timeout. There is no valid solution at this time. The default timeout is 0, resulting in no timeout.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  long timeout;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  timeout = get_timeout(lp); /* will return 0 since no timeout was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_timeout, time_elapsed, solve, lag_solve


get_total_iter

Returns the total number of iterations with Branch-and-bound of the last solution.

int get_total_iter(lprec *lp);

Return Value

get_total_iter returns the total number of iterations with Branch-and-bound of the last solution.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_total_iter function returns the total number of iterations with Branch-and-bound of the last solution.
Is only applicable if the model contains integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int total_iter;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  total_iter = get_total_iter(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_max_level, get_total_nodes


get_total_nodes

Returns the total number of nodes processed in branch-and-bound.

int get_total_nodes(lprec *lp);

Return Value

get_total_nodes returns the total number of nodes processed in branch-and-bound of the last solution.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_total_nodes function returns the total number of nodes processed in branch-and-bound of the last solution.
Is only applicable if the model contains integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int total_nodes;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  total_nodes = get_total_nodes(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_max_level, get_total_iter


get_upbo

Gets the upper bound of a variable.

REAL get_upbo(lprec *lp, int column);

Return Value

get_upbo returns the upper bound on the specified variable. If no bound was set, it returns a very big number, the value of get_infinite, the default upper bound.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable. It must be between 1 and the number of columns in the lp.

Remarks

The get_upbo function returns the upper bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
The default upper bound of a variable is infinity (well not quite. It is a very big number. The value of get_infinite).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_upbo(lp, 1); /* will return 1e30 since no upper bound was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_upbo, set_lowbo, get_lowbo, set_bounds, set_free, is_free, is_negative


get_var_branch

Returns, for the specified variable, which branch to take first in branch-and-bound algorithm.

int get_var_branch(lprec *lp, int column);

Return Value

get_var_branch returns which branch to take first in branch-and-bound algorithm.

Can by any of the following values:

BRANCH_CEILING (0) | Take ceiling branch first
BRANCH_FLOOR (1) | Take floor branch first
BRANCH_AUTOMATIC (2) | Algorithm decides which branch being taken first

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the mode must be returned. It must be between 1 and the number of columns in the lp. If it is not within this range, the return value is the value of get_bb_floorfirst

Remarks

The get_var_branch function returns which branch to take first in branch-and-bound algorithm. This can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
When no value was set via set_var_branch, the return value is the value of get_bb_floorfirst. It also returns the value of get_bb_floorfirst when set_var_branch was called with branch mode BRANCH_DEFAULT (3).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int branch_mode;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  branch_mode = get_var_branch(lp, 1); /* will return BRANCH_FLOOR (1), the default branch mode */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_var_branch, set_bb_floorfirst, get_bb_floorfirst, set_var_weights, get_var_priority


get_var_priority

Returns, for the specified variable, the priority the variable has in the branch-and-bound algorithm.

int get_var_priority(lprec *lp, int column);

Return Value

get_var_priority returns the priority of the variable.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the priority must be returned. It must be between 1 and the number of columns in the lp. If it is not within this range, the return value is 0

Remarks

The get_var_priority function returns the priority the variable has in the branch-and-bound algorithm. This priority is determined by the weights set by set_var_weights. The default priorities are the column positions of the variables in the model.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL weights[2];
  int priority;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  weights[0] = 2;
  weights[1] = 1;

  set_var_weights(lp, weights);

  priority = get_var_priority(lp, 1); /* will return 2 */
  priority = get_var_priority(lp, 2); /* will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_var_weights, get_var_branch, set_var_branch, set_bb_floorfirst, get_bb_floorfirst


get_verbose

Returns the verbose level.

int get_verbose(lprec *lp);

Return Value

get_verbose returns the current verbose level. Can be one of the following values:

NEUTRAL (0) | Only some specific debug messages in de debug print routines are reported.
CRITICAL (1) | Only critical messages are reported. Hard errors like instability, out of memory, ...
SEVERE (2) | Only severe messages are reported. Errors.
IMPORTANT (3) | Only important messages are reported. Warnings and Errors.
NORMAL (4) | Normal messages are reported. This is the default.
DETAILED (5) | Detailed messages are reported. Like model size, continuing B&B improvements, ...
FULL (6) | All messages are reported. Usefull for debugging purposes and small models.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_verbose function returns the verbose level.
lp_solve reports information back to the user. How much information is reported depends on the verbose level. The default verbose level is NORMAL. lp_solve determines how verbose a given message is. For example specifying a wrong row/column index values is considered as a SEVERE error. verbose determines how much of the lp_solve message are reported. All messages equal to and below the set level are reported.
The default reporting device is the console screen. It is possible to set a used defined reporting routine via put_logfunc.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int verbose;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  verbose = get_verbose(lp); /* Will return 4 (NORMAL) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_verbose, put_logfunc


get_working_objective

Returns the value of the objective function.

REAL get_working_objective(lprec *lp);

Return Value

get_working_objective returns the current value of the objective while solving the model.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_working_objective function returns the current value of the objective while solving the model.
This value can be retrieved while solving in a callback function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int msgfunction(lprec *lp, void *userhandle, char *buf)
{

 printf("%f\n", get_working_objective(lp));

 return(0);
}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_msgfunc(lp, msgfunction, NULL, 0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_working_objective, is_feasible, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex


has_BFP

Returns if there is a basis factorization package (BFP) available.

unsigned char has_BFP(lprec *lp);

Return Value

has_BFP returns TRUE if there is a BFP available, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

There should always be a BFP available, else lpsolve can not solve. Normally lpsolve is compiled with a default BFP. See Basis Factorization Packages for a complete description on BFPs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char hasBFP;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  hasBFP = has_BFP(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_nativeBFP, set_BFP


has_XLI

Returns if there is an external language interface (XLI) set.

unsigned char has_XLI(lprec *lp);

Return Value

has_XLI returns TRUE if there is an XLI set, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char hasXLI;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  hasXLI = has_XLI(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_XLI, is_nativeXLI, set_XLI


is_add_rowmode

Returns a flag which of the add routines perform best.

unsigned char is_add_rowmode(lprec *lp);

Return Value

is_add_rowmode returns TRUE or FALSE. If FALSE, then add_column, add_columnex, str_add_column performs best. If TRUE, then add_constraint, add_constraintex, str_add_constraint performs best.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

Default, this is FALSE, meaning that add_column, add_columnex, str_add_column performs best. If the model is build via add_constraint, add_constraintex, str_add_constraint calls, then these routines will be much faster if this routine is called with turnon set on TRUE. This is also called row entry mode. The speed improvement is spectacular, especially for bigger models, so it is advisable to call this routine to set the mode. Normally a model is build either column by column or row by row.
Note that there are several restrictions with this mode:
Only use this function after a make_lp call. Not when the model is read from file. Also, if this function is used, first add the objective function via set_obj_fn, set_obj_fnex, str_set_obj_fn and after that add the constraints via add_constraint, add_constraintex, str_add_constraint. Don't call other API functions while in row entry mode. No other data matrix access is allowed while in row entry mode. After adding the contraints, turn row entry mode back off. Once turned of, you cannot switch back to row entry mode. So in short:
- turn row entry mode on
- set the objective function
- create the constraints
- turn row entry mode off

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char rowmode;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  rowmode = is_add_rowmode(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_add_rowmode, set_add_rowmode, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, add_column, add_columnex, str_add_column, add_constraint, add_constraintex, str_add_constraint


is_anti_degen

Returns if the degeneracy rule specified in testmask is active.

unsigned char is_anti_degen(lprec *lp, int testmask);

Return Value

is_anti_degen returns TRUE or FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

testmask

ANTIDEGEN_NONE (0) | No anti-degeneracy handling
ANTIDEGEN_FIXEDVARS (1) | Check if there are equality slacks in the basis and try to drive them out in order to reduce chance of degeneracy in Phase 1
ANTIDEGEN_COLUMNCHECK (2) |
ANTIDEGEN_STALLING (4) |
ANTIDEGEN_NUMFAILURE (8) |
ANTIDEGEN_LOSTFEAS (16) |
ANTIDEGEN_INFEASIBLE (32) |
ANTIDEGEN_DYNAMIC (64) |
ANTIDEGEN_DURINGBB (128) |

Remarks

The is_anti_degen function returns a flag if the degeneracy rule specified in testmask is active.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char anti_degen;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  anti_degen = is_anti_degen(lp, ANTIDEGEN_FIXEDVARS | ANTIDEGEN_PERTURB); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_anti_degen, get_anti_degen


is_binary

Gets the type of the variable. Binary integer or floating point.

unsigned char is_binary(lprec *lp, int column);

Return Value

is_binary returns TRUE (1) if the variable is set as binary, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_binary function returns if a variable must be binary or not. Default a variable is not binary. A binary variable is an integer variable with lower bound 0 and upper bound 1. From the moment there is at least one integer variable in the model, the Branch and Bound algorithm is used to make these variables integer. Note that solving times can be considerably larger when there are integer variables. See integer variables for a description about integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int binary;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  binary = is_binary(lp, 1); /* will return 0 since the variable is not set as binary at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_binary, is_int, set_int


is_break_at_first

Returns if the branch-and-bound algorithm stops at first found solution.

unsigned char is_break_at_first(lprec *lp);

Return Value

is_break_at_first returns if the branch-and-bound algorithm stops at first found solution.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_break_at_first function returns if the branch-and-bound algorithm stops at the first found solution or not. Stopping at the first found solution can be useful if you are only interested for a solution, but not necessarily (and most probably) the most optimal solution.
The default is not (FALSE) stop at first found solution.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char break_at_first;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  break_at_first = is_break_at_first(lp); /* Will return 0 (FALSE) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_break_at_first, set_break_at_value, get_break_at_value, set_obj_bound, get_obj_bound, set_mip_gap, get_mip_gap


is_constr_type

Returns if constraint type specified in mask is active.

unsigned char is_constr_type(lprec *lp, int row, int mask);

Return Value

is_constr_type returns TRUE or FALSE

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the constraint type must be retrieved. Must be between 1 and number of rows in the lp.

mask

Any of the following values:
LE (1) | Less than or equal (<=)
EQ (3) | Equal (=)
GE (2) | Greater than or equal (>=)

Remarks

The is_constr_type function returns a flag if constraint type specified in mask is active.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char constr;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  constr = is_constr_type(lp, 1, LE); /* will be TRUE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_constr_type, set_constr_type, add_constraint, add_constraintex, str_add_constraint, del_constraint


is_debug

Returns a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.

unsigned char is_debug(lprec *lp);

Return Value

is_debug returns TRUE or FALSE. Debug or do not debug.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_debug function returns a flag if all intermediate results and the branch-and-bound decisions must be printed while solving. This function is mend for debugging purposes. The default is not to debug (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char dodebug;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  dodebug = is_debug(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_debug


is_feasible

Checks if provided solution is a feasible solution.

unsigned char is_feasible(lprec *lp, REAL *values, REAL threshold);

Return Value

is_feasible returns FALSE (0) or TRUE (1) that indicates if provided solution is feasible.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

values

An array of row/column values that are checked against the bounds and ranges.
The array must have 1+get_Nrows+get_Ncolumns elements. Element 0 is not used.

threshold

A tolerance value. The values may differ that much. Recommended to use get_epsint for this value.

Remarks

The is_feasible function checks if provided solution is a feasible solution. All values of the values array must be between the bounds and ranges to be a feasible solution.
This value is only valid after a successful solve or lag_solve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL values[1+2];
  unsigned char feasible;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  values[0] = 0.0;
  values[1] = 1.0;
  values[2] = 2.0;
  feasible = is_feasible(lp, values, 0); /* Will return TRUE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_objective, get_working_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex


is_free

Returns if the variable is free.

unsigned char is_free(lprec *lp, int column);

Return Value

is_free returns TRUE (1) if the variable is defined as free, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_free function returns if a variable is free or not. Free means a lower bound of -infinity and an upper bound of +infinity. Default a variable is not free because default it has a lower bound of 0 (and an upper bound of +infinity).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int free;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  free = is_free(lp, 1); /* will return 0 since the variable is not set as free at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_upbo, set_upbo, set_lowbo, get_lowbo, set_bounds, set_free, is_negative


is_infinite

Checks if the provided absolute of the value is larger or equal to "infinite".

unsigned char is_infinite(lprec *lp, REAL value);

Return Value

is_infinite returns TRUE if the value is equal or larger to "infinite".

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

value

The value to check against "infinite".

Remarks

Note that the absolute of the provided value is checked against the value set by set_infinite.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char infinite;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  infinite = is_infinite(lp, 1.0e31); /* will return TRUE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_infinite, get_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb


is_int

Gets the type of the variable. Integer or floating point.

unsigned char is_int(lprec *lp, int column);

Return Value

is_int returns TRUE (1) if the variable is set as integer, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_int function returns if a variable must be integer or not. Default a variable is not integer. From the moment there is at least one integer variable in the model, the Branch and Bound algorithm is used to make these variables integer. Note that solving times can be considerably larger when there are integer variables. See integer variables for a description about integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int integer;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  integer = is_int(lp, 1); /* will return 0 since the variable is not set as integer at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_int, is_binary, set_binary


is_integerscaling

Returns if integer scaling is active.

unsigned char is_integerscaling(lprec *lp);

Return Value

is_integerscaling returns if integer scaling is active (SCALE_INTEGERS set in get_scalelimit)

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_integerscaling function returns if integer scaling is active (SCALE_INTEGERS set in get_scalelimit). By default integers are not scaled. set_scaling must be called to active this feature.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int integerscaling;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  integerscaling = is_integerscaling(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_scaling, set_scaling, set_scalelimit, get_scalelimit


is_lag_trace

Returns a flag if Lagrangian progression must be printed while solving.

unsigned char is_lag_trace(lprec *lp);

Return Value

is_lag_trace returns TRUE or FALSE. Print or do not print.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_lag_trace function returns a flag if Lagrangian progression must be printed while solving. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char lag_trace;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  lag_trace = is_lag_trace(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_lag_trace


is_maxim

Returns objective function direction.

unsigned char is_maxim(lprec *lp);

Return Value

is_maxim returns a boolean value indicating if the objective direction is maximize (TRUE) or minimize (FALSE).

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The default of lp_solve is to minimize, except for read_lp, read_LP where the default is to maximize.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  ret = is_maxim(lp); /* will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_maxim, set_minim, set_sense


is_nativeBFP

Returns if the native (build-in) basis factorization package (BFP) is used, or an external package.

unsigned char is_nativeBFP(lprec *lp);

Return Value

is_nativeBFP returns TRUE if the native (build-in) BFP is used, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_nativeBFP function checks if an external BFP is set or not. See Basis Factorization Packages for a complete description on BFPs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char nativeBFP;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  nativeBFP = is_nativeBFP(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, has_BFP, set_BFP


is_nativeXLI

Returns if a build-in External Language Interfaces (XLI) is available or not.

unsigned char is_nativeXLI(lprec *lp);

Return Value

is_nativeXLI returns TRUE if a build-in XLI is available, FALSE if not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

At this moment, this routine always returns FALSE since no build-in XLI is available. See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char nativeXLI;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  nativeXLI = is_nativeXLI(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_XLI, has_XLI, set_XLI


is_negative

Returns if the variable is negative.

unsigned char is_negative(lprec *lp, int column);

Return Value

is_negative returns TRUE (1) if the variable is defined as negative, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_negative function returns if a variable is negative or not. Negative means a lower and upper bound that are both negative. Default a variable is not free because default it has a lower bound of 0 (and an upper bound of +infinity).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int negative;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  negative = is_negative(lp, 1); /* will return 0 since the variable is not set as negative at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_upbo, set_upbo, set_lowbo, get_lowbo, set_bounds, is_free, set_free


is_piv_mode

Returns if pivot mode specified in testmask is active.

unsigned char is_piv_mode(lprec *lp, int testmask);

Return Value

is_piv_mode returns TRUE or FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

testmask

PRICE_PRIMALFALLBACK (4) | In case of Steepest Edge, fall back to DEVEX in primal
PRICE_MULTIPLE (8) | Preliminary implementation of the multiple pricing scheme. This means that attractive candidate entering columns from one iteration may be used in the subsequent iteration, avoiding full updating of reduced costs. In the current implementation, lp_solve only reuses the 2nd best entering column alternative
PRICE_PARTIAL (16) | Enable partial pricing
PRICE_ADAPTIVE (32) | Temporarily use First Index if cycling is detected
PRICE_RANDOMIZE (128) | Adds a small randomization effect to the selected pricer
PRICE_LOOPLEFT (1024) | Scan entering/leaving columns left rather than right
PRICE_LOOPALTERNATE (2048) | Scan entering/leaving columns alternatingly left/right

Remarks

The is_piv_mode function checks if the pivot mode specified in testmask is active. The pivot mode is an extra modifier to the pivot rule. Any combination (OR) of the defined values is possible.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char piv_mode;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  piv_mode = is_piv_mode(lp, PRICE_ADAPTIVE); /* Will return TRUE, because this is the default */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_pivoting, get_pivoting, is_piv_rule


is_piv_rule

Checks if the specified pivot rule is active.

unsigned char is_piv_rule(lprec *lp, int rule);

Return Value

is_piv_rule returns TRUE if the specified pivot rule is active, else FALSE

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

rule

Can be one of the following values:
PRICER_FIRSTINDEX (0) | Select first
PRICER_DANTZIG (1) | Select according to Dantzig
PRICER_DEVEX (2) | Devex pricing from Paula Harris
PRICER_STEEPESTEDGE (3) | Steepest Edge

Remarks

This rule can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is PRICER_DEVEX (2).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char piv_rule;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  piv_rule = is_piv_rule(lp, PRICER_FIRSTINDEX);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_pivoting, set_pivoting, is_piv_mode


is_presolve

Returns if presolve level specified in testmask is active.

unsigned char is_presolve(lprec *lp, int testmask);

Return Value

is_presolve returns TRUE or FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

testmask

PRESOLVE_NONE (0) | No presolve at all
PRESOLVE_ROWS (1) | Presolve rows
PRESOLVE_COLS (2) | Presolve columns
PRESOLVE_LINDEP (4) | Eliminate linearly dependent rows
PRESOLVE_SOS (32) | Convert constraints to SOSes (only SOS1 handled)
PRESOLVE_REDUCEMIP (64) | If the phase 1 solution process finds that a constraint is redundant then this constraint is deleted
PRESOLVE_DUALS (128) | Calculate duals
PRESOLVE_SENSDUALS (256) | Calculate sensitivity if there are integer variables

Remarks

The is_presolve function returns a flag if the presolve level specified in testmask is active. Presolve looks at the model and tries to simplify it so that solving times are shorter. For example a constraint on only one variable is converted to a bound on this variable (and the constraint is deleted). Note that the model dimensions can change because of this, so be careful with this. Both rows and columns can be deleted by the presolve.
The default is not (FALSE) doing a presolve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int presolve;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  presolve = is_presolve(lp, PRESOLVE_ROWS | PRESOLVE_COLS); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_presolve, get_presolve


is_scalemode

Returns if scaling mode specified in testmask is active.

unsigned char is_scalemode(lprec *lp, int testmask);

Return Value

is_scalemode returns if scaling mode specified in testmask is active.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

testmask

SCALE_EXTREME (1) | Scale to convergence using largest absolute value
SCALE_RANGE (2) | Scale based on the simple numerical range
SCALE_MEAN (3) | Numerical range-based scaling
SCALE_GEOMETRIC (4) | Geometric scaling
SCALE_CURTISREID (7) | Curtis-reid scaling

Additionally, the value can be OR-ed with any combination of one of the following values:

SCALE_QUADRATIC (8) |
SCALE_LOGARITHMIC (16) | Scale to convergence using logarithmic mean of all values
SCALE_USERWEIGHT (31) | User can specify scalars
SCALE_POWER2 (32) | also do Power scaling
SCALE_EQUILIBRATE (64) | Make sure that no scaled number is above 1
SCALE_INTEGERS (128) | also scaling integer variables
SCALE_DYNUPDATE (256) | dynamic update

Remarks

The is_scalemode function returns if scaling mode specified in testmask. This can influence numerical stability considerably. It is advisable to always use some sort of scaling.
set_scaling must be called before solve is called.
SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC, SCALE_CURTISREID are the possible scaling algorithms. SCALE_QUADRATIC, SCALE_LOGARITHMIC, SCALE_USERWEIGHT, SCALE_POWER2, SCALE_EQUILIBRATE, SCALE_INTEGERS are possible additional scaling parameters.
SCALE_POWER2 results in creating a scalar of power 2. May improve stability.
SCALE_INTEGERS results also in scaling Integer columns. Default they are not scaled.
SCALE_DYNUPDATE is new from version 5.1.1.0
It has always been so that scaling is done only once on the original model. If a solve is done again (most probably after changing some data in the model), the scaling factors aren't computed again. The scalars of the original model are used. This is not always good, especially if the data has changed considerably. One way to solve this was/is call unscale before a next solve. In that case, scale factors are recomputed.
From version 5.1.1.0 on, there is another way to make sure that scaling factors are recomputed and this is by settings SCALE_DYNUPDATE. In that case, the scaling factors are recomputed also when a restart is done. Note that they are then always recalculated with each solve, even when no change was made to the model, or a change that doesn't influence the scaling factors like changing the RHS (Right Hand Side) values or the bounds/ranges. This can influence performance. It is up to you to decide if scaling factors must be recomputed or not for a new solve, but by default it still isn't so. It is possible to set/unset this flag at each next solve and it is even allowed to choose a new scaling algorithm between each solve. Note that the scaling done by the SCALE_DYNUPDATE is incremental and the resulting scalars are typically different from scalars recomputed from scratch.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int scalemode;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  scalemode = is_scalemode(lp, SCALE_MEAN);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scaling, get_scaling, set_scalelimit, get_scalelimit, is_integerscaling, is_scaletype


is_scaletype

Returns if scaling type specified in scaletype is active.

unsigned char is_scaletype(lprec *lp, int scaletype);

Return Value

is_scaletype returns if scaling mode specified in scaletype is active.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

scaletype

SCALE_EXTREME (1) | Scale to convergence using largest absolute value
SCALE_RANGE (2) | Scale based on the simple numerical range
SCALE_MEAN (3) | Numerical range-based scaling
SCALE_GEOMETRIC (4) | Geometric scaling
SCALE_CURTISREID (7) | Curtis-reid scaling

Remarks

The is_scaletype function returns if scaling mode specified in scaletype. This can influence numerical stability considerably. It is advisable to always use some sort of scaling.
set_scaling must be called before solve is called.
SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC, SCALE_CURTISREID are the possible scaling algorithms.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int scaletype;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  scaletype = is_scaletype(lp, SCALE_MEAN);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scaling, get_scaling, set_scalelimit, get_scalelimit, is_integerscaling, is_scalemode


is_semicont

Gets the type of the variable. semi-continuous or not.

unsigned char is_semicont(lprec *lp, int column);

Return Value

is_semicont returns TRUE (1) if the variable is set as semi-continuous, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_semicont function returns if a variable must be semi-continuous or not. Default a variable is not semi-continuous. See semi-continuous variables for a description about semi-continuous variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char sc;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  sc = is_semicont(lp, 1); /* will return 0 since the variable is not set as semi-continuous at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_semicont


is_SOS_var

Returns if the variable is SOS (Special Ordered Set) or not.

unsigned char is_SOS_var(lprec *lp, int column);

Return Value

is_SOS_var returns TRUE (1) if the variable is a SOS var, FALSE (0) if not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_SOS_var function returns if a variable is a SOS variable or not. Default a variable is not SOS. A variable becomes a SOS variable via add_SOS. See Special Ordered Sets for a description about SOS variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int isSOS;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  isSOS = is_SOS_var(lp, 1); /* will return 0 since the variable is not an SOS var at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_SOS


is_trace

Returns a flag if pivot selection must be printed while solving.

unsigned char is_trace(lprec *lp);

Return Value

is_trace returns TRUE or FALSE. Print or do not print.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_trace function returns a flag if pivot selection must be printed while solving. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char trace;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  trace = is_trace(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_trace


lag_solve

Solve the model via Lagrangian relaxation.

int lag_solve(lprec *lp, REAL start_bound, int num_iter, short verbose);

Return Value

TIMEOUT (-2) | A timeout occurred. A timeout was set via set_timeout
USERABORT (-3) | The abort routine returned TRUE. See put_abortfunc
OPTIMAL (0) | An optimal solution was obtained
INFEASIBLE (2) | The model is infeasible
FEAS_FOUND (6) | An feasible solution was obtained, but num_iter was reached
NO_FEAS_FOUND (7) | No feasible solution found

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

start_bound

Initial bound.

num_iter

Maximum number of iterations.

verbose

Not used. Still included for backwards compatibility. Use set_lag_trace to set the verbose level.

Remarks

The lag_solve function solves the model via Lagrangian relaxation. Gives the ability to find an integer solution without the branch-and-bound algorithm.
At least 1 Lagrangian constraint must be added via add_lag_con, str_add_lag_con before lag_solve can be used.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 1.0;
  add_lag_con(lp, row, LE, 1.0);

  ret = lag_solve(lp, 0, 30, FALSE);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, solve, get_statustext, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex, add_lag_con, get_Lrows


lp_solve_version

Returns the full version number of lp_solve.

void lp_solve_version(int *majorversion, int *minorversion, int *release, int *build);

Return Value

lp_solve_version has no return value.

Parameters

majorversion

major version number.

minorversion

minor version number.

release

release number.

build

build number.

Remarks

The lp_solve_version function returns the full version number of lp_solve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  int majorversion, minorversion, release, build;

  lp_solve_version(&majorversion, &minorversion, &release, &build);

  return(0);
}

lp_solve API reference

See Also


make_lp

Create and initialise a new lprec structure.

lprec *make_lp(int rows, int columns);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error. Specifically not enough memory available to setup an lprec structure.

Parameters

rows

Initial number of rows. Can be 0 as new rows can be added via add_constraint, add_constraintex, str_add_constraint

columns

Initial number of columns. Can be 0 as new columns can be added via add_column, add_columnex, str_add_column

Remarks

The make_lp function constructs a new LP. Sets all variables to initial values.
The LP has rows rows and columns columns. The matrix contains no values, but space for one value. All arrays that depend on rows and columns are allocated.

It is advised not to read/write the lprec structure. Instead, use the function interface to communicate with the lp_solve library. This because the structure can change over time. The function interface will be more stable.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI


print_constraints

Prints the values of the constraints of the lp.

void print_constraints(lprec *lp, int columns);

Return Value

print_constraints has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

columns

Number of columns to print solution.

Remarks

The print_constraints function prints the values of the constraints of the lp. This can only be done after a successful solve.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_constraints(lp, 1);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, See get_constraints, print_lp, print_objective, print_solution, print_duals, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump


print_debugdump

Do a generic readable data dump of key lp_solve model variables; principally for run difference and debugging purposes.

unsigned char print_debugdump(lprec *lp, char *filename);

Return Value

print_debugdump returns TRUE if data could be written, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_debugdump function creates a generic readable data dump of key lp_solve model variables; principally for run difference and debugging purposes
This function is meant for debugging purposes.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_debugdump(lp, "debug.txt"); /* dump to file debug.txt in current directory */

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_lp, print_objective, print_constraints, print_duals, print_scales, print_tableau, print_str


print_duals

Prints the values of the duals of the lp.

void print_duals(lprec *lp);

Return Value

print_duals has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_duals function prints the values of the duals of the lp. This can only be done after a successful solve.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_duals(lp, 1);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex, print_lp, print_objective, print_solution, print_constraints, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump


print_lp

Prints the lp model.

void print_lp(lprec *lp);

Return Value

print_lp has no return value. Note that row entry mode must be off, else this function fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_lp function prints the lp model.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  print_lp(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_objective, print_solution, print_constraints, print_duals, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump


print_objective

Prints the objective value of the lp.

void print_objective(lprec *lp);

Return Value

print_objective has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_objective function prints the objective value of the lp. This can only be done after a successful solve.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_objective(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_objective, print_lp, print_solution, print_constraints, print_duals, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump


print_scales

Prints the scales of the lp.

void print_scales(lprec *lp);

Return Value

print_scales has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_scales function prints the scales of the lp. This can only be done after a successful solve. It will only output something when the model is scaled.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_scaling(lp, CURTISREIDSCALE);

  solve(lp);

  print_scales(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_lp, print_objective, print_solution, print_constraints, print_duals, print_tableau, print_str, set_outputstream, set_outputfile, set_scaling, print_debugdump


print_solution

Prints the solution (variables) of the lp.

void print_solution(lprec *lp, int columns);

Return Value

print_solution has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

columns

Number of columns to print solution.

Remarks

The print_solution function prints the solution (variables) of the lp. This can only be done after a successful solve.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_solution(lp, 1);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_variables, get_ptr_variables, print_lp, print_objective, print_constraints, print_duals, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump


print_str

Prints a string.

void print_str(lprec *lp, char *str);

Return Value

print_str has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

str

The string to print

Remarks

The print_str function prints a string. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.
This function can be usefull for debugging/demo purposes.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_str(lp, "We are here\n");

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_objective, print_solution, print_constraints, print_duals, print_scales, print_tableau, set_outputstream, set_outputfile, print_debugdump


print_tableau

Prints the tableau.

void print_tableau(lprec *lp);

Return Value

print_tableau has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_tableau function prints the tableau. This function only works after a successfull solve
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_tableau(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_objective, print_solution, print_constraints, print_duals, print_scales, print_str, set_outputstream, set_outputfile, print_debugdump


put_abortfunc

Sets a abort routine.

void put_abortfunc(lprec *lp, ctrlcfunc newctrlc, void *ctrlchandle);

Return Value

put_abortfunc has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

newctrlc

The abort routine.

typedef int (__WINAPI ctrlcfunc)(lprec *lp, void *userhandle);

Note the __WINAPI attribute. This is importand under Windows. It ensures __stdcall calling convention which is required.

ctrlchandle

A parameter that will be provided to the abort routine.

Remarks

The put_abortfunc function sets a abort routine.
When set, the abort routine is called regularly. The user can do whatever he wants in this routine. For example check if the user pressed abort. The return value of this routine must be FALSE (0) or TRUE (1). If TRUE (1), then lp_solve aborts the solver and returns with an appropriate code. The abort routine can be cleared by specifying NULL as abort routine.
The default is no abort routine (NULL).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int __WINAPI abortfunction(lprec *lp, void *userhandle)
{
 int doabort = FALSE;

 /* do something */

 return(doabort);
}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_abortfunc(lp, abortfunction, NULL);

  solve(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, put_logfunc


put_logfunc

Sets a log routine.

void put_logfunc(lprec *lp, logfunc newlog, void *loghandle);

Return Value

put_logfunc has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

newlog

The log routine.

typedef void (__WINAPI logfunc)(lprec *lp, void *userhandle, char *buf);
Note the __WINAPI attribute. This is importand under Windows. It ensures __stdcall calling convention which is required.

loghandle

A parameter that will be provided to the log routine.

Remarks

The put_logfunc function sets a log routine.
When set, the log routine is called when lp_solve has someting to report. The return value of this routine should be 0. The log routine can be cleared by specifying NULL as log routine.
This function is called at the same time as something is written to file set via set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

void __WINAPI logfunction(lprec *lp, void *userhandle, char *buf)
{

 /* do something with buf (the message) */

}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_logfunc(lp, logfunction, NULL);
  set_verbose(lp, FULL);

  del_column(lp, 1); /* Will generate an error because column 1 does not exist */
                     /* Note that del_column returns FALSE (0) to indicate an error */
  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, put_abortfunc


put_msgfunc

Sets a message routine.

void put_msgfunc(lprec *lp, msgfunc newmsg, void *msghandle, int mask);

Return Value

put_msgfunc has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

newmsg

The message routine.

typedef void (__WINAPI msgfunc)(lprec *lp, void *userhandle, int message);

Note the __WINAPI attribute. This is importand under Windows. It ensures __stdcall calling convention which is required.

msghandle

A parameter that will be provided to the message routine.

mask

Any combination of the following values:

MSG_PRESOLVE (1) | Presolve done.
MSG_LPFEASIBLE (8) | Feasible solution found.
MSG_LPOPTIMAL (16) | Real optimal solution found. Only fired when there are integer variables at the start of B&B
MSG_MILPEQUAL (32) | Equal MILP solution found. Only fired when there are integer variables during B&B
MSG_MILPFEASIBLE (128) | First MILPsolution found. Only fired when there are integer variables during B&B
MSG_MILPBETTER (512) | Better MILPsolution found. Only fired when there are integer variables during B&B

Remarks

The put_msgfunc function sets a message routine. This routine is called when a situation specified in mask occurs. Note that this routine is called while solving the model. This can be usefull to follow the solving progress.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

void __WINAPI msgfunction(lprec *lp, void *userhandle, int msg)
{
 switch(msg) {
 case MSG_LPFEASIBLE:
  printf("Feasible solution found\n");
  break;
 case MSG_MILPFEASIBLE:
  printf("Integer feasible solution found\n");
  break;
 case MSG_MILPBETTER:
  printf("Better integer feasible solution found\n");
  break;
 }
}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_msgfunc(lp, msgfunction, NULL, MSG_LPFEASIBLE | MSG_MILPFEASIBLE | MSG_MILPBETTER);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, put_abortfunc


read_lp, read_LP

Create an lprec structure and read an lp model from file.

lprec *read_lp(FILE *stream, int verbose, char *lp_name);

lprec *read_LP(char *filename, int verbose, char *lp_name);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error. Specifically file could not be opened or file has wrong structure or not enough memory available to setup an lprec structure.

Parameters

stream

Pointer to FILE structure.

filename

Filename to read the lp model from.

verbose

The verbose level. Can be one of the following values:
CRITICAL (1), SEVERE (2), IMPORTANT (3), NORMAL (4), DETAILED (5), FULL (6)

See also set_verbose and get_verbose.

lp_name

Initial name of the model. See also set_lp_name and get_lp_name. May be NULL if the model has no name.

Remarks

The read_lp and read_LP functions construct a new lprec structure and read the model from filename. read_lp needs a file pointer to an already opened file. read_LP accepts the name of the file. The latter function will generally be more convenient.

The model in the file must be in lp-format.

It is advised not to read/write the lprec structure. Instead, use the function interface to communicate with the lp_solve library. This because the structure can change over time. The function interface will be more stable.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Read LP model */
  lp = read_LP("model.lp", NORMAL, "test model");
  if(lp == NULL) {
    fprintf(stderr, "Unable to read model\n");
    return(1);
  }

  /* Model read */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, write_lp, write_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_mps, write_freemps, write_MPS, write_freeMPS


read_mps, read_freemps, read_MPS, read_freeMPS

Create an lprec structure and read an mps model from file.

lprec *read_mps(FILE *stream, int verbose);

lprec *read_freemps(FILE *stream, int verbose);

lprec *read_MPS(char *filename, int verbose);

lprec *read_freeMPS(char *filename, int verbose);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error. Specifically file could not be opened or file has wrong structure or not enough memory available to setup an lprec structure.

Parameters

stream

Pointer to FILE structure.

filename

Filename to read the mps model from.

verbose

The verbose level. Can be one of the following values:
CRITICAL (1), SEVERE (2), IMPORTANT (3), NORMAL (4), DETAILED (5), FULL (6)

See also set_verbose and get_verbose.

Remarks

The read_mps, read_freemps, read_MPS, read_freeMPS functions construct a new lprec structure and read the model from filename. read_mps, read_freemps need a file pointer to an already opened file. read_MPS, read_freeMPS accepts the name of the file. The latter functions will generally be more convenient.

The model in the file must be in mps-format. The read_free* routines accept files in free MPS format. The other routines accept files in fixed MPS format.

It is advised not to read/write the lprec structure. Instead, use the function interface to communicate with the lp_solve library. This because the structure can change over time. The function interface will be more stable.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Read MPS model */
  lp = read_MPS("model.mps", NORMAL);
  if(lp == NULL) {
    fprintf(stderr, "Unable to read model\n");
    return(1);
  }

  /* Model read */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, write_mps, write_freemps, write_MPS, write_freeMPS, read_lp, read_LP, write_lp, write_LP


read_XLI

Create an lprec structure and read a model via the External Language Interface.

lprec *read_XLI(char *xliname, char *modelname, char *dataname, char *options, int verbose);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error.

Parameters

xliname

Filename of the XLI package.

modelname

Filename to read the model from.

dataname

Filename to read the data from. This may be optional. In that case, set the parameter to NULL.

options

Extra options that can be used by the reader.

verbose

The verbose level. Can be one of the following values:
CRITICAL (1), SEVERE (2), IMPORTANT (3), NORMAL (4), DETAILED (5), FULL (6)

See also set_verbose and get_verbose.

Remarks

The read_XLI function constructs a new lprec structure and reads the model from filename via the specified XLI. See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Read LP model */
  lp = read_XLI("xli_MathProg", "model.mat", NULL, "", NORMAL);
  if(lp == NULL) {
    fprintf(stderr, "Unable to read model\n");
    return(1);
  }

  /* Model read */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, write_lp, write_LP, read_mps, read_freemps, read_MPS, read_freeMPS, write_mps, write_freemps, write_MPS, write_freeMPS, write_XLI, has_XLI, is_nativeXLI, set_XLI


reset_basis

Causes reinversion at next opportunity

void reset_basis(lprec *lp);

Return Value

reset_basis has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

This routine is ment for internal use and development. It causes a reinversion of the matrix at a next opportunity. The routine should only be used by people deeply understanding the code.
In the past, this routine was documented as the routine to set an initial base. This is incorrect. default_basis must be used for this purpose. It is very unlikely that you must call this routine.

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basis, set_basis, default_basis, get_basiscrash set_basiscrash


set_add_rowmode

Specifies which add routine performs best. add_column, add_columnex, str_add_column or add_constraint, add_constraintex, str_add_constraint

unsigned char set_add_rowmode(lprec *lp, unsigned char turnon);

Return Value

set_add_rowmode return TRUE if changed from mode and FALSE if this mode was already set.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

turnon

TRUE or FALSE. If FALSE, then add_column, add_columnex, str_add_column performs best. If TRUE, then add_constraint, add_constraintex, str_add_constraint performs best.

Remarks

Default, this is FALSE, meaning that add_column, add_columnex, str_add_column performs best. If the model is build via add_constraint, add_constraintex, str_add_constraint calls, then these routines will be much faster if this routine is called with turnon set on TRUE. This is also called row entry mode. The speed improvement is spectacular, especially for bigger models, so it is advisable to call this routine to set the mode. Normally a model is build either column by column or row by row.
Note that there are several restrictions with this mode:
Only use this function after a make_lp call. Not when the model is read from file. Also, if this function is used, first add the objective function via set_obj_fn, set_obj_fnex, str_set_obj_fn and after that add the constraints via add_constraint, add_constraintex, str_add_constraint. Don't call other API functions while in row entry mode. No other data matrix access is allowed while in row entry mode. After adding the contraints, turn row entry mode back off. Once turned of, you cannot switch back to row entry mode. So in short:
- turn row entry mode on
- set the objective function
- create the constraints
- turn row entry mode off

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 10);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_add_rowmode(lp, TRUE);
  /* first! set the objective function */

  /* now add the constraints */
  set_add_rowmode(lp, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_add_rowmode, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, add_column, add_columnex, str_add_column, set_column, set_columnex, add_constraint, add_constraintex, str_add_constraint


set_anti_degen

Specifies if special handling must be done to reduce degeneracy/cycling while solving.

void set_anti_degen(lprec *lp, int anti_degen);

Return Value

set_anti_degen has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

anti_degen

Can be any combination (OR) of following values:

ANTIDEGEN_NONE (0) | No anti-degeneracy handling
ANTIDEGEN_FIXEDVARS (1) | Check if there are equality slacks in the basis and try to drive them out in order to reduce chance of degeneracy in Phase 1
ANTIDEGEN_COLUMNCHECK (2) |
ANTIDEGEN_STALLING (4) |
ANTIDEGEN_NUMFAILURE (8) |
ANTIDEGEN_LOSTFEAS (16) |
ANTIDEGEN_INFEASIBLE (32) |
ANTIDEGEN_DYNAMIC (64) |
ANTIDEGEN_DURINGBB (128) |

Remarks

The set_anti_degen function specifies if special handling must be done to reduce degeneracy/cycling while solving. Setting this flag can avoid cycling, but can also increase numerical instability. The default is ANTIDEGEN_NONE (0).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_anti_degen(lp, ANTIDEGEN_FIXEDVARS | ANTIDEGEN_PERTURB);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_anti_degen, is_anti_degen


set_basis

Sets an initial basis of the lp.

unsigned char set_basis(lprec *lp, int *bascolumn, unsigned char nonbasic);

Return Value

set_basis returns TRUE if provided basis was set. FALSE if not. If FALSE then provided data was invalid.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bascolumn

An array with 1+get_Nrows or 1+get_Nrows+get_Ncolumns elements that specifies the basis.

nonbasic

If FALSE, then bascolumn must have 1+get_Nrows elements and only contains the basic variables. If TRUE, then bascolumn must have 1+get_Nrows+get_Ncolumns elements and will also contain the non-basic variables.

Remarks

The set_basis function sets an initial basis of the lp.
The array receives the basic variables and if nonbasic is TRUE, then also the non-basic variables. If an element is less then zero then it means on lower bound, else on upper bound.
Element 0 of the array is unused.
The default initial basis is bascolumn[x] = -x.
Each element represents a basis variable. If the absolute value is between 1 and get_Nrows, it represents a slack variable and if it is between get_Nrows+1 and get_Nrows+get_Ncolumns then it represents a regular variable. If the value is negative, then the variable is on its lower bound. If positive it is on its upper bound.
Setting an initial basis can speed up the solver considerably. It is the starting point from where the algorithm continues to find an optimal solution.
When a restart is done, lp_solve continues at the last basis, except if set_basis or default_basis is called.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int bascolumn[1+2]; /* must be 1 more then number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  bascolumn[0] = 0;
  bascolumn[1] = -1;
  bascolumn[2] = -2;
  set_basis(lp, bascolumn, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basis, default_basis, get_basiscrash, set_basiscrash


set_basiscrash

Determines a starting base.

void set_basiscrash(lprec *lp, int mode);

Return Value

None

Parameters

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

mode

Specifies which basis crash mode is used. Can by any of the following values:

CRASH_NOTHING (0) | No basis crash
CRASH_MOSTFEASIBLE (2) |

Remarks

The set_basiscrash function specifies which basis crash mode must be used. This can influence the solving time considerly. Default it is CRASH_NOTHING.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  set_basiscrash(lp, CRASH_MOSTFEASIBLE);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basiscrash, default_basis, get_basis, set_basis


set_bb_depthlimit

Sets the maximum branch-and-bound depth.

void set_bb_depthlimit(lprec *lp, int bb_maxlevel);

Return Value

set_bb_depthlimit has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bb_maxlevel

Specifies the maximum branch-and-bound depth. A positive value means that the depth is absoluut. A negative value means a relative B&B depth limit. The "order" of a MIP problem is defined to be 2x the number of binary variables plus the number of SC and SOS variables. A relative value of -x results in a maximum depth of x times the order of the MIP problem.

Remarks

The set_bb_depthlimit function sets the maximum branch-and-bound depth.
This is only usefull if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algorithm must be used to solve them. The branch-and-bound algorithm will not go deeper than this level. When 0 then there is no limit to the depth. Limiting the depth will speed up solving time, but there is a chance that the found solution is not the most optimal one. Be aware of this. It can also result in not finding a solution at all.
The default is -50.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bb_depthlimit(lp, 10);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_bb_depthlimit


set_bb_floorfirst

Specifies which branch to take first in branch-and-bound algorithm.

void set_bb_floorfirst(lprec *lp, int bb_floorfirst);

Return Value

set_bb_floorfirst has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bb_floorfirst

Specifies which branch to take first in branch-and-bound algorithm. Can by any of the following values:

BRANCH_CEILING (0) | Take ceiling branch first
BRANCH_FLOOR (1) | Take floor branch first
BRANCH_AUTOMATIC (2) | Algorithm decides which branch being taken first

Remarks

The set_bb_floorfirst function specifies which branch to take first in branch-and-bound algorithm. This can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is BRANCH_FLOOR (1).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bb_floorfirst(lp, BRANCH_AUTOMATIC);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_bb_floorfirst, set_var_branch, get_var_branch, set_var_weights, get_var_priority


set_bb_rule

Specifies the branch-and-bound rule.

void set_bb_rule(lprec *lp, int bb_rule);

Return Value

set_bb_rule has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bb_rule

The branch-and-bound rule. Can by any of the following values:

NODE_FIRSTSELECT (0) | Select lowest indexed non-integer column
NODE_GAPSELECT (1) | Selection based on distance from the current bounds
NODE_RANGESELECT (2) | Selection based on the largest current bound
NODE_FRACTIONSELECT (3) | Selection based on largest fractional value
NODE_PSEUDOCOSTSELECT (4) | Simple, unweighted pseudo-cost of a variable
NODE_PSEUDONONINTSELECT (5) | This is an extended pseudo-costing strategy based on minimizing the number of integer infeasibilities
NODE_PSEUDORATIOSELECT (6) | This is an extended pseudo-costing strategy based on maximizing the normal pseudo-cost divided by the number of infeasibilities. Effectively, it is similar to (the reciprocal of) a cost/benefit ratio
NODE_USERSELECT (7) |

One of these values may be or-ed with one or more of the following values:

NODE_WEIGHTREVERSEMODE (8) |
NODE_BRANCHREVERSEMODE (16) | In case when get_bb_floorfirst is BRANCH_AUTOMATIC, select the oposite direction (lower/upper branch) that BRANCH_AUTOMATIC had chosen.
NODE_GREEDYMODE (32) |
NODE_PSEUDOCOSTMODE (64) |
NODE_DEPTHFIRSTMODE (128) | Select the node that has already been selected before the most number of times
NODE_RANDOMIZEMODE (256) |
NODE_DYNAMICMODE (1024) | When NODE_DEPTHFIRSTMODE is selected, switch off this mode when a first solution is found.
NODE_RESTARTMODE (2048) |
NODE_BREADTHFIRSTMODE (4096) | Select the node that has been selected before the fewest number of times or not at all
NODE_AUTOORDER (8192) | Create an "optimal" B&B variable ordering. Can speed up B&B algorithm.

Remarks

The set_bb_rule function specifies the branch-and-bound rule for choosing which non-integer variable is to be selected. This rule can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is NODE_FIRSTSELECT (0).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bb_rule(lp, NODE_FIRSTSELECT);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_bb_rule


set_BFP

Set basis factorization package.

unsigned char set_BFP(lprec *lp, char *filename);

Return Value

set_BFP returns TRUE if the call has succeeded, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

The name of the BFP package. Currently following BFPs are implemented:

"bfp_etaPFI" | original lp_solve product form of the inverse.
"bfp_LUSOL" | LU decomposition.
"bfp_GLPK" | GLPK LU decomposition.
NULL | The default BFP package.
However the user can also build his own BFP packages ...

Remarks

The set_BFP function sets the basis factorization package (BFP). See Basis Factorization Packages for a complete description on BFPs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_BFP(lp, "bfp_LUSOL");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, has_BFP, is_nativeBFP


set_XLI

Set External Language Interfaces package.

unsigned char set_XLI(lprec *lp, char *filename);

Return Value

set_XLI returns TRUE if the call has succeeded, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

The name of the XLI package.

Remarks

The set_BFP function sets the External Language Interface (XLI). This call is normally only needed when write_XLI will be called. read_XLI automatically calls this routine. See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_XLI(lp, "xli_MathProg");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_XLI, has_XLI, is_nativeXLI


set_binary

Set the type of the variable. Binary or floating point.

unsigned char set_binary(lprec *lp, int column, unsigned char must_be_bin);

Return Value

set_binary returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be set. It must be between 1 and the number of columns in the lp.

must_be_bin

TRUE (1) if the variable must be binary, FALSE (0) if not.

Remarks

The set_binary function defines if a variable must be binary or not. Default a variable is not binary. A binary variable is an integer variable with a lower bound of 0 and an upper bound of 1. This function also sets these bounds. The argument must_be_bin defines what the status of the variable becomes. From the moment there is at least one integer variable in the model, the Branch and Bound algorithm is used to make these variables integer. Note that solving times can be considerably larger when there are integer variables. See integer variables for a description about integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_binary(lp, 1, TRUE); /* sets variable 1 to binary */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_binary, is_int, set_int


set_bounds

Set the upper and lower bound of a variable.

unsigned char set_bounds(lprec *lp, int column, REAL lower, REAL upper);

Return Value

set_bounds returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the bounds must be set. It must be between 1 and the number of columns in the lp.

Remarks

The set_bounds function sets a lower and upper bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
Note that the default lower bound of each variable is 0. So variables will never take negative values if no negative lower bound is set. The default upper bound of a variable is infinity (well not quite. It is a very big number. The value of get_infinite).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bounds(lp, 1, 1.0, 2.0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_lowbo, get_lowbo, set_upbo, get_upbo, set_free, is_free, is_negative


set_bounds_tighter

Specifies if set bounds may only be tighter or also less restrictive.

void set_bounds_tighter(lprec *lp, unsigned char tighten);

Return Value

set_bounds_tighter has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

tighten

Specifies if set bounds may only be tighter (TRUE) or also less restrictive (FALSE).

Remarks

The set_bounds_tighter function sets if bounds may only be tighter or also less restrictive. If set to TRUE then bounds may only be tighter. This means that when set_lowbo or set_lowbo is used to set a bound and the bound is less restrictive than an already set bound, then this new bound will be ignored. If tighten is set to FALSE, the new bound is accepted. This functionality is useful when several bounds are set on a variable and at the end you want the most restrictive ones. By default, this setting is FALSE. Note that this setting does not affect set_bounds.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bounds_tighter(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_bounds_tighter, set_upbo, get_upbo, set_lowbo, get_lowbo, set_bounds, set_free, is_free, is_negative


set_break_at_first

Specifies if the branch-and-bound algorithm stops at first found solution.

void set_break_at_first(lprec *lp, unsigned char break_at_first);

Return Value

set_break_at_first has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

break_at_first

TRUE or FALSE. Stop branch-and-bound algorithm at first found solution or not.

Remarks

The set_break_at_first function specifies if the branch-and-bound algorithm stops at the first found solution or not. Stopping at the first found solution can be useful if you are only interested for a solution, but not necessarily (and most probably) the most optimal solution.
The default is not (FALSE) stop at first found solution.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_break_at_first(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_break_at_first, set_break_at_value, get_break_at_value, set_obj_bound, get_obj_bound, set_mip_gap, get_mip_gap


set_break_at_value

Specifies if the branch-and-bound algorithm stops when the object value is better than a given value.

void set_break_at_value(lprec *lp, REAL break_at_value);

Return Value

set_break_at_value has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

break_at_value

The value to break on.

Remarks

The set_break_at_value function allows the branch-and-bound algorithm to stops when the object value is better than a given value. Stopping at a given object value can be useful if you are only interested for a solution that has an object value which is at least a given value, but not necessarily (and most probably) the most optimal solution.
The default value is (-) infinity.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_break_at_value(lp, 1000); /* Will stop if object value is better than 1000 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_break_at_value, set_break_at_first, is_break_at_first, set_obj_bound, get_obj_bound, set_mip_gap, get_mip_gap


set_column, set_columnex

set a column in the lp.

unsigned char set_column(lprec *lp, int col_no, REAL *column);

unsigned char set_columnex(lprec *lp, int col_no, int count, REAL *column, int *rowno);

Return Value

set_column, set_columnex return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

col_no

The column number that must be changed.

count

Number of elements in column and rowno.

column

An array with 1+rows (count for set_columnex if rowno is different from NULL) elements that contains the values of the column.

rowno

An array with count elements that contains the row numbers of the column. However this variable can also be NULL. In that case element i in the variable column is row i.

Remarks

The set_column, set_columnex functions change the values of an existing column in the model at once. Note that add_column, add_columnex, str_add_column add a column to the model, making the number of columns one larger. These functions change an existing column.
Note that for set_column (and set_columnex when rowno is NULL) element 0 of the array is row 0 (the objective function), element 1 is row 1, ...
set_columnex has the possibility to specify only the non-zero elements. In that case rowno specifies the row numbers of the non-zero elements. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value. Thus it is almost always better to use set_columnex instead of set_column. set_columnex is always at least as performant as set_column. It is more performant to call these functions than multiple times set_mat. Note that unspecified values by set_columnex are set to zero.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL column[1+2];

  /* Create a new LP model */
  lp = make_lp(2, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  column[0] = 1.0; /* the objective value */
  column[1] = 2.0;
  column[1] = 3.0;
  set_column(lp, 1, column); /* changes the values of existing column 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_column, add_column, add_columnex, str_add_column, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, set_add_rowmode, is_add_rowmode, get_constr_type, is_constr_type, del_constraint, add_column, add_columnex, str_add_column, get_column, get_row, get_mat


set_col_name

Set the name of a column in the lp.

unsigned char set_col_name(lprec *lp, int column, char *new_name);

Return Value

set_col_name returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column for which the name must be set. Must be between 1 and the number of columns in the lp.

new_name

The name for the column.

Remarks

The set_col_name sets the name of the column.
The column must already exist. Column names are optional.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_col_name(lp, 1, "col1");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_col_name, get_origcol_name, set_row_name, get_row_name, get_origrow_name, get_nameindex


set_constr_type

Set the type of a constraint.

unsigned char set_constr_type(lprec *lp, int row, int con_type);

Return Value

set_constr_type returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the constraint type must be set. Must be between 1 and number of rows in the lp.

con_type

The type of the constraint. Can by any of the following values:

LE (1) | Less than or equal (<=)
EQ (3) | Equal (=)
GE (2) | Greater than or equal (>=)
FR (0) | Free

Remarks

The set_constr_type function sets the constraint type for the specified row.
The default constraint type is LE.
Note the free (FR) constraint type. This is new from version 5.1.0.1
A free constraint will act as if the constraint is not there. The lower bound is -Infinity and the upper bound is +Infinity.
This can be used to temporary disable a constraint without having to delete it from the model. Note that the already set RHS and range on this constraint is overruled with Infinity by this.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_constr_type(lp, 1, GE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_constr_type, is_constr_type, add_constraint, add_constraintex, str_add_constraint, del_constraint


set_debug

Sets a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.

void set_debug(lprec *lp, unsigned char debug);

Return Value

set_debug has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

debug

TRUE or FALSE. Debug or do not debug.

Remarks

The set_debug function sets a flag if all intermediate results and the branch-and-bound decisions must be printed while solving. This function is mend for debugging purposes. The default is not to debug (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_debug(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_debug


set_epsb

Specifies the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.

void set_epsb(lprec *lp, REAL epsb);

Return Value

set_epsb has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsb

The value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.

Remarks

The set_epsb function specifies the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epsb specifies the tolerance to determine if a RHS value should be considered as 0. If abs(value) is less than this epsb value in the RHS, it is considered as 0.
The default epsb value is 1.0e-10

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsb(lp, 1.0e-9); /* sets epsb to 1e-9 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsb, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap


set_epsd

Specifies the value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.

void set_epsd(lprec *lp, REAL epsd);

Return Value

set_epsd has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsd

The value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.

Remarks

The set_epsd function specifies the value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epsd specifies the tolerance to determine if a reducedcost value should be considered as 0. If abs(value) is less than this epsd value, it is considered as 0.
The default epsd value is 1e-9

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsd(lp, 1.0e-8); /* sets epsd to 1e-8 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsd, set_infinite, is_infinite, get_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap


set_epsel

Specifies the value that is used as a tolerance for rounding values to zero.

void set_epsel(lprec *lp, REAL epsel);

Return Value

set_epsel has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsel

The value that is used as a tolerance for rounding values to zero.

Remarks

The set_epsel function specifies the value that is used as a tolerance for rounding values to zero.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epsel specifies the tolerance to determine if a value should be considered as 0. If abs(value) is less than this epsel value, it is considered as 0.
epsel is used on all other places where epsint, epsb, epsd, epspivot, epsperturb are not used. The default epsel value is 1e-12

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsel(lp, 1.0e-11); /* sets epsel to 1e-11 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsel, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsb, get_epsb, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap


set_epsint

Specifies the tolerance that is used to determine whether a floating-point number is in fact an integer.

void set_epsint(lprec *lp, REAL epsint);

Return Value

set_epsint has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsint

The tolerance that is used to determine whether a floating-point number is in fact an integer.

Remarks

The set_epsint function specifies the tolerance that is used to determine whether a floating-point number is in fact an integer. This is only used when there is at least one integer variable and the branch and bound algorithm is used to make variables integer.
Integer variables are internally in the algorithm also stored as floating point. Therefore a tolerance is needed to determine if a value is to be considered as integer or not. If the absolute value of the variable minus the closed integer value is less than epsint, it is considered as integer. For example if a variable has the value 0.9999999 and epsint is 0.000001 then it is considered integer because abs(0.9999999 - 1) = 0.0000001 and this is less than 0.000001
The default value for epsint is 1e-7
So by changing epsint you determine how close a value must approximate the nearest integer. Changing this tolerance value to for example 0.001 will generally result in faster solving times, but your solution is less integer.
So it is a compromise.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsint(lp, 1.0e-3); /* sets epsint to 0.001 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsint, set_infinite, is_infinite, get_infinite, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap


set_epsperturb

Specifies the value that is used as perturbation scalar for degenerative problems.

void set_epsperturb(lprec *lp, REAL epsperturb);

Return Value

set_epsperturb has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsperturb

perturbation scalar.

Remarks

The default epsperturb value is 1e-5

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsperturb(lp, 1.0e-6); /* sets epsperturb to 1e-6 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsperturb, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_mip_gap, get_mip_gap


set_epspivot

Specifies the value that is used as a tolerance pivot element to determine whether a value should be considered as 0.

void set_epspivot(lprec *lp, REAL epspivot);

Return Value

set_epspivot has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epspivot

The value that is used as a tolerance for the pivot element to determine whether a value should be considered as 0.

Remarks

The set_epspivot function specifies the value that is used as a tolerance for the pivot element to determine whether a value should be considered as 0.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epspivot specifies the tolerance to determine if a pivot element should be considered as 0. If abs(value) is less than this epspivot value it is considered as 0 and at first instance rejected as pivot element. Only when no larger other pivot element can be found and the value is different from 0 it will be used as pivot element.
The default epspivot value is 2e-7

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epspivot(lp, 1.0e-5); /* sets epspivot to 1e-5 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epspivot, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epsperturb, set_epsperturb, set_mip_gap, get_mip_gap


set_free

Sets if the variable is free.

unsigned char set_free(lprec *lp, int column);

Return Value

set_free returns TRUE (1) if the variable could be set as free, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be set. It must be between 1 and the number of columns in the lp.

Remarks

The set_free function sets if a variable is free or not. Free means a lower bound of -infinity and an upper bound of +infinity. Default a variable is not free because default it has a lower bound of 0 (and an upper bound of +infinity).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_free(lp, 1); /* will return 0 since the variable is not set as free at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_upbo, set_upbo, set_lowbo, get_lowbo, set_bounds, is_free, is_negative


set_improve

Specifies the iterative improvement level.

void set_improve(lprec *lp, int improve);

Return Value

set_improve has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

improve

Specifies the iterative improvement level. Can by any of the following values:

IMPROVE_NONE (0) | improve none
IMPROVE_FTRAN (1) | improve FTRAN. Should not be used. Experimantal, buggy and slower.
IMPROVE_BTRAN (2) | improve BTRAN. Should not be used. Experimantal, buggy and slower.
IMPROVE_SOLVE (3) | improve FTRAN + BTRAN. Should not be used. Experimantal, buggy and slower.
IMPROVE_INVERSE (4) | triggers automatic inverse accuracy control in the dual simplex, and when an error gap is exceeded the basis is reinverted

Remarks

The set_improve function specifies the iterative improvement level.
The default is IMPROVE_NONE.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_improve(lp, IMPROVE_SOLVE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_improve


set_infinite

Specifies the practical value for "infinite".

void set_infinite(lprec *lp, REAL infinite);

Return Value

set_infinite has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

infinite

The value that must be used for "infinite".

Remarks

The set_infinite function specifies the practical value for "infinite". This value is used for very big numbers. For example the upper bound of a variable without an upper bound.
The default is 1e30

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_infinite(lp, 1.0e100); /* sets infinite to 1e100 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_infinite, is_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap


set_int

Set the type of the variable. Integer or floating point.

unsigned char set_int(lprec *lp, int column, unsigned char must_be_int);

Return Value

set_int returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be set. It must be between 1 and the number of columns in the lp.

must_be_int

TRUE (1) if the variable must be integer, FALSE (0) if not.

Remarks

The set_int function defines if a variable must be integer or not. Default a variable is not integer. The argument must_be_int defines what the status of the variable becomes. From the moment there is at least one integer variable in the model, the Branch and Bound algorithm is used to make these variables integer. Note that solving times can be considerably larger when there are integer variables. See integer variables for a description about integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_int(lp, 1, TRUE); /* sets variable 1 to integer */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_int, is_binary, set_binary


set_lag_trace

Sets a flag if Lagrangian progression must be printed while solving.

void set_lag_trace(lprec *lp, unsigned char lag_trace);

Return Value

set_lag_trace has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

lag_trace

TRUE or FALSE. Print or do not print.

Remarks

The set_lag_trace function sets a flag if Lagrangian progression must be printed while solving. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_lag_trace(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_lag_trace


set_lowbo

Set the lower bound of a variable.

unsigned char set_lowbo(lprec *lp, int column, REAL value);

Return Value

set_lowbo returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the bound must be set. It must be between 1 and the number of columns in the lp.

Remarks

The set_lowbo function sets a lower bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
Note that the default lower bound of each variable is 0. So variables will never take negative values if no negative lower bound is set.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_lowbo(lp, 1, 1.0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_lowbo, set_upbo, get_upbo, set_bounds, set_free, is_free, is_negative


set_lp_name

Set the name of the lp.

unsigned char set_lp_name(lprec *lp, char *lpname);

Return Value

set_lp_name returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

lpname

The name for the lp.

Remarks

The set_lp_name sets the name of the lp.
Giving the lp a name is optional. The default name is "Unnamed".

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_lp_name(lp, "test");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_lp_name


set_mat

Set a single element in the matrix.

unsigned char set_mat(lprec *lp, int row, int column, REAL value);

Return Value

set_mat returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

Row number of the matrix. Must be between 0 and number of rows in the lp. Row 0 is objective function.

column

Column number of the matrix. Must be between 1 and number of columns in the lp.

value

Value to be set for row row, column column.

Remarks

The set_mat function sets a value in the matrix. If there was already a value for this element, it is replaced and if there was no value, it is added.
This function is not efficient if many values are to be set. Consider to use add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, add_column, add_columnex, str_add_column, set_column, set_columnex.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(2, 3);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_mat(lp, 1, 2, 3.1415927);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_row, get_mat


set_maxim

Set objective function to maximize.

void set_maxim(lprec *lp);

Return Value

set_maxim has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The set_maxim function sets the objective direction to maximize. The default of lp_solve is to minimize, except for read_lp, read_LP where the default is to maximize.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_maxim(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_maxim, set_minim, set_sense


set_maxpivot

Sets the maximum number of pivots between a re-inversion of the matrix.

void set_maxpivot(lprec *lp, int max_num_inv);

Return Value

set_maxpivot has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

max_num_inv

The maximum number of pivots between a re-inversion of the matrix.

Remarks

The set_maxpivot function sets the maximum number of pivots between a re-inversion of the matrix.
For stability reasons, lp_solve re-inverts the matrix on regular times. max_num_inv determines how frequently this inversion is done. This can influence numerical stability. However, the more often this is done, the slower the solver becomes.
The default is 42.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_maxpivot(lp, 10);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_maxpivot


set_minim

Set objective function to minimize.

void set_minim(lprec *lp);

Return Value

set_minim has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The set_minim function sets the objective direction to minimize. The default of lp_solve is to minimize, except for read_lp, read_LP where the default is to maximize.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_minim(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_maxim, is_maxim, set_sense


set_mip_gap

Specifies the MIP gap value.

void set_mip_gap(lprec *lp, unsigned char absolute, REAL mip_gap);

Return Value

set_mip_gap has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

absolute

If TRUE then the absolute MIP gap is set, else the relative MIP gap

mip_gap

The MIP gap.

Remarks

The set_mip_gap function sets the MIP gap that specifies a tolerance for the branch and bound algorithm. This tolerance is the difference between the best-found solution yet and the current solution. If the difference is smaller than this tolerance then the solution (and all the sub-solutions) is rejected. This can result in faster solving times, but results in a solution which is not the perfect solution. So be careful with this tolerance.
The default mip_gap value is 1e-9

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_mip_gap(lp, TRUE, 1.0e-8); /* sets absolute mip_gap to 1e-8 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_mip_gap, get_epsd, set_epsd, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb


set_negrange

Set negative value below which variables are split into a negative and a positive part.

void set_negrange(lprec *lp, REAL negrange);

Return Value

set_negrange has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

negrange

The negative value below which variables are split into a negative and a positive part.

Remarks

The set_negrange function specifies the negative value below which variables are split into a negative and a positive part. This value must always be zero or negative. If a positive value is specified, then 0 is taken.
In some cases, negative variables must be split in a positive part and a negative part. This is when a negative lower or upper bound is set on a variable. If a bound is less than this value, it is possibly split. The default is -1e6.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_negrange(lp, -1000);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_negrange


set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj

Set the objective function (row 0) of the matrix.

unsigned char set_obj_fn(lprec *lp, REAL *row);

unsigned char set_obj_fnex(lprec *lp, int count, REAL *row, int *colno);

unsigned char str_set_obj_fn(lprec *lp, char *row_string);

unsigned char set_obj(lprec *lp, int column, REAL value);

Return Value

set_obj_fn, set_obj_fnex, str_set_obj_fn and set_obj return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

count

Number of elements in row and colno.

row

An array with 1+column (count for set_obj_fnex) elements that contains the values of the objective function.

colno

An array with count elements that contains the column numbers of the row. However this variable can also be NULL. In that case element i in the variable row is column i.

row_string

A string with column elements that contains the values of the objective function. Each element must be separated by space(s).

column

The column number for which the value must be set.

value

The value that must be set.

Remarks

The set_obj_fn, set_obj_fnex, str_set_obj_fn functions set all values of the objective function at once.
Note that for set_obj_fn (and set_obj_fnex when colno is NULL) element 0 of the array is not considered (i.e. ignored). Column 1 is element 1, column 2 is element 2, ...
set_obj_fnex has the possibility to specify only the non-zero elements. In that case colno specifies the column numbers of the non-zero elements. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value. Thus it is almost always better to use set_obj_fnex instead of set_obj_fn. set_obj_fnex is always at least as performant as set_obj_fn. Note that unspecified values by set_obj_fnex are set to zero.
The set_obj function sets the objective value for the specified column. If multiple objective values must be set, it is more performant to use set_obj_fnex.
Note that it is advised to set the objective function before adding rows via add_constraint, add_constraintex, str_add_constraint. This especially for larger models. This will be much more performant than adding the objective function afterwards.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 2.0;
  set_obj_fn(lp, row);  /* constructs the obj: +v_1 +2 v_2 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_row, get_mat


set_obj_bound

Set initial "at least better than" guess for objective function.

void set_obj_bound(lprec *lp, REAL obj_bound);

Return Value

set_obj_bound has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

obj_bound

The initial "at least better than" guess for objective function.

Remarks

The set_obj_bound function specifies the initial "at least better than" guess for objective function. This is only used in the branch-and-bound algorithm when integer variables exist in the model. All solutions with a worse objective value than this value are immediately rejected. This can result in faster solving times, but it can be difficult to predict what value to take for this bound. Also there is the chance that the found solution is not the most optimal one.
The default is infinite.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_obj_bound(lp, 1000);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_obj_bound, , set_break_at_value, get_break_at_value set_mip_gap, get_mip_gap


set_outputstream, set_outputfile

Defines the output when lp_solve has something to report.

void set_outputstream(lprec *lp, FILE *stream);

unsigned char set_outputfile(lprec *lp, char *filename);

Return Value

set_outputstream has no return value.

set_outputfile returns TRUE (1) if the file could be opened, else FALSE (0).

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

stream

The stream to print the results to. If NULL, then output is stdout again.

filename

The file to print the results to. If NULL, then output is stdout again.

Remarks

The set_outputstream, set_outputfile functions define the output when lp_solve has something to report.
This is done at the same time as something is reported via put_logfunc. The default reporting output is screen (stdout). If set_outputstream is called to change output to another stream, then be aware that the stream is not closed automatically when delete_lp is called. Output must be set again to stdout (or NULL) to close this handle or the handle must be closed by the application via a call to fclose afterwards. This allows the application to still print to the stream even after the lp structure is cleaned up. If set_outputfile is called to change output to the specified file, then the file is automatically closed when delete_lp is called. Note that this was not the case in previous versions of lp_solve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_outputfile(lp, "log.txt");

  /*
  .
  .
  .
  */

  set_outputfile(lp, NULL); /* closes the file. Don't forget this or file stays open ... */

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_lp, print_objective, print_solution, print_constraints, print_duals, print_scales, print_tableau, print_str, print_debugdump


set_pivoting

Sets the pivot rule and mode.

void set_pivoting(lprec *lp, int pivoting);

Return Value

set_pivoting has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

pivoting

The pivot rule and mode. Can be one of the following rules:

PRICER_FIRSTINDEX (0) | Select first
PRICER_DANTZIG (1) | Select according to Dantzig
PRICER_DEVEX (2) | Devex pricing from Paula Harris
PRICER_STEEPESTEDGE (3) | Steepest Edge

Some of these values can be combined with any (ORed) of the following modes:

PRICE_PRIMALFALLBACK (4) | In case of Steepest Edge, fall back to DEVEX in primal
PRICE_MULTIPLE (8) | Preliminary implementation of the multiple pricing scheme. This means that attractive candidate entering columns from one iteration may be used in the subsequent iteration, avoiding full updating of reduced costs. In the current implementation, lp_solve only reuses the 2nd best entering column alternative
PRICE_PARTIAL (16) | Enable partial pricing
PRICE_ADAPTIVE (32) | Temporarily use First Index if cycling is detected
PRICE_RANDOMIZE (128) | Adds a small randomization effect to the selected pricer
PRICE_LOOPLEFT (1024) | Scan entering/leaving columns left rather than right
PRICE_LOOPALTERNATE (2048) | Scan entering/leaving columns alternatingly left/right

Remarks

The set_pivoting function specifies the pivot rule (rule for selecting row and column entering/leaving) and mode. The rule is an exclusive option and the mode is a modifier to the rule. This rule/mode can influence solving times considerably. Depending on the model one rule/mode can be best and for another model another rule/mode.
The default is PRICER_DEVEX | PRICE_ADAPTIVE (34).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_pivoting(lp, PRICER_FIRSTINDEX);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_pivoting, is_piv_rule, is_piv_mode


set_preferdual

Sets the desired combination of primal and dual simplex algorithms.

void set_preferdual(lprec *lp, unsigned char dodual);

Return Value

set_preferdual has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

dodual

When TRUE, the simplex strategy is set to SIMPLEX_DUAL_DUAL.
When FALSE, the simplex strategy is set to SIMPLEX_PRIMAL_PRIMAL.
See also get_simplextype

Remarks

The set_preferdual function sets the desired combination of primal and dual simplex algorithms.
set_preferdual with dodual = TRUE is a shortcut for set_simplextype(SIMPLEX_DUAL_DUAL)
set_preferdual with dodual = FALSE is a shortcut for set_simplextype(SIMPLEX_PRIMAL_PRIMAL)
The default is SIMPLEX_DUAL_PRIMAL (6).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_preferdual(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_simplextype


set_presolve

Specifies if a presolve must be done before solving.

void set_presolve(lprec *lp, int do_presolve);

Return Value

set_presolve has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

do_presolve

Specifies presolve level. Can be the (OR) combination of any of the following values:

PRESOLVE_NONE (0) | No presolve at all
PRESOLVE_ROWS (1) | Presolve rows
PRESOLVE_COLS (2) | Presolve columns
PRESOLVE_LINDEP (4) | Eliminate linearly dependent rows
PRESOLVE_SOS (32) | Convert constraints to SOSes (only SOS1 handled)
PRESOLVE_REDUCEMIP (64) | If the phase 1 solution process finds that a constraint is redundant then this constraint is deleted
PRESOLVE_DUALS (128) | Calculate duals
PRESOLVE_SENSDUALS (256) | Calculate sensitivity if there are integer variables

Remarks

The set_presolve function specifies if a presolve must be done before solving. Presolve looks at the model and tries to simplify it so that solving times are shorter. For example a constraint on only one variable is converted to a bound on this variable (and the constraint is deleted). Note that the model dimensions can change because of this, so be careful with this. Both rows and columns can be deleted by the presolve.
Note that PRESOLVE_LINDEP can result in deletion of rows (the linear dependent ones). get_constraints, get_ptr_constraints will then return only the values of the rows that are kept and the values of the deleted rows are not known anymore. The default is not (PRESOLVE_NONE) doing a presolve. The following code can be used to retrieve the values of all the variables, even if variables are deleted by presolve:

int Norig_columns, Norig_rows, i;
REAL value;

Norig_columns = get_Norig_columns(lp);
Norig_rows = get_Norig_rows(lp);
for(i = 1; i <= Norig_columns; i++) {
  value = get_var_primalresult(lp, Norig_rows + i);
  printf("%f\n", value);
}

Note that there is no possibility to get the values of deleted rows.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_presolve(lp, PRESOLVE_ROWS | PRESOLVE_COLS | PRESOLVE_LINDEP);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_presolve, is_presolve


set_print_sol

Sets a flag if all intermediate valid solutions must be printed while solving.

void set_print_sol(lprec *lp, int print_sol);

Return Value

set_print_sol has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

print_sol

FALSE (0) | No printing
TRUE (1) | Print all values
AUTOMATIC (2) | Print only non-zero values

Remarks

The set_print_sol function sets a flag if all intermediate valid solutions must be printed while solving. Can give you useful solutions even if the total run time is too long. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_print_sol(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_print_sol


set_rh

Set the value of the right hand side (RHS) vector (column 0) for one row.

unsigned char set_rh(lprec *lp, int row, REAL value);

Return Value

set_rh returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the RHS value must be set. Must be between 0 and number of rows in the lp.

value

The value of the RHS.

Remarks

The set_rh function sets the value of the RHS vector (column 0) for the specified row.
Note that row can also be 0 with this function. In that case an initial value for the objective value is set. Functions set_rh_vec, str_set_rh_vec ignore row 0 (for historical reasons) in the specified RHS vector, but it is possible to first call one of these functions and then set the value of the objective with set_rh.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_rh(lp, 1, 1.0); /* sets the value 1.0 for RHS row 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_rh_vec, str_set_rh_vec, get_rh, add_constraint, add_constraintex, str_add_constraint, get_row, get_mat


set_rh_range

Set the range on a constraint.

unsigned char set_rh_range(lprec *lp, int row, REAL deltavalue);

Return Value

set_rh_range returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row number of the constraint on which the range must be set. It must be between 1 and the number of rows in the lp.

deltavalue

The range on the constraint.

Remarks

The set_rh_range function sets a range on the constraint (row) identified by row.
Setting a range on a row is the way to go instead of adding an extra constraint (row) to the model. Setting a range doesn't increase the model size that means that the model stays smaller and will be solved faster.
If the row has a less than constraint then the range means setting a minimum on the constraint that is equal to the RHS value minus the range. If the row has a greater than constraint then the range means setting a maximum on the constraint that is equal to the RHS value plus the range.
Note that the range value is the difference value and not the absolute value.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_rh_range(lp, 1, 1.0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_rh_range


set_rh_vec, str_set_rh_vec

Set the right hand side (RHS) vector (column 0).

void set_rh_vec(lprec *lp, REAL *rh);

unsigned char str_set_rh_vec(lprec *lp, char *rh_string);

Return Value

set_rh_vec has no return value. str_set_rh_vec returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

rh

An array with row elements that contains the values of the RHS.

rh_string

A string with row elements that contains the values of the RHS. Each element must be separated by space(s).

Remarks

The set_rh_vec, str_set_rh_vec functions set all values of the RHS vector (column 0) at once.
Note that element 0 of the array is not considered (i.e. ignored). Row 1 is element 1, row 2 is element 2, ...
If the initial value of the objective function must also be set, use set_rh.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL rhs[1+2]; /* must be 1 more then number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  rhs[1] = 1.0;
  rhs[2] = 2.0;
  set_rh_vec(lp, rhs);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_rh, get_rh, add_constraint, add_constraintex, str_add_constraint, add_column, add_columnex, str_add_column, get_mat, get_column, set_column, set_columnex, get_row, set_row, set_rowex


set_row, set_rowex

set a constraint in the lp.

unsigned char set_row(lprec *lp, int row_no, REAL *row);

unsigned char set_rowex(lprec *lp, int row_no, int count, REAL *row, int *colno);

Return Value

set_row, set_rowex return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row_no

The row number that must be changed.

count

Number of elements in row and colno.

row

An array with 1+column (count for set_rowex if colno is different from NULL) elements that contains the values of the row.

colno

An array with count elements that contains the column numbers of the row. However this variable can also be NULL. In that case element i in the variable row is column i and values start at element 1.

Remarks

The set_row, set_rowex functions change the values of an existing row in the model at once. Note that add_constraint, add_constraintex, str_add_constraint add a row to the model, making the number of rows one larger. These functions change an existing row.
Note that for set_row (and set_rowex when colno is NULL) element 1 of the array is column 1, element 2 is column 2, ... element 0 is not used.
set_rowex has the possibility to specify only the non-zero elements. And in contrary to set_row, set_rowex reads the arrays starting from element 0. However when colno is NULL then set_rowex acts as set_row and then values start at element 1. When colno is provided, then it specifies the column numbers of the non-zero elements. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value. Thus it is almost always better to use set_rowex instead of set_row. set_rowex is always at least as performant as set_row. It is more performant to call these functions than multiple times set_mat. Note that unspecified values by set_rowex are set to zero.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2];

  /* Create a new LP model */
  lp = make_lp(1, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 2.0;
  set_row(lp, 1, row); /* changes the values of existing row 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_row, add_constraint, add_constraintex, str_add_constraint, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, set_add_rowmode, is_add_rowmode, get_constr_type, is_constr_type, del_constraint, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_row, get_mat


set_row_name

Set the name of a constraint (row) in the lp.

unsigned char set_row_name(lprec *lp, int row, char *new_name);

Return Value

set_row_name returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the name must be set. Must be between 0 and the number of rows in the lp.

new_name

The name for the row.

Remarks

The set_row_name sets the name of the row.
The row must already exist. row 0 is the objective function. Row names are optional.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_row_name(lp, 1, "row1");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_row_name, get_origrow_name, set_col_name, get_col_name, get_origcol_name, get_nameindex


set_scalelimit

Sets the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.

void set_scalelimit(lprec *lp, REAL scalelimit);

Return Value

set_scalelimit has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

scalelimit

The relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations

Remarks

The set_scalelimit function sets the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations (default is 5).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_scalelimit(lp, 3.1);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_scalelimit, set_scaling, get_scaling, is_integerscaling, is_scalemode, is_scaletype


set_scaling

Specifies which scaling algorithm must be used.

void set_scaling(lprec *lp, int scalemode);

Return Value

set_scaling has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

scalemode

Specifies which scaling algorithm must be used. Can by any of the following values:

SCALE_EXTREME (1) | Scale to convergence using largest absolute value
SCALE_RANGE (2) | Scale based on the simple numerical range
SCALE_MEAN (3) | Numerical range-based scaling
SCALE_GEOMETRIC (4) | Geometric scaling
SCALE_CURTISREID (7) | Curtis-reid scaling

Additionally, the value can be OR-ed with any combination of one of the following values:

SCALE_QUADRATIC (8) |
SCALE_LOGARITHMIC (16) | Scale to convergence using logarithmic mean of all values
SCALE_USERWEIGHT (31) | User can specify scalars
SCALE_POWER2 (32) | also do Power scaling
SCALE_EQUILIBRATE (64) | Make sure that no scaled number is above 1
SCALE_INTEGERS (128) | also scaling integer variables
SCALE_DYNUPDATE (256) | dynamic update

Remarks

The set_scaling function specifies which scaling algorithm must be used. This can influence numerical stability considerably. It is advisable to always use some sort of scaling.
set_scaling must be called before solve is called.
SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC, SCALE_CURTISREID are the possible scaling algorithms. SCALE_QUADRATIC, SCALE_LOGARITHMIC, SCALE_USERWEIGHT, SCALE_POWER2, SCALE_EQUILIBRATE, SCALE_INTEGERS are possible additional scaling parameters.
SCALE_POWER2 results in creating a scalar of power 2. May improve stability.
SCALE_INTEGERS results also in scaling Integer columns. Default they are not scaled.
SCALE_DYNUPDATE is new from version 5.1.1.0
It has always been so that scaling is done only once on the original model. If a solve is done again (most probably after changing some data in the model), the scaling factors aren't computed again. The scalars of the original model are used. This is not always good, especially if the data has changed considerably. One way to solve this was/is call unscale before a next solve. In that case, scale factors are recomputed.
From version 5.1.1.0 on, there is another way to make sure that scaling factors are recomputed and this is by settings SCALE_DYNUPDATE. In that case, the scaling factors are recomputed also when a restart is done. Note that they are then always recalculated with each solve, even when no change was made to the model, or a change that doesn't influence the scaling factors like changing the RHS (Right Hand Side) values or the bounds/ranges. This can influence performance. It is up to you to decide if scaling factors must be recomputed or not for a new solve, but by default it still isn't so. It is possible to set/unset this flag at each next solve and it is even allowed to choose a new scaling algorithm between each solve. Note that the scaling done by the SCALE_DYNUPDATE is incremental and the resulting scalars are typically different from scalars recomputed from scratch.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_scaling(lp, CURTISREIDSCALE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_scaling, is_integerscaling, is_scalemode, is_scaletype


set_semicont

Set the type of the variable. semi-continuous or not.

unsigned char set_semicont(lprec *lp, int column, unsigned char must_be_sc);

Return Value

set_semicont returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be set. It must be between 1 and the number of columns in the lp.

must_be_sc

TRUE (1) if the variable must be semi-continuous, FALSE (0) if not.

Remarks

The set_semicont function defines if a variable is semi-continuous or not. By default, a variable is not semi-continuous. The argument must_be_sc defines what the status of the variable becomes.
Note that a semi-continuous variable must also have a lower bound to have effect. This because the default lower bound on variables is zero, also when defined as semi-continuous, and without a lower bound it has no point to define a variable as such. The lower bound may be set before or after setting the semi-continuous status. See semi-continuous variables for a description about semi-continuous variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_lowbo(lp, 1, 2.0);
  set_semicont(lp, 1, TRUE); /* sets variable 1 to semi-continuous */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_semicont, set_lowbo


set_sense

Set objective function sense.

void set_sense(lprec *lp, unsigned char maximize);

Return Value

set_sense has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

maximize

Set sense to minimize (FALSE) or maximize (TRUE).

Remarks

The set_sense function sets the objective sense. The default of lp_solve is to minimize, except for read_lp, read_LP where the default is to maximize.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_sense(lp, TRUE); /* set object sense to maximize */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_minim, set_maxim, is_maxim


set_simplextype

Sets the desired combination of primal and dual simplex algorithms.

void set_simplextype(lprec *lp, int simplextype);

Return Value

set_simplextype has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

simplextype

The desired combination of primal and dual simplex algorithms. Can by any of the following values:

SIMPLEX_PRIMAL_PRIMAL (5) | Phase1 Primal, Phase2 Primal
SIMPLEX_DUAL_PRIMAL (6) | Phase1 Dual, Phase2 Primal
SIMPLEX_PRIMAL_DUAL (9) | Phase1 Primal, Phase2 Dual
SIMPLEX_DUAL_DUAL (10) | Phase1 Dual, Phase2 Dual

Remarks

The set_simplextype function sets the desired combination of primal and dual simplex algorithms. The default is SIMPLEX_DUAL_PRIMAL (6).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_simplextype(lp, SIMPLEX_PRIMAL_DUAL);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_simplextype, set_preferdual


set_solutionlimit

Sets the solution number that must be returned.

void set_solutionlimit(lprec *lp, int limit);

Return Value

set_solutionlimit has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

limit

The solution number that must be returned. This value gives the number of the solution that must be returned.

Remarks

This function is only valid if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algoritm is used. If there are more solutions with the same objective value, then this number specifies which solution must be returned. This can be used to retrieve all possible solutions. Start with 1 till get_solutioncount

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_solutionlimit(lp, 3); /* return the 3rd solution */

  solve(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_solutionlimit, get_solutioncount


set_timeout

Set a timeout.

void set_timeout(lprec *lp, long sectimeout);

Return Value

set_timeout has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

sectimeout

The number of seconds after which a timeout occurs. If zero, then no timeout will occur.

Remarks

The set_timeout function sets a timeout in seconds. The solve and lag_solve functions may not last longer than this time or the routines return with a timeout. The default timeout is 0, resulting in no timeout.
If a timout occurs, but there was already an integer solution found (that is possibly not the best), then solve will return SUBOPTIMAL. If there was no integer solution found yet or there are no integers or the solvers is still in the first phase where a REAL optimal solution is searched for, then solve will return TIMEOUT.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_timeout(lp, 600); /* sets a timeout of 600 seconds (10 minutes) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_timeout, time_elapsed, solve, lag_solve


set_trace

Sets a flag if pivot selection must be printed while solving.

void set_trace(lprec *lp, unsigned char trace);

Return Value

set_trace has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

trace

TRUE or FALSE. Print or do not print.

Remarks

The set_trace function sets a flag if pivot selection must be printed while solving. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_trace(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_trace


set_upbo

Set the upper bound of a variable.

unsigned char set_upbo(lprec *lp, int column, REAL value);

Return Value

set_upbo returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the bound must be set. It must be between 1 and the number of columns in the lp.

Remarks

The set_upbo function sets an upper bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
The default upper bound of a variable is infinity (well not quite. It is a very big number. The value of get_infinite).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_upbo(lp, 1, 1.0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_upbo, set_lowbo, get_lowbo, set_bounds, set_free, is_free, is_negative


set_var_branch

Specifies, for the specified variable, which branch to take first in branch-and-bound algorithm.

unsigned char set_var_branch(lprec *lp, int column, int branch_mode);

Return Value

set_var_branch returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the mode must be set. It must be between 1 and the number of columns in the lp.

branch_mode

Specifies, for the specified variable, which branch to take first in branch-and-bound algorithm.
Can by any of the following values:

BRANCH_CEILING (0) | Take ceiling branch first
BRANCH_FLOOR (1) | Take floor branch first
BRANCH_AUTOMATIC (2) | Algorithm decides which branch being taken first
BRANCH_DEFAULT (3) | Use the branch mode specified with set_bb_floorfirst

Remarks

The set_var_branch function specifies which branch to take first in branch-and-bound algorithm. This can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is BRANCH_DEFAULT (3). BRANCH_DEFAULT (3) means that the branch mode specified with set_bb_floorfirst function must be used.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_var_branch(lp, 1, BRANCH_AUTOMATIC);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_var_branch, set_bb_floorfirst, get_bb_floorfirst, set_var_weights, get_var_priority


set_var_weights

Set the weights on variables.

unsigned char set_var_weights(lprec *lp, REAL *weights);

Return Value

set_var_weights returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

weights

The weights array.

Remarks

The set_var_weights sets a weight factor on each variable. This is only used for the integer variables in the branch-and-bound algorithm. Array members are unique, real-valued numbers indicating the "weight" of the variable at the given index. The array is 0-based. So variable 1 is at index 0, variable 2 at index 1. The array must contain get_Ncolumns elements.
The weights define which variable the branch-and-bound algorithm must select first. The lower the weight, the sooner the variable is chosen to make it integer.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL weights[2];

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  weights[0] = 2;
  weights[1] = 1;

  set_var_weights(lp, weights);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_var_priority, set_var_branch, get_var_branch, set_bb_floorfirst, get_bb_floorfirst


set_verbose

Set the verbose level.

void set_verbose(lprec *lp, int verbose);

Return Value

set_verbose has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

verbose

The verbose level. Can be one of the following values:

NEUTRAL (0) | Only some specific debug messages in de debug print routines are reported.
CRITICAL (1) | Only critical messages are reported. Hard errors like instability, out of memory, ...
SEVERE (2) | Only severe messages are reported. Errors.
IMPORTANT (3) | Only important messages are reported. Warnings and Errors.
NORMAL (4) | Normal messages are reported. This is the default.
DETAILED (5) | Detailed messages are reported. Like model size, continuing B&B improvements, ...
FULL (6) | All messages are reported. Usefull for debugging purposes and small models.

Remarks

The set_verbose function sets the verbose level.
lp_solve reports information back to the user. How much information is reported depends on the verbose level. The default verbose level is NORMAL (4). lp_solve determines how verbose a given message is. For example specifying a wrong row/column index values is considered as a SEVERE error. verbose determines how much of the lp_solve message are reported. All messages equal to and below the set level are reported.
The default reporting device is the console screen. It is possible to set a used defined reporting routine via put_logfunc.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_verbose(lp, NORMAL);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_verbose, put_logfunc


solve

solve the model.

int solve(lprec *lp);

Return Value

NOMEMORY (-2) | Out of memory
OPTIMAL (0) | An optimal solution was obtained
SUBOPTIMAL (1) The model is sub-optimal. Only happens if there are integer variables and there is already an integer solution found. The solution is not guaranteed the most optimal one.
  • A timeout occured (set via set_timeout or with the -timeout option in lp_solve)
  • set_break_at_first was called so that the first found integer solution is found (-f option in lp_solve)
  • set_break_at_value was called so that when integer solution is found that is better than the specified value that it stops (-o option in lp_solve)
  • set_mip_gap was called (-g/-ga/-gr options in lp_solve) to specify a MIP gap
  • An abort function is installed (put_abortfunc) and this function returned TRUE
  • At some point not enough memory could not be allocated
INFEASIBLE (2) | The model is infeasible
UNBOUNDED (3) | The model is unbounded
DEGENERATE (4) | The model is degenerative
NUMFAILURE (5) | Numerical failure encountered
USERABORT (6) | The abort routine returned TRUE. See put_abortfunc
TIMEOUT (7) | A timeout occurred. A timeout was set via set_timeout
PROCFAIL (10) | The B&B routine failed
PROCBREAK (11) | The B&B was stopped because of a break-at-first (see set_break_at_first) or a break-at-value (see set_break_at_value)
FEASFOUND (12) | A feasible B&B solution was found
NOFEASFOUND (13) | No feasible B&B solution found

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The solve function solves the model. solve can be called more than once. Between calls, the model may be modified in every way. Restrictions may be changed, matrix values may be changed and even rows and/or columns may be added or deleted.
If set_timeout was called before solve with a non-zero timeout and a timout occurs, and there was already an integer solution found (that is possibly not the best), then solve will return SUBOPTIMAL. If there was no integer solution found yet or there are no integers or the solvers is still in the first phase where a REAL optimal solution is searched for, then solve will return TIMEOUT.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  ret = solve(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, lag_solve, statustext, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex


time_elapsed

Gets the time elapsed since start of solve.

REAL time_elapsed(lprec *lp);

Return Value

time_elapsed returns the number of seconds after solve and lag_solve has started.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The time_elapsed function returns the time in seconds since solve and lag_solve has started.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  long timeelapsed;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  timeelapsed = time_elapsed(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_timeout, set_timeout, solve, lag_solve


unscale

Unscales the model.

void unscale(lprec *lp);

Return Value

unscale has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The unscale function unscales the model. Scaling can influence numerical stability considerably. It is advisable to always use some sort of scaling.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  unscale(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scaling, get_scaling, is_integerscaling, set_scalelimit, get_scalelimit, is_scalemode, is_scaletype


write_lp, write_LP

Write an lp model to a file.

unsigned char write_LP(lprec *lp, FILE *stream);

unsigned char write_lp(lprec *lp, char *filename);

Return Value

write_lp and write_LP return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

stream

Pointer to FILE structure.

filename

Filename to write the lp model to.

Remarks

The write_lp and write_LP functions write the model to filename. write_LP needs a file pointer to an already opened file. write_lp accepts the name of the file. The latter function will generally be more convenient.

When stream or filename are NULL, then output is written to output set by set_outputstream, set_outputfile. By default this is stdout.

The model in the file will be in lp-format.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  write_lp(lp, "model.lp");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_mps, write_freemps, write_MPS, write_freeMPS


write_mps, write_freemps, write_MPS, write_freeMPS

Write an mps model to a file.

unsigned char write_MPS(lprec *lp, FILE *stream);

unsigned char write_freeMPS(lprec *lp, FILE *stream);

unsigned char write_mps(lprec *lp, char *filename);

unsigned char write_freemps(lprec *lp, char *filename);

Return Value

write_mps, write_freemps, write_MPS, write_freeMPS return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

stream

Pointer to FILE structure.

filename

Filename to write the mps model to.

Remarks

The write_mps, write_freemps, write_MPS, write_freeMPS functions write the model to filename. write_MPS, write_freeMPS need a file pointer to an already opened file. write_mps, write_freemps accept the name of the file. The latter function will generally be more convenient.

When stream or filename are NULL, then output is written to output set by set_outputstream, set_outputfile. By default this is stdout.

The model in the file will be in mps-format. The write_free* routines write files in free MPS format. The other routines write files in fixed MPS format.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  write_mps(lp, "model.mps");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, read_lp, read_LP, write_lp, write_LP, read_lp, read_LP


write_XLI

Write a model to a file via the External Language Interface.

unsigned char write_XLI(lprec *lp, char *filename, char *options, unsigned char results);

Return Value

write_XLI returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

Filename to write the model to.

options

Extra options that can be used by the writer.

results

Depends on the implementation of the XLI.

Remarks

The write_XLI function writes the model to filename via the External Language Interface. Note that set_XLI must be called before this routine to set an XLI.

See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_XLI(lp, "xli_MathProg");

  write_XLI(lp, "model.mod", "", FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_mps, write_freemps, write_MPS, write_freeMPS, read_XLI, has_XLI, is_nativeXLI, set_XLI


Calling the lpsolve API from your application

There are two ways to call the lpsolve API from an application:

  • Statically
  • Dynamically

Statically means that the lpsolve code is statically linked to the code. This means that the program does not need extra files to be able to call lpsolve since the code is already contained in the executable. The executable will thus be larger. This can only be done if you have the source code of your program and you can recompile it and link it with the lpsolve code. Not all programming languages have the possibility to statically link code. For example VB6 does not have a way to do that. The advantage of this way of calling the lpsolve library is that you don't have to provide extra files with your executable since the library is already in the exe. The disadvantage is that you must recompile (or at least link) the program with the lpsolve code when an update of lpsolve is needed. There are two ways to link your application with the lpsolve code. The first way is add the needed lpsolve source code to the project and compile it together as one unit. This is most probably only possible when the code is also written in C/C++ (however not always since for example .NET allows to link for example C# code with C code). The disadvantage of this way of working is that you have to revise your project when you use a new version of lpsolve since there could be files added or removed in the lpsolve package. Also you may have to define some defines. A better way of working is making use of the lpsolve library. Under DOS/Windows this is called lpsolve51.lib, under Unix/Linux liblpkit5.a. The advantages are that other languages (like Pascal) can also link with such a library, your project is not overloaded with the lpsolve source files and also not unimportant, the linker only takes the code from the library that you really use resulting in a smaller executable. One disadvantage is that you cannot debug and step trough the lpsolve code then, if you would want to do that.

Dynamically means that the lpsolve code is dynamically linked to your code. This means that it is linked to your program when the executable is started or even only when you make calls to the lpsolve library. The lpsolve library is then not linked with the executable and is provided in a separate file. Under Windows this is a dll (lpsolve51.dll), under Unix/Linux this is a shared library (liblpkit5.so). You must distribute this separate library with your program to make it work. The library must be located on a place that can be found by the program. There are several advantages of this way of working. Almost all programming languages have a way to call dynamic libraries or even can only call libraries that way. One example is VB6. Another advantage is that it is easier to update the package. The program doesn't have to be recompiled/relinked. You only have to provide a new lpsolve library.

Needed sources files

The following source files must at least be added to your project:

bfp/lp_MDO.c
bfp/bfp_etaPFI/lp_etaPFI.c
colamd/colamd.c
commonlib.c
myblas.c
lp_crash.c
lp_Hash.c
lp_lib.c
lp_matrix.c
lp_mipbb.c
lp_MPS.c
lp_presolve.c
lp_price.c
lp_pricePSE.c
lp_report.c
lp_scale.c
lp_simplex.c
lp_SOS.c
lp_utils.c
lp_wlp.c

All header (.h) files from lpsolve must be accessible. Most compilers use the directive -Ipath with path the location to the header files. Note that the colamd, bfp and bfp/bfp_etaPFI directories also contain header files that must be included.

If you also need the lp parser to read an lp model (read_lp, read_LP) then you must also include the files lp_rlp.c and yacc_read.c and define the symbol PARSER_LP. Most compilers use the directive -DPARSER_LP to do that. If you forget to define this symbol then the linker will give a link error saying that the symbols read_lp, read_LP are already defined. Also define the symbol YY_NEVER_INTERACTIVE (-DYY_NEVER_INTERACTIVE). This to disable the interactive mode of the lex parser and remove the dependency on isatty() routine which not available in all environments.

Note that lp_rlp.c, lp_rlp.h may give you some warnings when they are compiled. This is 'normal'. These files are not human-written, but generated from yacc/bison/lex tools from the corresponding .y and .l files. These tools don't seem to care much in generating code that is fully Ansi compliant and without warnings. Normally they can be ignored.

Note that there are more .c files in the lpsolve directory. You don't have to (even may not) include these in your project also. This because there files are either automatically included by the other source files or are needed for other functionality.

Statically link your application with the lpsolve code

With the Windows Microsoft compiler, the command could be:

cl -Ic:\lp_solve_5.1 -Ic:\lp_solve_5.1\bfp -Ic:\lp_solve_5.1\bfp\bfp_etaPFI -Ic:\lp_solve_5.1\colamd /Zp8 -DWIN32 %src% -o MyExe.exe

With the Windows gnu compiler, the command could be:

gcc -Ic:\lp_solve_5.1 -DBFP_CALLMODEL=__stdcall %src% -o MyExe.exe

Under Unix/Linux, the command could be:

cc -I/lp_solve_5.1 -I/lp_solve_5.1/bfp -I/lp_solve_5.1/bfp/bfp_etaPFI -I/lp_solve_5.1/colamd $src -o MyExe.exe -lm -ldl

%src% / $src is an environment variable containing all source files. Note the /Zp8 option with the Windows c compiler. This is also important. It ensures 8-bit alignment. This is required when you make use of the BPF functionality (see Basis Factorization Packages) and the XLI functionality (see External Language Interfaces). It doesn't matter which calling convention is used. __cdecl or __stdcall or any other calling convention is ok, even if you make use of the BFP functionality. Note the -DBFP_CALLMODEL=__stdcall option with the non-Microsoft compiler. This is to define a macro for the BFP to make sure its routines are called via the __stdcall calling convention. This is required if you want to make use of the BFP functionality. If your compiler doesn't provide a way to specify the __stdcall calling convention, then you can drop this, but the BFP functionality will then probably not work (even crash). With the Microsoft compiler this option doesn't have to be specified because it is automatically set by the lpsolve header files via the WIN32 macro. Under Unix/Linux the -lm option must be added to link with the math library and the option -ldl is used to link with the shared library. Not all Unix systems have this functionality. In that case you can drop the -ldl option but then you have to add -DLoadInverseLib=0 -DLoadLanguageLib=0 in which case you will not be able to use the BFP functionality (see Basis Factorization Packages) and also not the XLI functionality (see External Language Interfaces).

The compiler commands to compile the package with also the lp (lpsolve and CPLEX) parser functionality:
With the Windows Microsoft compiler, the command could be:

cl -Ic:\lp_solve_5.1 -Ic:\lp_solve_5.1\bfp -Ic:\lp_solve_5.1\bfp\bfp_etaPFI -Ic:\lp_solve_5.1\colamd /Zp8 -DWIN32 -DYY_NEVER_INTERACTIVE -DPARSER_LP %src% -o MyExe.exe

With the Windows gnu compiler, the command could be:

gcc -Ic:\lp_solve_5.1 -Ic:\lp_solve_5.1\bfp -Ic:\lp_solve_5.1\bfp\bfp_etaPFI -Ic:\lp_solve_5.1\colamd -DBFP_CALLMODEL=__stdcall -DYY_NEVER_INTERACTIVE -DPARSER_LP %src% -o MyExe.exe

Under Unix/Linux, the command could be:

cc -I/lp_solve_5.1 -I/lp_solve_5.1/bfp -I/lp_solve_5.1/bfp/bfp_etaPFI -I/lp_solve_5.1/colamd -DYY_NEVER_INTERACTIVE -DPARSER_LP $src -o MyExe.exe -lm -ldl

And for Unix/Linux without the possibility to use the BFP and XLI functionality:

cc -I/lp_solve_5.1 -I/lp_solve_5.1/bfp -I/lp_solve_5.1/bfp/bfp_etaPFI -I/lp_solve_5.1/colamd -DYY_NEVER_INTERACTIVE -DPARSER_LP -DLoadInverseLib=0 -DLoadLanguageLib=0 $src -o MyExe.exe -lm

Note that I used here the command prompt commands to compile the sources. It is of course also possible to use the graphical interfaces with their project files to build it. The principle stays however the same.

In the lp_solve folder, there are also some batch/script files to build the lp_solve application. This may be a good start to begin. Note that lp_solve.c is here the application. It only contains this one source file. Or you could also look at the demo program in the demo directory. Here the application is demo.c

cvc6.bat | Build the executable with the Microsoft Visual C/C++ version 6 and 7 (.NET) compiler. Note that some environment variables must be set to be able to use this batch file. These are set via a batch file provided by Microsoft: vcvars32.bat or via a special command prompt added by the Visual Studio setup.
cgcc.bat | Build the executable with the GNU compiler (DOS/Windows)
ccc | Build the executable with the Unix/Linux compiler. Enter sh ccc to execute the script.

Statically link your application with the lpsolve library

The lpsolve code is in a library file. Under Windows with the Microsoft compiler, this is in a .lib file. Under Unix and under Windows with the cygwin gcc compiler, this is in a .a file. Note for the Microsoft compiler the extension of the file. This is the same as for a dynamic library with implicit linking. This may be confusing. There is a big difference between a static library and an import library. It is unfortunate that Microsoft has used the same extension for both. A static library contains code and it is statically linked to the executable. An import library only contains symbol definitions so that the linker can resolve the symbols. An import library will thus be much smaller in size than a static library.
The static library file is provided with the lpsolve distribution and is called liblpsolve51.lib for the Microsoft compiler and liblpsolve51.a under Linux and with the cygwin gnu compiler under windows. It depends on the environment and the version how to link the static library with your code. For Linux and with the cygwin gnu compiler, just specify the .a file to the compile command line.:

cc pgr.c liblpsolve51.a

For the Microsoft visual C compiler it can be done as follows: Via the link.exe command this is done by just specifying the liblpsolve51.lib file at the command line. Via the .NET environment, this can be done via: Project, Properties, Linker, Input, Additional Dependencies. Optionally it is possible to also specify a link path via Project, Properties, Linker, General, Additional Library Directories. In Visual studio 6, this can be done via: Project, Settings, Link, Category General, Object/library modules. Optionally it is possible to also specify a link path via Project, Settings, Link, Category Input, Additional library path.
After this is done, the lpsolve functions can be called just like the lpsolve functions are linked to the program.

Dynamically link your application with the lpsolve library

lpsolve is separated from the application. So there are two separate compilations. One of the application and one of the lpsolve library. Most people will not compile the lpsolve library themselves since it is provided for several popular platforms. Therefore it is first explained how to access the lpsolve library in your application. This depends on the OS and the calling language. The most common are described here.

There are two ways of linking a dynamic library to the application: Implicit and Explicit linking. It depends on the programming language which way of linking is supported. Some support only one of the two, some can do both ways.

With Implicit Linking, the shared library file gets loaded into memory as soon as we execute the client program. If implicitly linked, the library is not removed from memory unless the application is terminated. However, if there are other applications in memory that are using the library, it is not removed from memory till the last of these applications is terminated.
If we want, we can defer the loading of the library till the time a call to the exported function in the library is not made. This is known as Explicit Linking. Explicit linking is more appropriate for interpreted languages such as Visual Basic, but it can also be used from C/C++ if we need to.

If Implicit Linking is used, a link (or import) library must be provided to the linker to resolve the symbols. In the code, the function calls are made as if all symbols are available.
If Explicit Linking is used, the library is explicitly loaded in memory via a special API call and the routines are also explicitly called via API calls. It should be clear that Explicit linking requires more coding than Implicit linking, but it allows you do load the library only when you need it and even decide at runtime from which library to call the routines.

Some may see Implicit linking as 'early binding' and Explicit linking as 'late binding'. Although it is not exactly the same, the analogy is true. Just like 'early binding', with Implicit linking, the symbols are resolved and checked at compile (actually link) time. There is strong type checking and less chance to pass wrong arguments. Just like 'late binding', with Explicit linking, the symbols are resolved and checked at runtime. The type checking is loose and there is chance that wrong parameters are passed to the function with possible disastrous results. But with the flexibility to dynamically load and call functions.
For Windows, there is a good article explaining all this: DLLs for Beginners

WINDOWS: Call the lpsolve dll from C/C++
Microsoft Visual C/C++ supports both Implicit and Explicit linking.
Implicit linking
In implicit linking, the linker matches the symbols of the library via a .lib file (the import library). Note the extension of the file. This is the same as for a static library. This may be confusing. There is a big difference between a static library and an import library. It is unfortunate that Microsoft has used the same extension for both. A static library contains code and it is statically linked to the executable. An import library only contains symbol definitions so that the linker can resolve the symbols. An import library will thus be much smaller in size than a static library. This file is provided with the lpsolve dll and is called lpsolve51.lib. It depends on the environment and the version how to do this. Via the link.exe command, this is done by just specifying the lpsolve51.lib file at the command line. Via the .NET environment, this can be done via: Project, Properties, Linker, Input, Additional Dependencies. Optionally it is possible to also specify a link path via Project, Properties, Linker, General, Additional Library Directories. In Visual studio 6, this can be done via: Project, Settings, Link, Category General, Object/library modules. Optionally it is possible to also specify a link path via Project, Settings, Link, Category Input, Additional library path.
After this is done, the lpsolve functions can be called just like the lpsolve functions are linked to the program.
Explicit linking
In explicit linking we don't use the .lib file. Instead we call the Win32 LoadLibrary( ) function, specifying the DLL's pathname as a parameter. The LoadLibrary( ) function returns an HINSTANCE parameter. This parameter is used in a call to the GetProcAddress( ) function to fetch the address of the function to be called. This address is a pointer to a function. Through this pointer the function is finally called. As can be seen in the following example, this requires some extra coding.

Example:
#include <stdio.h>

#include "lp_lib.h"

main()
{
  lprec *lp;
  HINSTANCE lpsolve;
  make_lp_func *_make_lp;
  delete_lp_func *_delete_lp;

  lpsolve = LoadLibrary("lpsolve51.dll");

  if (lpsolve == NULL) {
    printf("Unable to load lpsolve shared library\n");
    return(FALSE);
  }
  _make_lp = (make_lp_func *) GetProcAddress(lpsolve, "make_lp");
  _delete_lp = (delete_lp_func *) GetProcAddress(lpsolve, "delete_lp");

  lp = _make_lp(0,4);

  /* ... */

  _delete_lp(lp);

  FreeLibrary(lpsolve);
}
Note that the prototype definitions of the lpsolve functions (ex make_lp_func) are already defined in lp_lib.h. This same code also works with the Windows gnu gcc compiler. The only thing that must be done at compile time is defining the WIN32 macro. This will make sure that the calling convention will be __stdcall as required.
The C demo example demonstrates both implicit and explicit linking.
WINDOWS: Call the lpsolve dll from VB (also VBS Excel, Word, Access)

These environments support only Explicit linking. However it is easier than in C. Via a DECLARE statement, the API routines are declared and can immediately be called. The LoadLobrary/GetProcAddress API calls are not needed. To make things even easier, a class file is made to access the lpsolve library. It is called lpsolve51.cls. See the VB/Excel demos to see how it works.

WINDOWS: Call the lpsolve dll from VB.NET, C#

This is analog as for VB. These environments probably also allow to use implicit linking, but this is not investigated. There is also a class library made to call the lpsolve library. It is called lpsolve51.vb and lpsolve51.cs
See the demos for how it works.

Building the lpsolve shared library


integer variables

Integer variables are variables that must take an integer value (0, 1, 2, ...). A special kind of integer variables is binary variables. Binary variables can only take the value 0 or 1. They are integer variables with a maximum of 1 on them (and don't forget there is always an implicit minimum of 0 on each variable). If all variables are integer then it is a pure integer model, else it is a mixed-integer model, sometimes denoted as MIP (Mixed Integer Programming).

There are many practical uses of such variables. Binary variables for example are used to specify that something may be used or not. Integer variables say that a variable must take a multiple of a given value. For example if you want that a given variable must be a multiple of 25 then you can construct following equation:

var - 25 i = 0

with i the integer variable and var the variable that must be a multiple of 25.

There is however one drawback on integer variables. These models are harder to solve and solution time can increment exponentially. The more integer variables there are the more time it takes to solve the model. A model without the integer variables may for example be solved in 0.1 seconds while the same model with some of the variables integer can take several minutes to solve. Be aware of this. Also try to limit the solution as much as possible. If you know some extra bounds on variables then it can be very good for the solution time to set them because this limits the number of combinations the algorithm has to examine. Another negative site on integer variables is the inaccurate sensitivity analysis when integer variables are used. See Inaccurate sensitivity analysis in a model with integer variables

The integer solution is searched via the so-called 'branch-and-bound' algorithm. The model is first solved without the integer restrictions. Then it is investigated which of the integer variables are non-integer. When such a variable is found the model is split in two sub models. A first one with a minimum restriction on this variable that has the ceiling integer value and a second one with a maximum restriction on this variable that has the floor integer value. Both these sub models are optimised again and now this variable will have an integer value (if there is a solution). The algorithm then looks again if there are still (other) integer variables that have a non-integer value and if so the process is done again. This until a solution is found where are integer variables have integer values. This solution is then remembered as the best-until-now solution and the algorithm continues until it finds again an integer solution and if it is better it takes this one as the best-until-now solution. The more integer variables there are, the more combinations must be investigated and the more time it takes to solve the model.

lp_solve supports integer variables since a long time. The API call set_int can be used to define a variable as integer. The API call set_binary can be used to define a variable as binary.

In the mps format, integer variables can be specified in the COLUMNS section. See mps-format .

Example:

ROWS
 N  r_0
 L  r_1
 G  r_2
 G  r_3
 G  r_4
COLUMNS
    x1        r_0                 -1   r_1                  1
    x1        r_2                  2   r_3                 -1
    x2        r_0                 -2   r_1                  1
    x2        r_2                 -1   r_3                  3
    MARK0000  'MARKER'                 'INTORG'
    x3        r_0                0.1   r_4                  1
    MARK0001  'MARKER'                 'INTEND'
    x4        r_0                  3   r_4                  1
RHS
    RHS       r_1                  5   r_4                0.5
BOUNDS
 LO BND       x3                 1.1
ENDATA

The red lines are two lines that specify that variable x3 is an integer variable. It also has a lower bound of 1.1 set on it. The solution of this model is:
Value of objective function: -8.13333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   2
x4                   0

As can be seen, the value of x3 is 2, an integer value. If the integer restrictions would not be set on x3 then the value would be 1.1.

In the lp-format, variables can be specified as integer by putting them in the int section. See lp-format. The above mps example would be in lp-format:

min: -x1 -2 x2 +0.1 x3 +3 x4;
r_1: +x1 +x2 <= 5;
r_2: +2 x1 -x2 >= 0;
r_3: -x1 +3 x2 >= 0;
r_4: +x3 +x4 >= 0.5;
x3 >= 1.1;

int x3;


semi-continuous variables

Semi-continuous variables are variables that must take a value between their minimum and maximum or zero. So these variables are treated the same as regular variables, except that a value of zero is also accepted, even if there is a minimum bigger than zero is set on the variable.

The practical usage of such variables is the following. If the variable is taken then take at least the minimum or else don't take it at all. For example in a blending problem this could mean if an amount of a raw material is taken then it must be at least the minimum or else take none at all. This because less than the minimum cannot be weighted for example. If a fixed minimum would be set then it would not be allowed to not to use the raw material at all. However via semi-continuous variables it is possible to state this kind of restrictions.

Since release 4, lp_solve has supported semi-continuous variables via the API call set_semicont or in the mps format in the bounds section via the SC bound type. See mps-format. If there is no minimum set on a semi-continuous variable then the default minimum is 1. The SC bound type normally needs the maximum in field 4. However this value may be omitted. In that case an upper bound of infinity is taken.

Example:

ROWS
 N  r_0
 L  r_1
 G  r_2
 G  r_3
 G  r_4
COLUMNS
    x1        r_0                 -1   r_1                  1
    x1        r_2                  2   r_3                 -1
    x2        r_0                 -2   r_1                  1
    x2        r_2                 -1   r_3                  3
    x3        r_0                  4   r_4                  1
    x4        r_0                  3   r_4                  1
RHS
    RHS       r_1                  5   r_4                0.5
BOUNDS
 SC BND       x3                  10
 LO BND       x3                 1.1
ENDATA

The red lines are two lines that specify that variable x3 is a semi-continuous variable with a maximum of 10 and a minimum of 1.1. If the LO entry would not be there then the minimum would be 1, the default. If the 10 is omitted in the SC entry then there is no maximum.

Since lp_solve version 4.0.1.10, lp_solve also supports semi-continuous variables in the lp-format See lp-format. The above mps example would be in lp-format:

max: x1 + 2x2 - 4x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

sec x3;

If the line x3 >= 1.1; is omitted then there is an implicit minimum of 1. If the line x3 <= 10; is omitted then there is no maximum on the variable. The new section sec is analogue as the int section and specifies all the variables that are semi-continuous. Multiple variables can be specified separated by a comma (,) or space.

The solution for this model is:

Value of objective function: 6.83333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   0
x4                   0.5

Why does it take 0 and not 1.1? Because the objective value is better if 0 is taken than 1.1. If the variable would not be semi-continuous (delete sec x3;) then the solution would be:

Value of objective function: 3.93333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   1.1
x4                   0

6.83333 is a better solution than 3.93333

If the model is changed to:

max: x1 + 2x2 - 0.1x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

sec x3;

Only the cost of x3 is changed here from -4 to -0.1. The solution of this model is:

Value of objective function: 8.22333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   1.1
x4                   0

Now the solver takes the 1.1 as value because this solution is better than if 0 would be taken. This can be proven with the following model:

max: x1 + 2x2 - 1x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 <= 0;

sec x3;

This gives as solution:

Value of objective function: 6.83333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   0
x4                   0.5

6.83333 is worse than 8.22333, thus the solver takes the 1.1 solution.

Note that semi-continuous variables may be combined with integer variables. The same rules then apply, but the variable must also be integer then.

For example:

max: x1 + 2x2 - .1x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

sec x3;

int x3;

The solution of this model is:

Value of objective function: 8.13333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   2
x4                   0

Because x3 must now be integer, it takes the value 2 instead of 1.1. The objective value 8.13333 is still better than he objective value if x3 would be 0 (6.83333).

In the mps format this can be either specified via the SI attribute or via SC attribute with the MARKER INTORG, MARKER INTEND in the COLUMNS section:

ROWS
 N  r_0
 L  r_1
 G  r_2
 G  r_3
 G  r_4
COLUMNS
    x1        r_0                 -1   r_1                  1
    x1        r_2                  2   r_3                 -1
    x2        r_0                 -2   r_1                  1
    x2        r_2                 -1   r_3                  3
    x3        r_0                0.1   r_4                  1
    x4        r_0                  3   r_4                  1
RHS
    RHS       r_1                  5   r_4                0.5
BOUNDS
 SI BND       x3                  10
 LO BND       x3                 1.1
ENDATA

Or

ROWS
 N  r_0
 L  r_1
 G  r_2
 G  r_3
 G  r_4
COLUMNS
    x1        r_0                 -1   r_1                  1
    x1        r_2                  2   r_3                 -1
    x2        r_0                 -2   r_1                  1
    x2        r_2                 -1   r_3                  3
    MARK0000  'MARKER'                 'INTORG'
    x3        r_0                0.1   r_4                  1
    MARK0001  'MARKER'                 'INTEND'
    x4        r_0                  3   r_4                  1
RHS
    RHS       r_1                  5   r_4                0.5
BOUNDS
 SC BND       x3                  10
 LO BND       x3                 1.1
ENDATA


Special Ordered Sets

Special Ordered Sets (SOS)

Special Ordered Sets of Type One

A Special Ordered Set of type One (SOS1) is defined to be a set of variables for which not more than one member from the set may be non-zero in a feasible solution. All such sets are mutually exclusive of each other, the members are not subject to any other discrete conditions and are grouped together consecutively in the data.

The normal use of an SOS1 is to represent a set of mutually exclusive alternatives ordered in increasing values of size, cost or some other suitable units appropriate to the context of the model. This representation is a discrete programming extension of the separable programming model. There is a strong implied assumption that a non-linear function represented in this way is single valued over the range of its argument.

Consider a function g(y) represented by the points P1,...,PK as shown in figure 2.

Figure 2

Given the tabulated coordinates [image] k=1,...,K, the function g(y) may be represented as

(1)

where

(2)

(3)

The discrete function can take only one of the [image] possible values weighted by the variables [image] , of which only one can be non-zero, and that must have the value one.

This requirement could be expressed by restricting each xk to be a binary variable but the alternative of defining them collectively as a special ordered set of type one, which is a direct statement of their nature, leads to a more efficient solution process.

The weighting variables xk are called special ordered set type one variables and the rows (1), (2), and (3) are called function rows, reference rows and convexity rows respectively. Should the SOS1's not represent a modelling of discrete, separable variables then none of these rows need actually exist, but there is an advantage to the system if it is aware of the reference rows at least.

Special Ordered Sets of Type Two

A Special Ordered Set of type Two (SOS2) is a set of consecutive variables in which not more than two adjacent members may be non-zero in a feasible solution. All such sets are mutually exclusive of each other, the members are not subject to any other discrete conditions and each set is grouped together consecutively in the data.

SOS2s were introduced to make it easier to find global optimum solutions to problems containing piecewise linear approximations to a non-linear function of a single argument (as in classical Separable Programming). The overall problem has an otherwise LP or an IP structure except for such non-linear functions.

Consider the function [image] illustrated in Figure 3 as a piecewise linear function in one variable defined over the closed intervals [image] , where the coordinates [image] , represent points P1,...,P K.

Figure 3

Any point [image] in the closed interval [image] may be written as

where

.

Similarly, as [image] is linear in the interval, it can be written as

.

This leads to the representation of [image] using a set of weighting variables, [image] , by the equality

(4)

where

(5)

. (6)

Plus the added condition that not more than two adjacent variables can be non-zero at any one time.

The weighting variables xk are called the special ordered set type two variables and the rows (4), (5), and (6) are called function rows, reference rows and the convexity rows respectively, as in equations (1), (2) and (3) of Topic "Special Ordered Sets of Type One". Should the SOS2's not represent separable functions then none of these rows need actually exist, but there is an advantage to the system if it is aware of the reference rows at least.

The lp_solve implementation of SOS is the following:

A specially ordered set of degree N is a collection of variables where at most N variables may be non-zero. The non-zero variables must be contiguous (neighbours) sorted by the ascending value of their respective unique weights. In lp_solve, specially ordered sets may be of any cardinal type 1, 2, and higher, and may be overlapping. The number of variables in the set must be equal to, or exceed the cardinal SOS order.

lp_solve supports Special Ordered Sets via the API interface, in the MPS format and in the lp format (from release 4.0.1.11).

Below is a representation of a SOS in an MPS file, where each SOS is defined in its own SOS section, which should follow the BOUNDS section.

0        1         2         3         4
1234567890123456789012345678901234567890
SOS
 Sx CaseName  SOSName.  SOSpriority.
    CaseName  VarName1  VarWeight1..
    CaseName  VarName2  VarWeight2..

    CaseName  VarNameN  VarWeightN..

x at the second line, position 3, defines is the order of the SOS. Due to limitations in the MPS format, N is restricted to the 1..9 range. Each SOS should be given a unique name, SOSName. lp_solve does not currently use case names for SOS'es and the CaseName could be any non-empty value. The SOSpriority value determines the order in which multiple SOS'es are analysed in lp_solve. VarWeight specifies the weight each variable gets.

SOS1 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S1 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA

In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 1;

The SOS definition says that either x1 or x2 or x3 or x4 or x5 may be taken.

The solution is:
Value of objective function: -90

Actual values of the variables:
x1                   0
x2                   0
x3                   30
x4                   0
x5                   0

SOS2 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S2 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA

In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 2;

The SOS definition says that two consecutive variables from x1, x2, x3, x4, x5 may be taken.

The solution is:
Value of objective function: -91

Actual values of the variables:
x1                   0
x2                   1
x3                   30
x4                   0
x5                   0

SOS3 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S3 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA

In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 3;

The SOS definition says that three consecutive variables from x1, x2, x3, x4, x5 may be taken.

The solution is:
Value of objective function: -93.75

Actual values of the variables:
x1                   0
x2                   1
x3                   30.75
x4                   0.25
x5                   0

SOS4 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S4 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA

In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 4;

The SOS definition says that four consecutive variables from x1, x2, x3, x4, x5 may be taken.

The solution is:
Value of objective function: -233.75

Actual values of the variables:
x1                   40
x2                   1
x3                   50.75
x4                   20.25
x5                   0

SOS5 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S5 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA

In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 5;

The SOS definition says that five consecutive variables from x1, x2, x3, x4, x5 may be taken.

The solution is:
Value of objective function: -235.75

Actual values of the variables:
x1                   40
x2                   1
x3                   50.75
x4                   20.25
x5                   1


Ratio's

Constraints

Linear constraints are of the form:

a1 x1 + a2 x2 + a3 x3 + ... >= minimum

a1 x1 + a2 x2 + a3 x3 + ... <= maximum

Where minimum and maximum are constants.

lp_solve can only handle these kind of Linear equations. However sometimes there are tricks to convert an equation that seems non-Linear at first sight to a Linear equation. One of these is ratio's:

a11 x1 + a12 x2 + a13 x3 + ... <= minimum
a21 x1 + a22 x2 + a23 x3 + ...

On condition that a21 x1 + a22 x2 + a23 x3 + ... is positive, this is equal to:

a11 x1 + a12 x2 + a13 x3 + ... <= minimum * (a21 x1 + a22 x2 + a23 x3 + ...)

If the denominator is always negative, then it can be converted to:

a11 x1 + a12 x2 + a13 x3 + ... >= minimum * (a21 x1 + a22 x2 + a23 x3 + ...)

Let's continue with the case that the denominator is positive, then the equation is also equal to:

a11 x1 + a12 x2 + a13 x3 + ... - minimum * (a21 x1 + a22 x2 + a23 x3 + ...) <= 0

Or

(a11 - minimum * a21) x1 + (a12 - minimum * a22) x2 + (a13 - minimum * a23) x3 + ... <= 0

And there we have again a Linear equation. The same can be done for a maximum or equality of course. Don't forget that there is one assumption: the denominator is positive or negative. If it can be both, then this trick cannot be used.

One example of this is for example that it is required that two variables must have a ration of 1/2. For example:

x1 = 1/2
x2

With the formula above, this gives:

x1 - 0.5 x2 = 0

Adding this equation will result in the fact that x2 will be two times larger than x1. Again in the assumption that x2 stays positive.

Oh, and what if the denominator is zero? Division by zero is undefined and cannot give a real value. In the above example with two variables, if x2 is zero, then x1 is also forced to be zero. That is the side effect by converting the non-Linear equation to a Linear equation.

Objective function

max   c0 + c1 x1 + c2 x2 + c3 x3 + ...
      d0 + d1 x1 + d2 x2 + d3 x3 + ...

s.t.  ai1 x1 + ai2 x2 + ai3 x3 + ... <= bi
      xj >= 0

Note that c0 and d0 are constants. They are optional and not required for this solution.
Also note that the explanation uses <= constraints, but they can as well be >= constraints without any modification.
And as a last note, this text uses maximization of the objective function, but minimization works as good without any modification.

Linear programming only accepts models with equations in the first degree. The objective function however has a numerator and denominator so this seems not possible to solve with pure linear programming. However there is a trick to overcome to this problem. This model can be transformed to another model that is pure linear. When the solution is found to this transformed model, the results can be recalculated back to the original model.

There is only one condition to make this possible: the denominator must be strictly positive (or negative, but in that case you can multiply numerator and denominator by -1 such that the denominator becomes positive).

      d0 + d1 x1 + d2 x2 + d3 x3 + ... > 0

Again note the > sign. The denominator may also not become zero. If the transformed model returns a solution saying that it is zero, then the solution is invalid.

Now with this assumption in mind, we can introduce a new variable y0:

      y0 =                   1
            d0 + d1 x1 + d2 x2 + d3 x3 + ...

Then the model can also be written as:

max   c0 y0 + c1 x1 y0 + c2 x2 y0 + c3 x3 y0 + ...

s.t.  ai1 x1 + ai2 x2 + ai3 x3 + ... <= bi
      y0 =                   1
            d0 + d1 x1 + d2 x2 + d3 x3 + ...
      y0, xj >= 0

The constraints can also be multiplied by y0 and the y0 constraint can be written differently:

max   c0 y0 + c1 x1 y0 + c2 x2 y0 + c3 x3 y0 + ...

s.t.  ai1 x1 y0 + ai2 x2 y0 + ai3 x3 y0 + ... <= bi y0
      d0 y0 + d1 x1 y0 + d2 x2 y0 + d3 x3 y0 + ... = 1
      y0, xj y0 >= 0

Note again that this can only be done if y0 > 0

Now also make following substitution:

      yj = xj y0

Also put the bi y0 term to the left:

max   c0 y0 + c1 y1 + c2 y2 + c3 y3 + ...

s.t.  -bi y0 + ai1 y1 + ai2 y1 + ai3 y3 + ... <= 0
      d0 y0 + d1 y1 + d2 y2 + d3 y3 + ... = 1
      yj >= 0

All yj are variables (j starting from 0)

This new transformed model is an exact transformation of the original model, but with the advantage that it is a pure linear model. Also note that this model has one extra variable (y0) with coefficients in the matrix which are the negative of the right hand side (-bi y0). A constraint is also added requiring the constant term in the denominator times the new variable (d0 y0) plus the denominator terms involving the transformed variables to equal 1. The transformed model uses the same aij's as the original. Its right hand sides are all 0's except the one in the new constraint. The objective function does not have a denominator term and the objective function altered to include the numerator constant times the new variable y0.
This model can now be solved with lp_solve. Then to get the solution of the original model we must do a reverse transformation of this solution. This can be easily done:

      yj = xj y0

So:

      xj = yj / y0
Example

Suppose that it is desirable to solve the following problem.

max         1.8 x1 + 1.7 x2
       10 + 4.0 x1 + 4.1 x2

s.t.  1.5 x1 +   x2 <= 6
      3.0 x1 + 4 x2 <= 20
      x1, x2 >= 0

Then the transformed problem is:

max            1.8 y1 + 1.7 y2

s.t.   -6 y0 + 1.5 y1 +     y2 <= 0
      -20 y0 + 3.0 y1 +   4 y2 <= 0
       10 y0 + 4.0 y1 + 4.1 y2 = 1
          y0, y1, y2 >= 0

The solution of this transformed model is:

Value of objective function: 0.289916

Actual values of the variables:
y1                      0.0420168
y2                        0.12605
y0                      0.0315126

Dual values with from - till limits:
                           Dual value            From            Till
R1                           0.342437     -0.03278689       0.1090909
R2                         0.04222689      -0.3076923       0.1156069
R3                           0.289916               0          1e+030
y1                                  0         -1e+030          1e+030
y2                                  0         -1e+030          1e+030
y0                                  0         -1e+030          1e+030

The value of the objective function of this transformed model is also the value of the objective function of the original model. The values of the original xi variables are calculated by dividing the yi values by y0:

x1 = y1 / y0 = 0.0420168 / 0.0315126 = 1.33333333
x2 = y2 / y0 = 0.12605 / 0.0315126 = 4

Plugging back into the original problem, the numerator equals 9.2; the denominator, 31.73, and their fraction 0.289916 (the objective function value reported). One may also recover the dual values or reduced costs. In this case since the rows are multiplied by one over the denominator, the original values may be recovered by dividing through by the denominator (1 / y0 or multiplying them by y0). Thus the effective dual value for constraint 1 is 0.01079, and constraint 2 is 0.0013307. Constraint 3 has no analogue in the original problem, and thus, is not transformed. The From - Till limits can also be recalculated back by dividing them by y0 and correcting these values with the bi y0 term.

Comments

This is an exact transformation as long as the denominator remains strictly positive. The formulation fails if y0 equals zero in the optimal solution. Much research has been done on fractional programming. The original development appears in Charnes and Cooper (1962). A historical perspective and literature review can be found in Schaible and Ibaraki.


Sensitivity

Sensitivity or post-optimal analysis is extra information that is provided about the current optimal solution. lp_solve provides a substantial amount of sensitivity information. Several API calls are available to retrieve the sensitivity: get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult. The lp_solve program doesn't show the sensitivity by default. So to see the sensitivity information, use the -S4 option. The best way to explain this is via an example.

min: +COLONE +3 COLTWO +6.24 COLTHREE +0.1 COLFOUR;
THISROW: +78.26 COLTWO +2.9 COLFOUR >= 92.3;
THATROW: +0.24 COLONE +11.31 COLTHREE <= 14.8;
LASTROW: +12.68 COLONE +0.08 COLTHREE +0.9 COLFOUR >= 4;
COLONE >= 28.6;
COLFOUR >= 18.00;
COLFOUR <= 48.98;

The solution of this model is (with the -S4 option):

Value of objective function: 31.7828

Actual values of the variables:
COLONE               28.6
COLTWO               0
COLTHREE             0
COLFOUR              31.8276

Actual values of the constraints:
THISROW              92.3
THATROW              6.864
LASTROW              391.293

Objective function limits:
                              From            Till          FromValue
COLONE                              0          1e+030         -1e+030
COLTWO                       2.698621          1e+030       0.5123946
COLTHREE                            0          1e+030       0.7016799
COLFOUR                             0       0.1111679         -1e+030

Dual values with from - till limits:
                          Dual value          From            Till
THISROW                   0.03448276             52.2         142.042
THATROW                            0          -1e+030          1e+030
LASTROW                            0          -1e+030          1e+030
COLONE                             1        -1.943598        61.66667
COLTWO                     0.3013793       -0.6355993       0.5123946
COLTHREE                        6.24         -4841.16       0.7016799
COLFOUR                            0          -1e+030          1e+030

First look at 'Objective function limits' (via API obtained by get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex). There is a list of all variables with for each variable 3 values. From, Till and FromValue. From - Till gives the limits where between the objective value may vary so that the solution stays the same. For example, variable COLFOUR has a From value of 0 and a Till value of 0.1111679. The coefficient in the objective function of this variable is 0.1. This means that as this coefficient varies between 0 and 0.1111679, the solution doesn't change. The values for the variables and the constraints will remain unchanged as long as the objective coefficient stays in this range. The objective function value will vary of course and also the sensitivity information of the other variables, but the solution will stay the same if only the objective coefficient value for this variable is changed. When the objective coefficient of variable COLFOUR is above 0.1111679 then the solution will change. The FromValue is only meaningful if the variable has a value of 0 (rejected). This is the value that this variable becomes when the From (minimization) or Till (maximization) value is reached. For example, the variable COLTWO that has an amount of 0 will become 0.5123946 if the coefficient in the objective function of COLTWO reaches 2.698621. Note that you only get information about this variable. There is no information what the values will be of the other variables. In a blending example where the coefficients of the objective function are generally the prices of ingredients this information tells you at what point a price may change to have the same composition and the FromValue says at what value a relected ingredient will be taken when the price lowers till the lower range value.

Another piece of information are the Dual values with the from - till limits. This is provided for both the constraints and the variables. The information is the same for both. For example, constraint THISROW has a dual value of 0.03448276 with a From value of 52.2 and a Till value of 142.042. This means that the Dual value specifies how much the objective function will vary if the constraint value is incremented by one unit. This implies that there is only a non-zero dual value if the constraint is active. Constraint THATROW for example is not active because the constraint is <= 14.8, but its value is only 6.864. However constraint THISROW is >= 92.3 and its value is also 92.3, thus active. If the constraint is changed to 93.3 (+1), then the objective value will be the current value + change * dual value = 31.7828 + 1 * 0.03448276 = 31.81728. However this is only true for the range From - Till, which means that the dual value stays only the same as long as the constraint lies between the From - Till limits. The moment that you are outside of these limits, the dual value will change. The dual value gives a very good indication how much this restriction costs. If the dual value is very high then this constraint is very influential on the objective function and if you are able to change it a bit then the solution will be much better. Also the sign of the dual value has a meaning. A positive value means that as the restriction becomes larger, the objective value will be larger, and as it becomes more negative, the objective value will be smaller. Also note that changes in the restrictions, even between the limits, can cause the solution to change. The from - till limits only say that the cost will remain the same, nothing less, nothing more.

Inaccurate sensitivity analysis in a model with integer variables

The sensitivity analysis doesn't take the integer restrictions in account. This is almost impossible since it would ask too much calculation time. In particular the from - till limits on both the objective function and the dual values are trustworthy. They only apply for the current solution without the integer restrictions. Keep this in mind. The dual values are correct.


Basis Factorization Packages

Basis Factorization Package (shortened as BFP) is a unique lp_solve feature. Considerable effort has been put in this new feature and we have big expectations for this. BFP is a generic interface model and users can develop their own implementations based on the provided templates. We are very interested in providing as many different BFPs as possible to the community.

Until version 4, lp_solve always used the product form of the inverse (etaPFI) to perform its matrix pivot changes. However there are other methods like LU decomposition. Each method has its advantages and disadvantages. Some are faster/slower, other are numerical more/less stable. The speed and stability of a solver depends considerably on the BFP. One model will be solved better with one BFP and another with another BFP.
The following is a personal comment on the different BFPs by Kjell Eikland:

"Personally, I go for numerical robustness and size capability LUSOL is the one to beat. The LUSOL code has tremendous features for tackling even the toughest models, balancing accuracy and fill-in to a phenomenal extent. I have experimented with a maximum update limit before refactorization of 1500, and even at that level LUSOL was much more reliable than etaPFI! LUSOL does extremely well with some classes of very tough models, such as the PILOT models. For simple, not too large network-like models with little fill-in, etaPFI can be extremely fast and maintain accuracy if the numerics are not too bad. etaPFI v2 is typically both faster and numerically more robust and can handle much more challenging models than v1. The main reason is that v2 typically has quite a bit less fill-in and better pivot management, which automatically leads to better speed and accuracy. GLPK has an LU implementation model that is conceptually/numerically inferior to LUSOL, but updating and btran can be faster. For medium size models of a higher than average toughness, GLPK is definitely a good choice. However, in my experience GLPK is not robust from the perspective of memory management. With some unusually hard models prone to fill-in it simply bombs, which is not good in a production environment. Accuracy management is limited to refactorization (just like etaPFI)."

lp_solve version 5.1 has the etaPFI from lp_solve v3.2 built in as default engine. This BFP is versioned 1.0 to distinguish it from the newer external bfp_etaPFI version 2. In addition two other BFPs are included for both Windows and Linux: bfp_LUSOL.dll, bfp_etaPFI.dll for Windows and libbfp_LUSOL.so, libbfp_etaPFI.so for Linux. The standalone bfp_etaPFI is v2.0 and includes advanced column ordering using the COLAMD library, as well as better pivot management for stability. For complex models, however, the LU factorization approach is much better, and lp_solve now includes LUSOL as one of the most stable engines available anywhere. LUSOL was originally developed by Prof. Saunders at Stanford, and it has now been ported to C and enhanced by Kjell Eikland. It is expected that the LUSOL source will be made available.

These BFPs are not statically linked, but are dynamically loaded when requested (except for the default etaPFI engine). It is even possible for people to write their own BFP. Under Windows, a BFP is provided as DLL (bfp_*.dll), under UNIX/LINUX as a dynamic linked library (libbfp_*.so).
To change the BFP with lp_solve, use the option -bfp <filename>. Via the API, use set_BFP. filename is the name of the dynamic linked library. It is possible to provide a path to this name to be sure that the BFP from the specified location is used. If no path is given, then it depends on the OS where it will be searched.

Under Windows, the following search order is used:

  1. Current directory.
  2. A semi-colon-separated (;) list of directories in the user's PATH environment variable.

Under Unix/Linux, following search order is used:

  1. A colon-separated (:) list of directories in the user's LD_LIBRARY_PATH environment variable.
  2. The list of libraries specified in /etc/ld.so.cache (which is generated from /etc/ld.so.conf).
  3. /lib, followed by /usr/lib. Note the order here; this is the reverse of the order used by the old a.out loader. The old a.out loader, when loading a program, first searched /usr/lib, then /lib (see the man page ld.so(8)). This shouldn't normally matter, since a library should only be in one or the other directory (never both), and different libraries with the same name are a disaster waiting to happen.

Under Unix/Linux it is standard that a library has the lib prefix and a .so postfix. Under Windows there is no prefix and a .dll postfix.
To make the calling structure for BFPs uniform across different types of OS, lp_solve automatically adds the prefix and postfix if not provided. So the following commands are valid for both Windows and Unix/Linux:

lp_solve -bfp bfp_LUSOL input.lp
lp_solve -bfp ./bfp_LUSOL input.lp

The latter makes sure that the BFP is searched in the current directory, especially for Unix/Linux.

Note that for the time being only bfp_etaPFI can be recompiled by you using the included source. A third BFP based on GLPK may be included later, but license issues must first be resolved. In the interim, you may experiment with the working sample BFP interface files for GLPK.

If you compile BFPs yourself, make sure that under Windows, you use __stdcall convention and use 8 byte alignments. This is needed for the BFPs to work correctly with the general distribution of lp_solve and also to make sharing BFPs as uncomplicated as possible.


External Language Interface

External Language Interfaces

To facilitate the development of other model language interfaces, a quite simple "eXternal Language Interface" (XLI) has been defined, which allows lp_solve to be dynamically configured (at run-time) to use alternative means to read and write the MIP model. lp_solve has several build-in interfaces to models: mps, lp, CPLEX lp. XLI allows implementing a custom reader and writer for other model layouts.
At present, a MathProg (AMPL subset) interface is in place, and the template is provided for other platforms. An XML-based interface is likely to come fairly soon also. Obviously, all existing interface methods will remain unchanged.
This feature again gives a unique flexibility and openness to the user and developer community that we have quite some expectations for.
If you write your own XLI, we would be glad if you would share your code with the lp_solve community. We are very interested in providing as many different XLIs as possible to the community.

Under Windows, an XLI is provided as DLL (xli_*.dll), under UNIX/LINUX as a dynamic linked library (libxli_*.so).
The lp_solve program provides a way to specify an XLI for reading a model and an XLI for writing the model. These can be different so that a model in one format can be converted to another format. It is still possible to both read and write the models with the build-in formats (mps, lp, CPLEX lp) and you can combine with the XLI.
With the lp_solve program, to set the XLI to read the model, use the option -rxli xliname filename [datafilename]. Via the API, use read_XLI. xliname is the name of the dynamic linked library. It is possible to provide a path to this name to be sure that the XLI from the specified location is used. If no path is given, then it depends on the OS where it will be searched.

Under Windows, the following search order is used:

  1. Current directory.
  2. A semi-colon-separated (;) list of directories in the user's PATH environment variable.

Under Unix/Linux, following search order is used:

  1. A colon-separated (:) list of directories in the user's LD_LIBRARY_PATH environment variable.
  2. The list of libraries specified in /etc/ld.so.cache (which is generated from /etc/ld.so.conf).
  3. /lib, followed by /usr/lib. Note the order here; this is the reverse of the order used by the old a.out loader. The old a.out loader, when loading a program, first searched /usr/lib, then /lib (see the man page ld.so(8)). This shouldn't normally matter, since a library should only be in one or the other directory (never both), and different libraries with the same name are a disaster waiting to happen.
filename is the name (with optional path) of the modelname. datafilename is optional and depends on the XLI implementation if needed/required/possible. For example for the MathProg XLI, this is a possible optional datafilename containing the data. Note that this name may not start with a minus sign (-)

Under Unix/Linux it is standard that a library has the lib prefix and a .so postfix. Under Windows there is no prefix and a .dll postfix.
To make the calling structure for XLIs uniform across different types of OS, lp_solve automatically adds the prefix and postfix if not provided. So the following commands are valid for both Windows and Unix/Linux:

lp_solve -rxli xli_MathProg input.mod
lp_solve -rxli ./xli_MathProg input.mod

The latter makes sure that the XLI is searched in the current directory, especially for Unix/Linux.

With the lp_solve program, to set the XLI to write the model, use the option -wxli xliname filename. Via the API, use set_XLI to set the XLI library and write_XLI to write the model. xliname is the name of the dynamic linked library. It is possible to provide a path to this name to be sure that the XLI from the specified location is used. If no path is given, then it depends on the OS where it will be searched.

Under Windows, the following search order is used:

  1. Current directory.
  2. A semi-colon-separated (;) list of directories in the user's PATH environment variable.

Under Unix/Linux, following search order is used:

  1. A colon-separated (:) list of directories in the user's LD_LIBRARY_PATH environment variable.
  2. The list of libraries specified in /etc/ld.so.cache (which is generated from /etc/ld.so.conf).
  3. /lib, followed by /usr/lib. Note the order here; this is the reverse of the order used by the old a.out loader. The old a.out loader, when loading a program, first searched /usr/lib, then /lib (see the man page ld.so(8)). This shouldn't normally matter, since a library should only be in one or the other directory (never both), and different libraries with the same name are a disaster waiting to happen.
filename is the name (with optional path) of the modelname.

Under Unix/Linux it is standard that a library has the lib prefix and a .so postfix. Under Windows there is no prefix and a .dll postfix.
To make the calling structure for XLIs uniform across different types of OS, lp_solve automatically adds the prefix and postfix if not provided. So the following commands are valid for both Windows and Unix/Linux:

lp_solve -wxli xli_MathProg output.mod
lp_solve -wxli ./xli_MathProg output.mod

The latter makes sure that the XLI is searched in the current directory, especially for Unix/Linux.

Creating an XLI

To create your own XLI, you have to create a DLL/shared library that implements the following routines:

MYBOOL XLI_CALLMODEL xli_name(void)

Return Value

xli_name must return a string describing the XLI library.

Parameters

None

MYBOOL XLI_CALLMODEL xli_readmodel(lprec *lp, char *model, char *data, char *options, int verbose);

Return Value

Must return TRUE or FALSE to indicate if successfull (TRUE) or not (FALSE).

Parameters

lp

An initial lp structure created via make_lp(0, 0).

model

Filename to read the model from.

data

Optional data to read data from. For example used by the MathProg XLI.

options

Extra options that can be used by the reader.

verbose

The verbose level. Can be used to output more or less information while creating the model.

Remarks

This routine must be used to create the model. Via the provided lp variable all lpsolve API routines can be accessed to create the model.
Note that xli_readmodel already provides an lp structure. You must use this one to build the model. The lp structure is created via make_lp(0, 0). So it contains 0 rows and 0 columns.

MYBOOL XLI_CALLMODEL xli_writemodel(lprec *lp, char *filename, char *options, MYBOOL results);

Return Value

Must return TRUE or FALSE to indicate if successfull (TRUE) or not (FALSE).

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

Filename to write the model to.

options

Extra options that can be used by the writer.

results

...

Remarks

This routine must be used to write the model. Via the provided lp variable all lpsolve API routines can be accessed to write the model.

lp_XLI1.c must be included at the beginning of the source file. This to include an extra routine xli_compatible needed by the lpsolve library to check the compatibility.

If you want to create XLIs yourself, make sure that under Windows, you use 8 byte alignments. This is needed for the XLIs to work correctly with the general distribution of lp_solve and also to make sharing XLIs as uncomplicated as possible. If not, it will likely crash. It doesn't matter which calling convention is used to compile the library. The XLI_CALLMODEL directive makes sure that the calling convention of the needed routines is always ok independent of the calling convention specified in the project.
Also under windows, a definition file must be added. If this is not done, it will not work. The definition file should have extention .def and contain the following:

EXPORTS
  xli_compatible           @1
  xli_name                 @2
  xli_readmodel            @3
  xli_writemodel           @4

The definition file must be added to the project. How to do this depends on the version.
For Visual Studio 6: Project, Add to Project, Files, Files of type: Definition files (.def) and choose the created .def file
For Visual Studio .NET: Project, Properties, Linker, Input, Module Definition file. There you enter the name (with optional path) of the .def file.

XLI prototype
/* Generic include libraries */
#include <malloc.h>
#include <string.h>
#include "lp_lib.h"
#ifdef FORTIFY
# include "lp_fortify.h"
#endif

/* Include routines common to language interface implementations */

#include "lp_XLI1.c"

char * XLI_CALLMODEL xli_name(void)
{
  return("XLI_xxx v1.0" );  /* return the name and version */
}

MYBOOL XLI_CALLMODEL xli_readmodel(lprec *lp, char *model, char *data, char *options, int verbose)
{
  MYBOOL status = FALSE;

  /* implement the code here to read the model */

  return(status); /* status says if the model could be read or not. TRUE is ok, FALSE is not ok */
}

MYBOOL XLI_CALLMODEL xli_writemodel(lprec *lp, char *filename, char *options, MYBOOL results)
{
  MYBOOL status = FALSE;

  /* implement the code here to write the model */

  return( status ); /* status says if the model could be written or not. TRUE is ok, FALSE is not ok */
}
Working example:
demo.c:
/*  Modularized external language interface module - w/interface for lp_solve v5.0+
   ----------------------------------------------------------------------------------
    Author:        Peter Notebaert
    Contact:       peno@mailme.org
    License terms: LGPL.

    Template used:
    Requires:

    Release notes:
    v1.0.0  28 June 2004        First implementation.

   ---------------------------------------------------------------------------------- */

/* Generic include libraries */
#include <malloc.h>
#include <string.h>
#include "lp_lib.h"

/* Include libraries for this language system */
#include <math.h>

#ifdef FORTIFY
# include "lp_fortify.h"
#endif

/* Include routines common to language interface implementations */
#include "lp_XLI1.c"

MYBOOL XLI_CALLMODEL xli_name(void)
{
  return( "xli_demo v1.0" );
}

MYBOOL XLI_CALLMODEL xli_readmodel(lprec *lp, char *model, char *data, char *options, int verbose)
{
  MYBOOL status = FALSE;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  lp->add_columnex(lp, 0, NULL, NULL); /* add empty column */
  lp->add_columnex(lp, 0, NULL, NULL); /* add empty column */
  lp->set_add_rowmode(lp, TRUE);
  row[1] = 1.0;
  row[2] = 2.0;
  lp->add_constraint(lp, row, GE, 3.0); /* constructs the row: +v_1 +2 v_2 >= 3 */
  lp->set_add_rowmode(lp, FALSE);
  status = TRUE;

  return(status);
}

MYBOOL XLI_CALLMODEL xli_writemodel(lprec *lp, char *filename, char *options, MYBOOL results)
{
  return(lp->write_lp(lp, filename));
}
demo.def:
EXPORTS
  xli_compatible           @1
  xli_name                 @2
  xli_readmodel            @3
  xli_writemodel           @4

This example is not very practical. It is only usefull for demonstration purposes. Let's assume that the name of this library is xli_demo.
xli_readmodel creates the model. It doesn't even read from a file in this example. xli_writemodel uses write_lp to write the model to filename.

This XLI can be called from lp_solve via the following syntax:

lp_solve -rxli xli_demo "" -wxli xli_demo output.txt

An empty ("") filename is provided because it isn't used by this demo. This command will create a file output.txt with contents:

/* Objective function */
min: ;

/* Constraints */
+C1 +2 C2 >= 3;

/* Variable bounds */

Because we didn't provide the option -parse_only, the model is also solved and the result is shown on screen:

Value of objective function: 0

Actual values of the variables:
C1                              3
C2                              0


MPS file format

Fixed MPS format

The main things to know about fixed MPS format are that it is column oriented
(as opposed to entering the model as equations), and everything
(variables, rows, etc.) gets a name.

MPS is an old format, so it is set up as though you were using punch
cards, and is not free format. Fields start in column 2, 5, 15, 25, 40
and 50.  Sections of an MPS file are marked by so-called header cards,
which are distinguished by their starting in column 1.  Although it is
typical to use upper-case throughout the file (like I said, MPS has
long historical roots), many MPS-readers will accept mixed-case for
anything except the header cards, and some allow mixed-case anywhere.
The names that you choose for the individual entities (constraints or
variables) are not important to the solver; you should pick names that
are meaningful to you, or will be easy for a post-processing code to
read.

Here is a little sample model written in MPS format (explained in more
detail below):

NAME          TESTPROB
ROWS
 N  COST
 L  LIM1
 G  LIM2
 E  MYEQN
COLUMNS
    XONE      COST                 1   LIM1                 1
    XONE      LIM2                 1
    YTWO      COST                 4   LIM1                 1
    YTWO      MYEQN               -1
    ZTHREE    COST                 9   LIM2                 1
    ZTHREE    MYEQN                1
RHS
    RHS1      LIM1                 5   LIM2                10
    RHS1      MYEQN                7
BOUNDS
 UP BND1      XONE                 4
 LO BND1      YTWO                -1
 UP BND1      YTWO                 1
ENDATA

For comparison, here is the same model written out in lp-format:

min: +XONE +4 YTWO +9 ZTHREE;
LIM1: +XONE +YTWO <= 5;
LIM2: +XONE +ZTHREE >= 10;
MYEQN: -YTWO +ZTHREE = 7;
XONE <= 4;
YTWO >= -1;
YTWO <= 1;

Strangely, there is nothing in MPS format that specifies the direction
of optimisation.  And there really is no standard "default" direction;
some LP codes will maximize if you don't specify otherwise, others will
minimize, and still others put safety first and have no default and
require you to specify it somewhere in a control program or by a
calling parameter.  If you have a model formulated for minimization
and the code you are using insists on maximization (or vice versa), it
may be easy to convert: just multiply all the coefficients in your
objective function by (-1).  The optimal value of the objective
function will then be the negative of the true value, but the values of
the variables themselves will be correct.

Any line with an asterisk (*) in Column 1 is treated as a comment.

The eight character names used to specify variables, constraints and
other entities are fixed format. Names are not automatically justified,
so blanks are treated just like other characters. For example "ROW1    "
is not the same as " ROW1   ". (Note that some optimisers do not permit
blanks in names.) No case conversion is performed, so "row1    " is
different from "ROW1    ".

Floating point numbers may be specified in free format within the 12
character field (including embedded blanks). The following list describes
the possible ways of writing a number.

Mantissa:

        + or -      optional sign character (no sign indicates a positive number)

        digits      optional integer part of the mantissa

        .           optional decimal point (if not present, a decimal point will
                    be assumed after the mantissa digit)

        digits      optional fraction part of the mantissa -the mantissa must
                    contain at least one digit

Exponent (optional):

        D or E      exponent leader

        + or -      optional exponent sign

        digits      exponent digits

Numbers with an absolute value greater than 1010 or less than 10-10 are rejected.

The NAME card can have anything you want, starting in column 15.  The
ROWS section defines the names of all the constraints; entries in
column 2 or 3 are E for equality rows, L for less-than ( <= ) rows, G
for greater-than ( >= ) rows, and N for non-constraining rows (the
first of which would be interpreted as the objective function).  The
order of the rows named in this section is unimportant.

The largest part of the file is in the COLUMNS section, which is the
place where the entries of the A-matrix are put. All entries for a given
column must be placed consecutively, although within a column the
order of the entries (rows) is irrelevant. Rows not mentioned for a
column are implied to have a coefficient of zero.

The RHS section allows one or more right-hand-side vectors to be
defined; most people don't bother having more than one.  In the above
example, the name of the RHS vector is RHS1, and has non-zero values
in all 3 of the constraint rows of the problem.  Rows not mentioned in
an RHS vector would be assumed to have a right-hand-side of zero.

The optional BOUNDS section lets you put lower and upper bounds on
individual variables (no * wild cards, unfortunately), instead of
having to define extra rows in the matrix.  All the bounds that have
a given name in column 5 are taken together as a set.  Variables not
mentioned in a given BOUNDS set are taken to be non-negative (lower
bound zero, no upper bound).  A bound of type UP means an upper bound
is applied to the variable.  A bound of type LO means a lower bound is
applied.  A bound type of FX ("fixed") means that the variable has
upper and lower bounds equal to a single value.  A bound type of FR
("free") means the variable has neither lower nor upper bounds.

There is another optional section called RANGES that I won't go into
here. The final card must be ENDATA, and yes, it is spelled funny.

==========================================================================

MPS input format was originally introduced by IBM to express linear
and integer programs in a standard way.  The format is a fixed column
format, so care must be taken that all information is placed in the
correct columns as described below.

The following is not intended as a complete description of MPS format,
but only as a brief introduction.  For more information, the reader is
directed to:

  "Advanced Linear Programming," by Bruce A. Murtagh
  "Computer Solutions of Linear Programs," by J.L. Nazareth

It may be useful to look at an example MPS file while reading this
MPS information.

The following template is a guide for the use of MPS format:

---------------------------------------------------------------------
Field:    1           2          3         4         5         6
Columns:  2-3        5-12      15-22     25-36     40-47     50-61

          NAME   problem name

          ROWS

           type     name

          COLUMNS
                   column       row       value     row      value
                    name        name                name
          RHS
                    rhs         row       value     row      value
                    name        name                name
          RANGES
                    range       row       value     row      value
                    name        name                name
          BOUNDS

           type     bound       column    value
                    name        name

          SOS
           type     CaseName    SOSName   SOSpriority
                    CaseName    VarName1  VarWeight1
                    CaseName    VarName2  VarWeight2

                    CaseName    VarNameN  VarWeightN

          ENDATA
---------------------------------------------------------------------

NOTES:

A. In the ROWS section, each row of the constraint matrix must have a
   row type and a row name specified.  The code for indicating row type
   is as follows:

                     type      meaning
                     ---------------------------
                      E    equality
                      L    less than or equal
                      G    greater than or equal
                      N    objective
                      N    no restriction

B. In the COLUMNS section, the names of the variables are defined along
   with the coefficients of the objective and all the nonzero constraint
   matrix elements.  It is not necessary to specify columns for slack or
   surplus variables as this is taken care of automatically.

C. The RHS section contains information for the right-hand side of the problem.

D. The RANGES section is for constraints of the form:  h <= constraint <= u .
   The range of the constraint is  r = u - h .  The value of r is specified
   in the RANGES section, and the value of u or h is specified in the RHS
   section.  If b is the value entered in the RHS section, and r is the
   value entered in the RANGES section, then u and h are thus defined:

        row type       sign of r       h          u
        ----------------------------------------------
           G            + or -         b        b + |r|
           L            + or -       b - |r|      b
           E              +            b        b + |r|
           E              -          b - |r|      b

E. In the BOUNDS section, bounds on the variables are specified.  When
   bounds are not indicated, the default bounds ( 0 <= x < infinity )
   are assumed.  The code for indicating bound type is as follows:

                    type            meaning
                   ---------------------------------------------------
                     LO    lower bound        b <= x (< +inf)
                     UP    upper bound        (0 <=) x <= b
                     FX    fixed variable     x = b
                     FR    free variable      -inf < x < +inf
                     MI    lower bound -inf   -inf < x (<= 0)
                     PL    upper bound +inf   (0 <=) x < +inf
                     BV    binary variable    x = 0 or 1
                     LI    integer variable   b <= x (< +inf)
                     UI    integer variable   (0 <=) x <= b
                     SC    semi-cont variable x = 0 or l <= x <= b
                           l is the lower bound on the variable
                           If none set then defaults to 1

F. Sections RANGES and BOUNDS are optional as are the fields 5 and 6.
   Everything else is required.  In regards to fields 5 and 6, consider
   the following 2 constraints:

                       const1:  2x + 3y <= 6
                       const2:  5x + 8y <= 20

   Two ways to enter the variable x in the COLUMNS section are:

     (Field:  2    3           4            5         6  )
   1.         x  const1       2.0         const2     5.0

   2.         x  const1       2.0
              x  const2       5.0

G. A mixed integer program requires the specification of which variables
   are required to be integer.  Markers are used to indicate the start
   and end of a group of integer variables.  The start marker has its
   name in field 2, 'MARKER' in field 3, and 'INTORG' in field 5.  The
   end marker has its name in field 2, 'MARKER' in field 3, and 'INTEND'
   in field 5.  These markers are placed in the COLUMNS section.

H. A specially ordered set of degree N is a collection of variables where
   at most N variables may be non-zero.  The non-zero variables must be
   contiguous (neighbours) sorted by the ascending value of their respective
   unique weights.  In lp_solve, specially ordered sets may be of any
   cardinal type 1, 2, and higher, and may be overlapping.  The number of
   variables in the set must be equal to, or exceed the cardinal SOS order.

   Below is a representation of a SOS in an MPS file, where each SOS is
   defined in its own SOS section, which should follow the BOUNDS section.

   0        1         2         3         4
   1234567890123456789012345678901234567890
   SOS
    Sx CaseName  SOSName.  SOSpriority.
       CaseName  VarName1  VarWeight1..
       CaseName  VarName2  VarWeight2..

       CaseName  VarNameN  VarWeightN..

   x at the second line, position 3, defines is the order of the SOS.
   Due to limitations in the MPS format, N is restricted to the 1..9 range.
   Each SOS should be given a unique name, SOSName. lp_solve does not
   currently use case names for SOS'es and the CaseName could be any non-empty
   value.  The SOSpriority value determines the order in which multiple SOS'es
   are analysed in lp_solve.
   See also Interpolation with GAMS.

   Example:

NAME          SOS2test
ROWS
 N  obj
 L  c1
 L  c2
 E  c3
COLUMNS
    x1        obj                 -1   c1                  -1
    x1        c2                   1
    x2        obj                 -2   c1                   1
    x2        c2                  -3   c3                   1
    x3        obj                 -3   c1                   1
    x3        c2                   1
    x4        obj                 -1   c1                  10
    x4        c3                -3.5
    x5        obj                  0
RHS
    rhs       c1                  30   c2                  30
BOUNDS
 UP BOUND     x1                  40
 LI BOUND     x4                   2
 UI BOUND     x4                   3
SOS
 S2 SET       SOS2                10
    SET       x1               10000
    SET       x2               20000
    SET       x4               40000
    SET       x5               50000
ENDATA

Free MPS format

The free format is very similar to the fixed MPS format, but it is less restrictive e.g. it allows longer names. Also some implementations allow more than 12 positions to specify the values. The fields do not have fixed column positions as in the fixed MPS format. They may be written anywhere except column 1, with each field separated from the next by one or more blanks. However, they must appear in the same sequence as in fixed format. There is one important limitation compared to the fixed MPS format: names may not contain blanks. Also note that there is no real standard for the free format. Each implementer has its own implementation and interpretation of the free format ... Some allow one space in the name, some require that names must take at least 8 positions (and thus extended with spaces). lp_solve tries to handle all possible free formats. The only real limitation is that there may be no blanks in names. When lp_solve writes an mps file in free format, it will be the same as for fixed format, except if names are longer than 8 characters. In that case all data is shifted to the right.


LP file format

The lp-format input syntax is a set of algebraic expressions and "int"
declarations in the following order:

<objective function>
<constraint>*
<declaration>*

where:

- <objective function> is a linear combination of optional variables and
  constants, ending with a semicolon, optionally preceded by "max: " or "min: "
  to indicate whether you want it to be minimized or maximized. The case
  is not important, "Max:" or "MAX:" will work as well. Maximization
  is the default. Alternatives are minimise, minimize, maximise, Maximize.
  The objective function is required, but can be empty.

- <constraint> is an optional constraint name followed by a colon plus
  a linear combination of variables and constants or (just one)
  constraint name followed by a colon (a range) or (just one) variable
  name without a colon (a bound), followed by a relational operator,
  followed again by a linear combination of variables and constants,
  ending with a semicolon. The relational operator can be any of the
  following: "<" "<=" "=" ">" ">=". There is no semantic difference
  between "<" and "<=" nor between ">" and ">=" (even for integer
  variables!).

- <declaration> is of one of the forms:
  To define variables as integer:
   "int"
   var [","] var [","] var ... ";"

  To define variables as semi-cont:
   "sec"
   var [","] var [","] var ... ";"

  To define Special Ordered Sets (SOS):
   "sos"
   [sosdescr:] [","] var[:weight] [","] var[:weight] [","] var[:weight] ... "<[=]" sostype[:sosorder] ";" ...
  or:
   "sosx"
   [sosdescr:] var[:weight] [","] var[:weight] [","] var[:weight] ... ";" ...

- A var must start with a letter (either upper or lower case), and may
  contain any number of additional letters, numerals, or characters
  from this list: _[]{}/.&#$%~'@^

- Comments can be used with the /* */ syntax, just like in C.
  It can be put anywhere in the file and even over multiple lines.
  lp_solve 4.0.1.11 and newer also supports the C++ line comment //.

- Empty lines are also allowed.

EXAMPLES
      The simple problem:

      x1 >= 1
      x2 >= 1
      x1 + x2 >= 2
      minimize x1 + x2 (= maximize -(x1 + x2)), with x1 integer

      Can be written as follows in lp-format:

      -x1 -x2;
      /* or min: x1 + x2; */
      x1 >= 1;
      x2 >= 1;
      x1 + x2 >= 2;
      int x1;

The correct result for (x1, x2) is of course (1, 1).

If you want to give a name to a restriction then begin the line with the name and a colon.

For example:

      min: x1 + x2;
      x1 >= 1;
      x2 >= 1;
      myrow: x1 + x2 >= 2;
      int x1;

The objective function may also be empty, but it must be there:

      min: ;
      x1 >= 1;
      x2 >= 1;
      myrow: x1 + x2 >= 2;
      int x1;

Also constants may be put in the objective function:

      min: x1 + x2 + 3;
      x1 >= 1;
      x2 >= 1;
      myrow: x1 + x2 >= 2;
      int x1;

Or even the following is ok. The constants will be added to one constant value:

      min: 2 + x1 + 3 + x2 + 4;
      x1 >= 1;
      x2 >= 1;
      myrow: x1 + x2 >= 2;
      int x1;

This will lead to the same solution as without the constant(s),
but the objective value will be increased with this value.

Note that for bounds on variables, you should not put labels before them.
This is because lp_solve then makes this an extra restriction.
If you don't put a label before single variables then lp_solve doesn't have to create
an extra row for bounds on variables, resulting in better performance.

So it is better to write:

      x1 >= 1;

than

      r_x1: x1 >= 1;

Note that this is only for single variables, so

      myrow: x1 + x2 >= 2;

performs as well as

      x1 + x2 >= 2;

In addition, the variable can have a constant, without performance penalty.
For example:

      2 x1 >= 2;

is automatically translated to

      x1 >= 1;

by lp_solve, so this is not a restriction, but a (better performing) bound.
The moment there is more than one variable in a constraint, lp_solve can only
create a restriction (extra row) for this.

Sometimes there is a lower and upper bound on a variable. This can be written in several ways:

      x1 >= 1;
      x1 <= 3;

It doesn't matter if the lower bound comes first or not. They are also not required to be together.

Another way to write this is:

      1 <= x1 <= 3;

Or

      3 >= x1 >= 1;

These bounds on variables are handled by lp_solve in a special way so that no extra restrictions
(rows) are created, which will lead to better performance.

Also on restrictions there can be both a lower and upper value. They are called ranges.
For example:

      myrow: x1 + x2 >= 2;

Suppose that the same restriction should also be <= 6, then this could be written as:

      myrowmin: x1 + x2 >= 2;
      myrowmax: x1 + x2 <= 6;

However, then there are two rows in the model which makes it larger and harder to solve.
lp_solve can handle this in one row so that the model is smaller and it will solve more quickly.
This will only be done if the modeling is done in one of the following ways:

      myrow: x1 + x2 >= 2;
      myrow: <= 6;

Or

      myrow: x1 + x2 <= 6;
      myrow: >= 2;

Or

      myrow: 6 >= x1 + x2 >= 2;

Or

      myrow: 2 <= x1 + x2 <= 6;

Or

      6 >= x1 + x2 >= 2;

Or

      2 <= x1 + x2 <= 6;

Note that there must be a row label if the construction
label: op constant
is used. This requirement does not count if the min and max restriction is put on one line.
Also the range must come after the constraint definition.

Example with integer variables:

    min: -x1 -2 x2 +0.1 x3 +3 x4;
    r_1: +x1 +x2 <= 5;
    r_2: +2 x1 -x2 >= 0;
    r_3: -x1 +3 x2 >= 0;
    r_4: +x3 +x4 >= 0.5;
    x3 >= 1.1;

    int x3, x4;

See integer variables for a description about integer variables.

Example with semi-continuous variables:

    max: x1 + 2x2 - 4x3 -3x4;
    x1 + x2 <= 5;
    2x1 - x2 >= 0;
    -x1 + 3x2 >= 0;
    x3 + x4 >= .5;
    x3 >= 1.1;
    x3 <= 10;

    sec x3, x4;

See semi-continuous variables for a description about semi-continuous variables.

Examples with Special Ordered Sets (SOS):

    min: -x1 -x2 -3 x3 -2 x4 -2 x5;
    c1: -x1 -x2 +x3 +x4 <= 30;
    c2: +x1 +x3 -3 x4 <= 30;
    x1 <= 40;
    x2 <= 1;
    x5 <= 1;

    sos
    SOS1: x1, x2, x3, x4 <= 2;
    SOS2: x2, x3, x4, x5 <= 3;

Alternative:

    min: -x1 -x2 -3 x3 -2 x4 -2 x5;
    c1: -x1 -x2 +x3 +x4 <= 30;
    c2: +x1 +x3 -3 x4 <= 30;
    x1 <= 40;
    x2 <= 1;
    x5 <= 1;

    sos2
    SOS1: x1, x2, x3, x4;
    SOS2: x2, x3, x4, x5;

With SOS weights:

      min: -x1 -x2 -3 x3 -2 x4 -2 x5;
    c1: -x1 -x2 +x3 +x4 <= 30;
    c2: +x1 +x3 -3 x4 <= 30;
    x1 <= 40;
    x2 <= 1;
    x5 <= 1;

    sos
    SOS1: x1:5, x2:9, x3:12, x4:17 <= 2:3;
    SOS2: x2:9, x3:12, x4:17, x5:21 <= 2:3;

See Special Ordered Sets (SOS) for a description about Special Ordered Sets.

Peculiarities of the lp format:

Note that some strange effects can occur.

Exponents:

Consider the following lp:

min: d1 + e1;

-0.5 d1 + e1 <= 3;
d1 + e1 >= 6;
3 d1 - 2 e1 <= 16;

This works as expected. d1 and e1 are always seen as variables.

Now consider this:

min: d1 + e1;

-0.5 d1 + e1 <= 3;
d1 + e1 >= 6;
3d1 - 2e1 <= 16;

You would expect that this is exactly the same model as before. And for variable d1, this is also the case.
However, e1 in the last constraint is a problem. Here lp_solve doesn't recognise 2e1 as two times variable e1,
but as the constant value 2.0e1 (20). It sees the e1 as an exponent!
There is no problem when there is at least one space between 2 and e1. In that case lp_solve knows that it is
two times variables e1 because there may not be any spaces in numbers.

Operators

Consider the following constraint:

+3 x + 2 y <= 16;

The + sign is optional.

So above equation can also be written as:

3 x + 2 y <= 16;

But also as:

3 x 2 y <= 16;

This may look somewhat strange and can even lead to confusion. Consider the equation without the factor 2:

3 x y <= 16;

This is still considered as:

3 x + y <= 16;

And not as

3 x * y <= 16;

as could be thought...

Also, lp_solve allows adjacent operators.

Consider the following constraint:

+3 x - 2 y <= 16;

This may also be written as:

+3 x + -2 y <= 16;

or

+3 x +- 2 y <= 16;

or

+3 x - +2 y <= 16;

And the constraint

+3 x + 2 y <= 16;

may also be written as:

+3 x + +2 y <= 16;

or

+3 x + + 2 y <= 16;

and even:

+3 x - -2 y <= 16;

Note that the lp_format does not allow parentheses () to make things clearer ...

So the following is not allowed:

+3 x - (-2) y <= 16;

In fact, there is no limit on the number of operators that are placed next to
each other, separated with as many or as few spaces as desired...

For example - --     -- is seen as -, while ----       -- is seen as +.


CPLEX LP file format

The CPLEX LP file format provides a facility for entering a problem in a natural, algebraic LP formulation from the keyboard. The problem can be modified and saved from within lpsolve. This procedure is one way to create a file in a format that lpsolve can read. An alternative technique is to create a similar file using a standard text editor and to read it into lpsolve.

The CPLEX LP format is provided as an input alternative to the MPS file format. An LP format file may be easier to generate than an MPS file if your problem already exists in an algebraic format or if you have an application that generates the problem file more readily in algebraic format (such as a C application).

lpsolve will accept any problem saved in an ASCII file provided that it adheres to the following syntax rules.

Syntax Rules of LP File Format
  1. Anything that follows a backslash (\) is a comment and will be ignored until a return is encountered. Blank lines are also ignored. Blank and comment lines may be placed anywhere and as frequently as you want in the file.

  2. In general, white space between characters is irrelevant as it is skipped when a file is read. However, white space is not allowed in the keywords used to introduce a new section, such as MAX, MIN, ST, or BOUNDS. Also the keywords must be separated by white space from the rest of the file and must be at the beginning of a line. The maximum line length allowed is 255 characters.

Skipping spaces may cause lpsolve to misinterpret (and accept) an invalid entry, such as the following:

 x1 x2 = 0

If the user intended to enter that example as a nonlinear constraint-not valid in LP format, lpsolve would instead interpret it as a constraint specifying that one variable named x1x2 must be equal to zero.

  3. The problem statement must begin with the word MINIMIZE or MAXIMIZE, MINIMUM or MAXIMUM, or the abbreviations MIN or MAX, in any combination of upper- and lower-case characters. The word introduces the objective function section.

  4. Variables can be named anything provided that the name does not exceed 16 characters, all of which must be alphanumeric (a-z, A-Z, 0-9) or one of these symbols: ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~. Longer names will be truncated to 16 characters. A variable name cannot begin with a number or a period.

The letter E or e, alone or followed by other valid symbols, or followed by another E or e, should be avoided as this notation is reserved for exponential entries. Thus, variables cannot be named e9, E-24, E8cats, or other names that could be interpreted as an exponent. Even variable names such as eels or example can cause a read error, depending on their placement in an input line.

Also, the following characters are not valid in variable names (in order to allow for quadratic objective information): ^, *, [ and ].

  5. The objective function definition must follow MINIMIZE/MAXIMIZE. It may be entered on multiple lines as long as neither a variable, nor a constant, nor a sense indicator is split by a return. For example, this objective function 1x1 + 2x2 +3x3 can be entered like this:

    1x1 + 2x2
+ 3x3

but not like this:

1x1 + 2x
2 + 3x3         \ a bad idea

because the second style splits the variable name x2 by a return.

  6. The objective function may be named by typing a name and a colon before the objective function. The objective function name and the colon must appear on the same line. Objective function names must conform to the same guidelines as variable names (Rule 4).

  7. The constraints section is introduced by the keyword SUBJECT TO. This expression can also appear as such that, st, S.T., or ST. in any mix of upper- and lower-case characters. One of these expressions must precede the first constraint and be separated from it by at least one space.

  8. Each constraint definition must begin on a new line. A constraint may be named by typing a name and a colon before the constraint. The constraint name and the colon must appear on the same line. Constraint names must adhere to the same guidelines as variable names (Rule 4). If no constraint names are specified, lpsolve will assign the names R1, R2, R3, etc.

  9. The constraints are entered in the same way as the objective function; however, a constraint must be followed by an indication of its sense and a right-hand side coefficient. The right-hand side coefficient must be typed on the same line as the sense indicator. Acceptable sense indicators are <, <=, =<, >, >=, =>, and =. These are interpreted as =, =, =, =, =, = and =, respectively.

For example, here is a named constraint:

time: x1 + x2 <= 10

  10. The optional BOUNDS section follows the mandatory constraint section. It is preceded by the word bounds or bound in any mix of lower- and upper-case characters.

  11. Each bound definition must begin on a new line. The format for a bound is ln=xn = un except in the following cases:

Upper and lower bounds can also be entered separately as ln=xn and xn = un

with the default lower bound of 0 (zero) and the default upper bound of +8 remaining in effect until the bound is explicitly changed.

Bounds that fix a variable can be entered as simple equalities. For example, x5 = 5.6 is equivalent to 5.6 <= x5 <= 5.6.

The bounds +8 (positive infinity) and -8 (negative infinity) must be entered as words: +infinity, -infinity, +inf, -inf.

A variable with a negative infinity lower bound and positive infinity upper bound may be entered as free, in any mix of upper- and lower-case characters, with a space separating the variable name and the word free. For example, x7 free is equivalent to - infinity <= x7 <= + infinity.

  12. The file must end with the word end in any combination of upper- and lower-case characters, alone on a line, when it is created with the enter command. This word is not required for files that are read in to lpsolve, but it is strongly recommended. Files that have been corrupted can frequently be detected by a missing last line.

  13. To specify any of the variables as general integer variables, add a GENERAL section; to specify any of the variables as binary integer variables, add a BINARY section. The GENERAL and BINARY sections follow the BOUNDS section, if one is present; otherwise, they follow the constraints section. Either of the GENERAL or BINARY sections can precede the other. The GENERAL section is preceded by the word GENERAL, GENERALS, or GEN that must appear alone on a line. The following line or lines should list the names of all variables that are to be restricted to general integer values, separated by at least one space. The BINARY section is preceded by the word BINARY, BINARIES, or BIN that must appear alone on a line. The following line or lines should list the names of all variables that are to be restricted to binary integer values, separated by at least one space. Binary variables are automatically given bounds of 0 (zero) and 1 (one), unless alternative bounds are specified in the BOUNDS section, in which case a warning message is issued.

Here is an example of a problem formulation in LP format where x4 is a general integer:

Maximize
 obj: x1 + 2 x2 + 3 x3 + x4
Subject To
 c1: - x1 + x2 + x3 + 10 x4 <= 20
 c2: x1 - 3 x2 + x3 <= 30
 c3: x2 - 3.5 x4 = 0
Bounds
 0 <= x1 <= 40
 2 <= x4 <= 3
General
 x4
End


lp_solve usage

Usage of lp_solve version 5.1.1.2:
lp_solve [options] [[<]input_file]
List of options:
-h              prints this message
-lp             read from LP file (default) See lp-format
-mps            read from MPS file in fixed format See mps-format
-fmps           read from MPS file in free format See mps-format
-rxli xliname filename
                read file with xli library See external language interface
-rxlidata datafilename
                data file name for xli library.
-rxliopt options
                options for xli library.
-wlp filename   write to LP file See lp-format
-wmps filename  write to MPS file in fixed format See mps-format
-wfmps filename write to MPS file in free format See mps-format
-wxli xliname filename
                write file with xli library See external language interface
-wxliopt options
                options for xli library.
-wafter         Write model after solve (usefull if presolve used).
-parse_only     parse input file but do not solve
-nonames        Ignore variables and constraint names

-min            Minimize the lp problem (overrules setting in file) See set_minim
-max            Maximize the lp problem (overrules setting in file) See set_maxim
-b <bound>      specify a lower bound for the objective function See set_obj_bound
                to the program. If close enough, may speed up the
                calculations.
-r <value>      specify max nbr of pivots between a re-inversion of the matrix See set_maxpivot
-piv <rule>     specify simplex pivot rule See set_pivoting
         -piv0: Select first
         -piv1: Select according to Dantzig
         -piv2: Select Devex pricing from Paula Harris (default)
         -piv3: Select steepest edge
These pivot rules can be combined with any of the following:
-pivf           In case of Steepest Edge, fall back to DEVEX in primal. See set_pivoting
-pivm           Multiple pricing. See set_pivoting
-piva           Temporarily use First Index if cycling is detected.  See set_pivoting
-pivr           Adds a small randomization effect to the selected pricer. See set_pivoting
-pivll          Scan entering/leaving columns left rather than right. See set_pivoting
-pivla          Scan entering/leaving columns alternatingly left/right. See set_pivoting
-s <mode> <scaleloop>   use automatic problem scaling. See set_scaling
          -s:
         -s0: Numerical range-based scaling
         -s1: Geometric scaling
         -s2: Curtis-reid scaling
         -s3: Scale to convergence using largest absolute value
         -s4: Numerical range-based scaling
         -s5: Scale to convergence using logarithmic mean of all values
         -s6: Scale based on the simple numerical range
         -s7: Scale quadratic
These scaling rules can be combined with any of the following:
-sp             also do power scaling. See set_scaling
-si             also do Integer scaling. See set_scaling
-se             also do equilibration to scale matrix vales to the -1..1 range. See set_scaling
-presolve       presolve problem before start optimizing See set_presolve
-presolverow    presolve problem before start optimizing (rows only) See set_presolve
-presolvecol    presolve problem before start optimizing (columns only) See set_presolve
-presolvel      also eliminate linearly dependent rows See set_presolve
-presolves      also convert constraints to SOSes (only SOS1 handled) See set_presolve
-presolver      If the phase 1 solution process finds that a constraint is
                redundant then this constraint is deleted See set_presolve
-C <mode>       basis crash mode See set_basiscrash
         -C0: No crash basis
         -C2: Most feasible basis
-prim           Prefer the primal simplex for both phases. See set_preferdual
-dual           Prefer the dual simplex for both phases. See set_preferdual
-simplexpp      Set Phase1 Primal, Phase2 Primal. See set_simplextype
-simplexdp      Set Phase1 Dual, Phase2 Primal. See set_simplextype
-simplexpd      Set Phase1 Primal, Phase2 Dual. See set_simplextype
-simplexdd      Set Phase1 Dual, Phase2 Dual. See set_simplextype
-degen          use perturbations to reduce degeneracy,
                can increase numerical instability See set_anti_degen
-degenc         use column check to reduce degeneracy See set_anti_degen
-degend         dynamic check to reduce degeneracy See set_anti_degen
-trej <Trej>    set minimum pivot value See set_epspivot
-epsd <epsd>    set minimum tolerance for reduced costs See set_epsd
-epsb <epsb>    set minimum tolerance for the RHS See set_epsb
-epsel <epsel>  set tolerance for rounding values to zero See set_epsel
-epsp <epsp>    set the value that is used as perturbation scalar for
                degenerative problems See set_epsperturb
-improve <level>	      iterative improvement level See set_improve
         -improve0: none (default)
         -improve4: Automatic inverse accuracy control in the dual simplex
-timeout <sec>  Timeout after sec seconds when not solution found. See set_timeout
-bfp <filename> Set basis factorization package. See set_BFP

-noint          Ignore integer restrictions
-e <number>     specifies the tolerance which is used to determine whether a
                floating point number is in fact an integer.
                Should be < 0.5 See set_epsint
-g <number>
-ga <number>    specifies the absolute MIP gap for branch-and-bound. See set_mip_gap
                This specifies the absolute allowed tolerance
                on the object function. Can result in faster solving times.
-gr <number>    specifies the relative MIP gap for branch-and-bound. See set_mip_gap
                This specifies the relative allowed tolerance
                on the object function. Can result in faster solving times.
-f              specifies that branch-and-bound algorithm stops at first found
                solution See set_break_at_first
-o <value>      specifies that branch-and-bound algorithm stops when objective
                value is better than value See set_break_at_value
-c              during branch-and-bound, take the ceiling branch first See set_bb_floorfirst
-ca             during branch-and-bound, the algorithm chooses branch See set_bb_floorfirst
-depth <limit>  set branch-and-bound depth limit See set_bb_depthlimit
-n <solnr>      specify which solution number to return See set_solutionlimit
-B <rule>       specify branch-and-bound rule See set_bb_rule
         -B0: Select Lowest indexed non-integer column (default)
         -B1: Selection based on distance from the current bounds
         -B2: Selection based on the largest current bound
         -B3: Selection based on largest fractional value
         -B4: Simple, unweighted pseudo-cost of a variable
         -B5: This is an extended pseudo-costing strategy based on minimizing
              the number of integer infeasibilities
         -B6: This is an extended pseudo-costing strategy based on maximizing
              the normal pseudo-cost divided by the number of infeasibilities.
              Similar to (the reciprocal of) a cost/benefit ratio
These branch-and-bound rules can be combined with any of the following:
-Bw             WeightReverse branch-and-bound See set_bb_rule
-Bb             BranchReverse branch-and-bound See set_bb_rule
-Bg             Greedy branch-and-bound See set_bb_rule
-Bp             PseudoCost branch-and-bound See set_bb_rule
-Bf             DepthFirst branch-and-bound See set_bb_rule
-Br             Randomize branch-and-bound See set_bb_rule
-BG             GubMode branch-and-bound See set_bb_rule
-Bd             Dynamic branch-and-bound See set_bb_rule
-Bs             RestartMode branch-and-bound See set_bb_rule
-BB             BreadthFirst branch-and-bound See set_bb_rule
-Bo             Order variables to improve branch-and-bound performance See set_bb_rule

-time           Print CPU time to parse input and to calculate result. See time_elapsed
-v <level>      verbose mode, gives flow through the program. See set_verbose
                if level not provided (-v) then -v4 (NORMAL) is taken.
         -v0: NEUTRAL
         -v1: CRITICAL
         -v2: SEVERE
         -v3: IMPORTANT (default)
         -v4: NORMAL
         -v5: DETAILED
         -v6: FULL
-t              trace pivot selection See set_trace
-d              debug mode, all intermediate results are printed,
                and the branch-and-bound decisions See set_debug
-R              report information while solving the model See put_msgfunc See get_working_objective
-Db <filename>  Do a generic readable data dump of key lp_solve model variables
                before solve. See print_debugdump
                Principally for run difference and debugging purposes
-Da <filename>  Do a generic readable data dump of key lp_solve model variables
                after solve. See print_debugdump
                Principally for run difference and debugging purposes
-i              print all intermediate valid solutions. See set_print_sol
                Can give you useful solutions even if the total run time
                is too long
-ia             print all intermediate (only non-zero values) valid solutions. See set_print_sol
                Can give you useful solutions even if the total run time
                is too long
-S <detail>     Print solution. If detail omitted, then -S2 is used.
         -S0: Print nothing
         -S1: Only objective value See print_objective See get_objective
         -S2: Obj value+variables (default) See print_solution See get_variables, get_ptr_variables
         -S3: Obj value+variables+constraints See print_constraints See get_constraints
         -S4: Obj value+variables+constraints+duals See print_duals See get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, See get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex
         -S5: Obj value+variables+constraints+duals+lp model See print_lp
         -S6: Obj value+variables+constraints+duals+lp model+scales See print_scales
         -S7: Obj value+variables+constraints+duals+lp model+scales+lp tableau See print_tableau

The lp_solve program is a command line application that can use as good as all functionality of the library. Note for Windows users, that you can not just run the lp_solve program by dubbel clicking on it from Windows Explorer. The program needs arguments and this is best done from the command line (cmd.exe / command.com) or via batch files. lp_solve has many options as shown here above.

This program reads the MIP model from standard input or from a file and outputs the result back to the console or to a file. There are several possible input formats: The 'lp' format (See lp-format), the 'mps' format (See mps-format) and the CPLEX lp (See CPLEX-format) formats are build in, but other formats are also supported via the XLI functionality (See external language interface). For example a MathProg interface is developed via the XLI functionality (See external language interface for an example). These input formats have nothing to do with the API. So lp1 = make_lp(0,4) is a totally wrong input for the lp_solve program. The lp format is the default. Optionaly you can use the -lp option for it. To enable the mps format, use the -mps option. To enable the XLI, use the -rxli option. If lp_solve is started without an input file, then it gives a blinking cursor and waits for input. It is then possible to enter the model in the specified format (lp by default). But this is not very handy. You must enter the whole model each time you want to solve it and must be careful that you don't type any errors. To stop input mode, press Ctrl Z.
However it is much better to write your model in a disk file with your favourite editor (make sure it is in text format) and then provide this file to lp_solve. For example:

lp_solve input.lp

It is also possible to use input redirection:

lp_solve <input.lp

Or more sophisticated constructs like:

gen_model | lp_solve

gen_model is here a user written program that outputs the model to standard output and via the pipe character (|) this output is redirected to lp_solve. So no intermediate file is needed in this case.

Examples:

lp_solve input.lp

lp_solve -s input.lp

lp_solve -s input.lp >output.txt

lp_solve -s -mps input.mps >output.txt

lp_solve -s -S4 -mps input.mps >output.txt


LPSolve IDE

The LPSolve IDE (Integrated Development Interface) is a very user friendly Windows interface to the lpsolve API. All functionality of lpsolve can be accessed via a graphical and very user friendly application.

Many thanks to Henri Gourvest for making this nice interface to lpsolve and making it available to the community.

Here is a list of some of the features of the IDE:

  • Everything is graphical and mouse controled
  • Enter your lp model in all supported formats and even via an XLI interface (See External Language Interfaces)
  • Convert your lp model from any supported format to another supported format and even via an XLI interface (See External Language Interfaces)
  • Very user friendly editor to enter/change the model with syntax highlight.
  • Syntax checking of the model
  • Solve the model
  • See the results in grids
  • Control every possible lpsolve option (tolerances, presolve, scaling, ...)
  • View the matrix in grids
  • Export model to HTML, RTF, LaTeX output
  • Export matrix to CSV, HTML, RTF output
  • Export results to CSV, HTML, RTF output
  • Show statistics about the model.
  • ...

Here are some screen shorts:

Installation

This program has no setup procedure. It doesn't need one. Just put all files from the archive into a directory and run the exe, that is all. Note however that it needs the lpsolve dll (lpsolve51.dll) to do its job. Four your convenience, a dll is provided with this archive, but it is not guaranteed to be the most recent one. To get the most recent lpsolve dll, download it from the lpsolve yahoo site (http://groups.yahoo.com/group/lp_solve/files/Version5.1) It is contained in the lp_solve_5.1_dev.zip archive. Also note that the IDE also puts some messages on the console. This may be changed in the future. When started from a command prompt, the messages are shown in this screen, when started from Windows, a console screen will also be created. If you are looking for a message not shown in the IDE, maybe it is shown on the console window...


Using lpsolve from AMPL

AMPL?

AMPL (A Mathematical Programming Language) is a high-level language for describing mathematical programs. AMPL allows a mathematical programming model to be specified independently of the data used for a specific instance of the model. AMPL's language for describing mathematical programs closely follows that used by humans to describe mathematical programs to each other. For this reason, modellers may spend more time improving the model and less time on the tedious details of data manipulation and problem solution.
To start, AMPL needs a mathematical programming model, which describes variables, objectives and relationships without referring to specific data. AMPL also needs an instance of the data, or a particular data set. The model and one (or more) data files are fed into the AMPL program. AMPL works like a compiler: the model and input are put into an intermediate file that can be read by a solver. The solver actually finds an optimal solution to the problem by reading in the intermediate file produced by AMPL and applying an appropriate algorithm. The solver outputs the solution as a text file, which can be viewed directly and cross-referenced with the variables and constraints specified in the model file.

We will not discuss the specifics of AMPL here but instead refer the reader to AMPL (A Mathematical Programming Language) at the University of Michigan Documentation and the AMPL website http://www.ampl.com.

AMPL and lpsolve

One of the possible solvers that can be used by AMPL is lpsolve. However note that AMPL allows also defining non-linear models. These are not solvable by lpsolve because lpsolve can only handle MILP models. A message will be given if the AMPL model results in a model that cannot be handled by lpsolve.

To make this possible, a driver program is needed: lpsolve(.exe). This program must be put in the AMPL directory and AMPL can call the lpsolve solver. The newer versions of the lpsolve(.exe) driver call lpsolve via the shared library (lpsolve51.dll under Windows and liblpsolve51.so under Unix/Linux). This has the advantage that the lpsolve driver program doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the path. That is all.

Solve a model from AMPL via lpsolve

In the following text, ampl: before the AMPL commands is the AMPL prompt. Only the text after the : must be entered.

To select the lpsolve solver, the following command must be executed in AMPL:

ampl: option solver lpsolve;

To solve the model, the following command must be executed in AMPL:

ampl: solve;

Options can be passed to lpsolve. For example to enable scaling, the following command must be executed in AMPL:

ampl: option lpsolve_options 'scale';

Multiple options can be specified by separating them with at least one space:

ampl: option lpsolve_options 'scale scalemode=7 verbose';

A list of all options is given at the end of this document.

An example

ampl: model diet.mod;
ampl: data diet.dat;
ampl: option solver lpsolve;
ampl: option lpsolve_options 'scale scalemode=7';
ampl: solve;

This gives as result:

LP_SOLVE 5.1.1.2: scale
scalemode=7
LP_SOLVE 5.1.1.2: optimal, objective 88.2
1 simplex iterations

solve_result_num

AMPL has a parameter that is used to indicate the outcome of the optimisation process. It is used as follows

ampl: display solve_result_num

solve_result_num can take the values shown in following table which also presents a short explanation for each value.

Interpretation of solve_result_num.
Value | Message
0 | the solution is optimal
100 | suboptimal solution
200 | infeasible problem
300 | unbounded problem
500 | solution status is unknown
501 | failure
502 | integer programming failure

Restart

This is also new with version 5. Before, when lpsolve was used from AMPL, the model was each time completely resolved at each AMPL solve command. The last base was not used to do further iterations. This is specific to AMPL because lpsolve is called as a seperate program each time a solve is done and to make restart possible the last base must be provided again to lpsolve to start from there again. From version 5 on this is now implemented by default. This means if a solve is done immediately after a previous solve that no iterations are needed and the solution can be given immediately. This can be shown via an example:
ampl: model diet.mod;
ampl: data diet.dat;
ampl: option solver lpsolve;
ampl: solve;

This gives as result:

LP_SOLVE 5.1.1.2: optimal, objective 88.2
3 simplex iterations

Note that 3 iterations were needed to solve the model. Now solve the model again:

ampl: solve;

This gives as result:

LP_SOLVE 5.1.1.2: optimal, objective 88.2
0 simplex iterations

Note now that no iterations are needed to solve the model. This because the result of the previous solve is used as a starting point for the new solve. It is even allowed to add or deleted variables and constraints in the model, lpsolve will still try to start from the last result to continue.

If, for some reason, you don't want this and let lpsolve resolve the model from scratch, there are two possibilities to let lpsolve ignore the starting base. Either via an lpsolve option or an AMPL option.

The lpsolve option that can be set is:

ampl: option lpsolve_options 'coldstart';

The AMPL option that can be set is:

ampl: option send_statuses 0;

One of both is enough.

Now solve the model again:
ampl: solve;

This gives as result:

LP_SOLVE 5.1.1.2: coldstart
LP_SOLVE 5.1.1.2: optimal, objective 88.2
3 simplex iterations

Note that again 3 iterations are needed to solve the model.

Special considerations for integer models. From the moment that a model contains integer variables, the B&B algorithm must be used to solve this. This algorithm must go trough a tree of possible solutions each time a solve is done. The last base of the best integer solution can not be used as a starting base for a resolve. This is not an lpsolve limitation, but a B&B algorithm property...
For this reason, by default, AMPL doesn't provide a starting to the solver and solve is done from scratch. By default... However, a compromise can be implemented by the solver. And this is also done in lpsolve. Solving integer models is always started with solving the non-integer model. When this is done, the non-integer variables are made integer via the B&B algorithm. lpsolve returns the base of the non-integer model and this base is used as a starting base for the model at the next solve. As said, this is a compromise because it results in a fast solve of the non-integer model, but the B&B algorithm must still be executed. So even if no modifications are done to the model and solve is done again, there will be iterations needed by the B&B algorithm to solve the integers. Because this must be explicitly implemented in the solver, AMPL doesn't provide the starting base by default for integer models. It must explicitly be activated:

ampl: option send_statuses 2;

Only then, lpsolve will get a starting base when there are integers.

Example:

ampl: model multmip3.mod;
ampl: data multmip3.dat;
ampl: option solver lpsolve;
ampl: solve;

This gives as result:

LP_SOLVE 5.1.1.2: optimal, objective 235625
1986 simplex iterations
592 branch & bound nodes: depth 21

Note that 1986 iterations were needed to solve the model. Now solve the model again:

ampl: solve;

This gives as result:

LP_SOLVE 5.1.1.2: optimal, objective 235625
1986 simplex iterations
592 branch & bound nodes: depth 21

The same as above. So no restart was done. Now activate the starting base for integer models and solve again:

ampl: option send_statuses 2;
ampl: solve;

This gives as result:

LP_SOLVE 5.1.1.2: optimal, objective 235625
1922 simplex iterations
592 branch & bound nodes: depth 21

Note that less iterations are needed, but not 0 as in non-integer models. These are the iterations needed for the B&B algorithm.

lpsolve options

lpsolve accepts a lot of options. Some options are just on/off switches and for there you just specify the option keyword (for example scale). Other options need a value and this is specified by an equal (=) sign after the option keyword and then the value (for example scalemode=7). Multiple options can be specified by separating them by a space (for example scale scalemode=7).

Here is a list of the possible lpsolve options:

bb=...         branch-and-bound rule: one of
              0 (default) for lowest indexed non-integer variable
              1 for selection based on distance from the current bounds
              2 for selection based on the largest current bound
              3 for selection based on largest fractional value
              4 for simple, unweighted pseudo-cost of a variable
              5 this is an extended pseudo-costing strategy based on
                      minimizing the number of integer infeasibilities
              6 this is an extended pseudo-costing strategy based on
                      maximizing the normal pseudo-cost divided by the
                      number of infeasibilities.
             plus
             32 for greedy mode
             64 for pseudo cost mode
            128 select the node that has already been selected before
                      the most number of times
           4096 select the node that has been selected before the
                      fewest number of times or not at all
bfp=...        set basis factorization package
cauto          in IPs, algorithm decides which branch being taken first
cfirst         in IPs, take ceiling branch first
coldstart      ignore starting base
crash=...      determines a starting base: one of
              0 (default) none
              2 most feasible basis
debug          debug mode
degen          perturb degeneracies
degenx=...     anti-degen handling: one of
              0 (default) no anti-degeneracy handling
              1 check if there are equality slacks in the basis and
                      try to drive them out in order to reduce chance of
                      degeneracy in Phase 1
                    2 ColumnCheck
                    4 Stalling
                    8 NumFailure
                   16 LostFeas
                   32 Infeasible
                   64 Dynamic
                  128 During BB
depth=...      set branch-and-bound depth limit
dual           prefer the dual simplex for both phases
eps=...        tolerance for rounding to integer
epsb=...       minimum tolerance for the RHS
epsd=...       minimum tolerance for reduced costs
epsel=...      minimum tolerance for rounding values to zero
epsp=...       value that is used as perturbation scalar for
               degenerative problems
f              specifies that branch-and-bound algorithm stops at first
               found solution
ga=...         specifies the absolute MIP gap for branch-and-bound
gr=...         specifies the relative MIP gap for branch-and-bound
improve=...    the iterative improvement level: one of
              0 (default) improve none
              1 improve FTRAN
              2 improve BTRAN
              3 improve FTRAN + BTRAN
                    4 triggers automatic inverse accuracy control in the dual
                      simplex, and when an error gap is exceeded the basis is
                      reinverted
n=...          specify which solution number to return
o=...          specifies that branch-and-bound algorithm stops when
               objective value is better than value
objno=...      objective number: 0 = none, 1 (default) = first
obound=...     a lower bound for the objective function.
               may speed up the calculations
parse_only     parse input file but do not solve
piv=...        simplex pivot rule: one of
              0 select first
              1 select according to Dantzig
              2 (default) select Devex pricing from Paula Harris
              3 select steepest edge
piva           temporarily use first index if cycling is detected
pivf           in case of Steepest Edge, fall back to DEVEX in primal
pivla          scan entering/leaving columns alternatingly left/right
pivll          scan entering/leaving columns left rather than right
pivm           multiple pricing
pivr           adds a small randomization effect to the selected pricer
presolve       presolve problem before start optimizing
presolvel      also eliminate linearly dependent rows
presolver      if the phase 1 solution process finds that a constraint is
               redundant then this constraint is deleted
prim           prefer the primal simplex for both phases
printsol=...   print solution: one of
              0 (default) print nothing
              1 only objective value
              2 obj value+variables
              3 obj value+variables+constraints
              4 obj value+variables+constraints+duals
              5 obj value+variables+constraints+duals+lp model
              6 obj value+variables+constraints+duals+lp model+scales
              7 obj value+variables+constraints+duals+lp model+scales+
                      lp tableau
prlp           print the LP
psols          print (intermediate) feasible solutions
psolsa         print (intermediate) feasible solutions (non-zeros)
r=...          max nbr of pivots between a re-inversion of the matrix
scale          scale the problem
scalemode=...  scale mode:  one of
              1 for scale to convergence using largest absolute value,
              2 for scale based on the simple numerical range, or
              3 (default) for numerical range-based scaling, or
              4 for geometric scaling, or
              7 for Curtis & Reid scaling
             plus
             16 for scale to convergence using logarithmic mean
                      of all values
             32 for also do Power scaling
             64 to make sure that no scaled number is above 1
            128 to scale integer variables
simplexdd      set Phase1 Dual, Phase2 Dual
simplexdp      set Phase1 Dual, Phase2 Primal
simplexpd      set Phase1 Primal, Phase2 Dual
simplexpp      set Phase1 Primal, Phase2 Primal
timeout=...    timeout after sec seconds when not solution found
trace          trace pivot selections
trej=...       minimum pivot value
verbose        verbose mode
version        report version details
wafter         write model after solve (usefull if presolve used)
wantsol=...    solution report without -AMPL: sum of
        1 ==> write .sol file
        2 ==> print primal variable values
        4 ==> print dual variable values
        8 ==> do not print solution message
wfmps=...      write to MPS file in free format
wlp=...        write to LP filename
wmps=...       write to MPS file in fixed format
wxli=...       write file with xli library
wxliname=...   xli library
wxliopt=...    options for xli library

lpsolve command line options

Normally, the lpsolve program is called from AMPL. However the program can also be called stand-alone. When the command is invoked without an option or with the option -?, a list of the possible options is shown:

usage: lpsolve [options] stub [-AMPL] [<assignment> ...]

Options:
        --  {end of options}
        -=  {show name= possibilities}
        -?  {show usage}
        -e  {suppress echoing of assignments}
        -s  {write .sol file (without -AMPL)}
        -v  {just show version}

stub and the -AMPL option is used when the program is called from AMPL.
The -v option shows the version of lpsolve.
The -= option shows all the options that can be passed to lpsolve from within AMPL.
These options can also be specified in an environment variable lpsolve_options.

To call the lpsolve command to solve a model, you first must have a stub file that can be read by lpsolve. This stub file can be created by AMPL as follows:

ampl: model models\diet.mod;
ampl: data models\diet.dat;
ampl: write bdiet;
ampl: quit

This created a binary file diet.nl. As an alternative the command write gdiet; can be used. This creates an ascii file that also can be read. However it is somewhat slower to read, especially when the models are larger.

This creates a file diet.nl in the current directory. This file is the stub file needed by lpsolve:

lpsolve lpsolve diet.nl

This gives:

LP_SOLVE 5.1.1.2: optimal, objective 88.19999999999999
3 simplex iterations

Options can be passed to lpsolve via the environment variable lpsolve_options:

set lpsolve_options=scale scalemode=7 verbose

Then the result of the previous lpsolve command is:

scale
scalemode=7
verbose
Model name:  '' - run #1
Objective:   Minimize(R0)

Submitted:
Model size:        4 constraints,       8 variables,           39 non-zeros.
Constraints:       0 equality,          0 GUB,                  0 SOS.
Variables:         0 integer,           0 semi-cont.,           0 SOS.

Using DUAL simplex for phase 1 and PRIMAL simplex for phase 2.

Optimal solution with dual simplex at iteration          1

lp_solve solution         88.2 final at iteration        1,       0 nodes explor
ed

Excellent numeric accuracy ||*|| = 1.13687e-013

 Memo: Largest [etaPFI v1.0] inv(B) had 0 NZ entries, 0.0x largest basis.
      In the total iteration count 1, 0 (0.0%) were minor/bound swaps.
      There were 0 refactorizations, 0 triggered by time and 0 by density.
             ... on average 1.0 major pivots per refactorization.
      Total solver time was 0.000 seconds.
LP_SOLVE 5.1.1.2: optimal, objective 88.19999999999999
1 simplex iterations

In this mode, the lpsolve option wantsol shows the solution:

set lpsolve_options=wantsol=2
lpsolve diet.nl

This gives:

wantsol=2
LP_SOLVE 5.1.1.2: optimal, objective 88.19999999999999
3 simplex iterations

variable  value
_svar[1]  0
_svar[2]  0
_svar[3]  0
_svar[4]  0
_svar[5]  46.666666666666664
_svar[6]  0
_svar[7]  -3.552713678800501e-15
_svar[8]  0

The -e option results in not echoing the options passed to lpsolve:

set lpsolve_options=wantsol=2
lpsolve -e diet.nl

This gives:

LP_SOLVE 5.1.1.2: optimal, objective 88.19999999999999
3 simplex iterations

variable  value
_svar[1]  0
_svar[2]  0
_svar[3]  0
_svar[4]  0
_svar[5]  46.666666666666664
_svar[6]  0
_svar[7]  -3.552713678800501e-15
_svar[8]  0

lpsolve options can also be passed at the command line, they don't overrule the lpsolve_options environment variable, they are added:

set lpsolve_options=wantsol=2
lpsolve diet.nl "verbose scale"

This gives:

wantsol=2
verbose
scale
Model name:  '' - run #1
Objective:   Minimize(R0)

Submitted:
Model size:        4 constraints,       8 variables,           39 non-zeros.
Constraints:       0 equality,          0 GUB,                  0 SOS.
Variables:         0 integer,           0 semi-cont.,           0 SOS.

Using DUAL simplex for phase 1 and PRIMAL simplex for phase 2.

Optimal solution with dual simplex at iteration          1

lp_solve solution         88.2 final at iteration        1,       0 nodes explor
ed

Excellent numeric accuracy ||*|| = 1.13687e-013

 Memo: Largest [etaPFI v1.0] inv(B) had 0 NZ entries, 0.0x largest basis.
      In the total iteration count 1, 0 (0.0%) were minor/bound swaps.
      There were 0 refactorizations, 0 triggered by time and 0 by density.
             ... on average 1.0 major pivots per refactorization.
      Total solver time was 0.000 seconds.
LP_SOLVE 5.1.1.2: optimal, objective 88.19999999999997
1 simplex iterations

variable  value
_svar[1]  0
_svar[2]  0
_svar[3]  0
_svar[4]  0
_svar[5]  46.66666666666666
_svar[6]  0
_svar[7]  0
_svar[8]  0


Using lpsolve from MATLAB

MATLAB?

MATLAB® is a high-performance language for technical computing. It integrates computation, visualization, and programming in an easy-to-use environment where problems and solutions are expressed in familiar mathematical notation. Typical uses include

  • Math and computation
  • Algorithm development
  • Data acquisition
  • Modelling, simulation, and prototyping
  • Data analysis, exploration, and visualization
  • Scientific and engineering graphics
  • Application development, including graphical user interface building

MATLAB is an interactive system whose basic data element is an array that does not require dimensioning. This allows you to solve many technical computing problems, especially those with matrix and vector formulations, in a fraction of the time it would take to write a program in a scalar noninteractive language such as C or Fortran.

The name MATLAB stands for matrix laboratory. MATLAB was originally written to provide easy access to matrix software developed by the LINPACK and EISPACK projects. Today, MATLAB engines incorporate the LAPACK and BLAS libraries, embedding the state of the art in software for matrix computation.

MATLAB has evolved over a period of years with input from many users. In university environments, it is the standard instructional tool for introductory and advanced courses in mathematics, engineering, and science. In industry, MATLAB is the tool of choice for high-productivity research, development, and analysis.

MATLAB features a family of add-on application-specific solutions called toolboxes. Very important to most users of MATLAB, toolboxes allow you to learn and apply specialized technology. Toolboxes are comprehensive collections of MATLAB functions (M-files) that extend the MATLAB environment to solve particular classes of problems. Areas in which toolboxes are available include signal processing, control systems, neural networks, fuzzy logic, wavelets, simulation, and many others.

We will not discuss the specifics of MATLAB here but instead refer the reader to the MATLAB website and documentation.

MATLAB and lpsolve

lpsolve is callable from MATLAB via an external interface or MEX-function. As such, it looks like lpsolve is fully integrated with MATLAB. Matrices can directly be transferred between MATLAB and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for MATLAB (especially for matrix support). So you have full control to the complete lpsolve functionality via the mxlpsolve MATLAB driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level M-files that can make things a lot easier. See further in this article.

Installation

To make this possible, a driver program is needed: mxlpsolve (mxlpsolve.dll under Windows). This driver must be put in a directory known to MATLAB (specified via File, Set Path or via the MATLAB path command) and MATLAB can call the mxlpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve51.dll under Windows and liblpsolve51.so under Unix/Linux). This has the advantage that the mxlpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows path.

So note the difference between the MATLAB lpsolve driver that is called mxlpsolve and the lpsolve library that implements the API that is called lpsolve51.

There are also some MATLAB script files (.m) as a quick start.

To test if everything is installed correctly, enter mxlpsolve in the MATLAB command window. If it gives the following, then everything is ok:

mxlpsolve MATLAB Interface version 5.1.0.0
using lpsolve version 5.1.1.2

Usage: [ret1, ret2, ...] = mxlpsolve('functionname', arg1, arg2, ...)

However, if you get the following:

mxlpsolve driver not found !!!
Check if mxlpsolve.dll is on your system and in a directory known to MATLAB.
Press enter to see the paths where MATLAB looks for the driver.

Then MATLAB can find the mxlpsolve.m file, but not the mxlpsolve.dll file. This dll should be in the same directory as the .m file.

If you get the following:

??? Undefined function or variable 'mxlpsolve'.

Then MATLAB cannot find the mxlpsolve.* files. Enter path in the command line to see the MATLAB search path for its files. You can modify this path via File, Set Path. Specify the path where the mxlpsolve.* files are located on your system.

If you get the following:

??? Failed to initialise lpsolve library.

Error in ==> ...\mxlpsolve.dll

Then MATLAB can find the mxlpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve51.dll and should be on your system in a directory that in the PATH environment variable. This path can be shown via the following command in MATLAB: !PATH

The lpsolve51.dll files must be in one of these specified directories. It is common to place this in the WINDOWS\system32 folder.

Note that it may also be necessary to restart MATLAB after having put the files in the specified directory. It was noted that MATLAB sometimes doesn't see the newly added files in folders until it is restarted.

All this is developed and tested with MATLAB version 6.0.0.88 Release 12.

Solve an lp model from MATLAB via mxlpsolve

In the following text, >> before the MATLAB commands is the MATLAB prompt. Only the text after >> must be entered.

To call an lpsolve function, the following syntax must be used:

>> [ret1, ret2, ...] = mxlpsolve('functionname', arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between single quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra MATLAB specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in MATLAB, this structure is replaced by a handle. This is an incrementing number starting from 0 and the lprec structures are maintained internally by the mxlpsolve driver. However you will see not much (if any) difference in the use of it.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the MATLAB functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from MATLAB, nothing must be dimensioned in advance. The mxlpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to mxlpsolve. Never as argument to the routine. This can be a single value as for get_objective (although MATLAB stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Note that you can get an overview of the available functionnames and their arguments by entering the following in MATLAB:

>> help mxlpsolve

An example

(Note that you can execute this example by entering command per command as shown below or by just entering example1. This will execute example1.m. You can see its contents by entering type example1.m)

>> lp=mxlpsolve('make_lp', 0, 4);
>> mxlpsolve('set_verbose', lp, 3);
>> mxlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
>> mxlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
>> mxlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
>> mxlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
>> mxlpsolve('set_lowbo', lp, 1, 28.6);
>> mxlpsolve('set_lowbo', lp, 4, 18);
>> mxlpsolve('set_upbo', lp, 4, 48.98);
>> mxlpsolve('set_col_name', lp, 1, 'COLONE');
>> mxlpsolve('set_col_name', lp, 2, 'COLTWO');
>> mxlpsolve('set_col_name', lp, 3, 'COLTHREE');
>> mxlpsolve('set_col_name', lp, 4, 'COLFOUR');
>> mxlpsolve('set_row_name', lp, 1, 'THISROW');
>> mxlpsolve('set_row_name', lp, 2, 'THATROW');
>> mxlpsolve('set_row_name', lp, 3, 'LASTROW');
>> mxlpsolve('write_lp', lp, 'a.lp');
>> mxlpsolve('get_mat', lp, 1, 2)

ans =

   78.2600

>> mxlpsolve('solve', lp)

ans =

     0

>> mxlpsolve('get_objective', lp)

ans =

   31.7828

>> mxlpsolve('get_variables', lp)

ans =

   28.6000
         0
         0
   31.8276

>> mxlpsolve('get_constraints', lp)

ans =

   92.3000
    6.8640
  391.2928

>> mxlpsolve('delete_lp', lp);

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. For example:

>> obj=mxlpsolve('get_objective', lp)

obj =

   31.7828

Or without echoing on screen:

>> obj=mxlpsolve('get_objective', lp);

The last command will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

>> x=mxlpsolve('get_variables', lp);
>> b=mxlpsolve('get_constraints', lp);

It is always possible to show the contents of a variable by just giving it as command:

>> x

x =
  28.6000
        0
        0
  31.8276

Matrices

In MATLAB, all numerical data is stored in matrices; even a scalar variable. MATLAB also supports complex numbers (a + b * i with i=SQRT(-1)). mxlpsolve can only work with real numbers. MATLAB also supports sparse matrices. Sparse matrices are matrices where only the non-zero elements are provided and stored. This results in both less storage and faster calculation if there are a sufficient number of zero values in the matrix and there usually are. The mxlpsolve driver supports both dense and sparse matrices and their use is totally transparent to the user. Everywhere a matrix can be provided, it can be dense or sparse. In the above example all matrices were dense. For example:
>> mxlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);

In sparse matrix notation, this can be written:

>> mxlpsolve('add_constraint', lp, sparse([0.24, 0, 11.31, 0]), 1, 14.8);

Most of the time, variables are used to provide the data:

>> mxlpsolve('add_constraint', lp, a1, 1, 14.8);

Where a1 is a matrix variable that can be dense or sparse.

The mxlpsolve driver sees all provided matrices as sparse matrices. mxlpsolve also uses sparse matrices internally and data can be provided sparse via the ex routines. For example add_constraintex. The mxlpsolve driver always uses the ex routines to provide the data to lpsolve. Even if you call from MATLAB the routine names that would require a dense matrix (for example add_constraint), the mxlpsolve driver will always call the sparse version of the routine (for example add_constraintex). This results in the most performing behaviour. Note that if a dense matrix is provided, the dimension must exactly match the dimension that is expected by mxlpsolve. Matrices with too few or too much elements gives an 'invalid vector.' error. Sparse matrices can off course provide less elements (the non provided elements are seen as zero). However if too many elements are provided or an element with a too large index, again an 'invalid vector.' error is raised.

Most of the time, mxlpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

>> mxlpsolve('add_constraint', lp, [0.24; 0; 11.31; 0], 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the MATLAB interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the MATLAB matrix.

Sets

All numerical data is stored in matrices. Alphanumerical data, however, is more difficult to store in matrices. Matrices require that each element has the same size (length) and that is difficult and unpractical for alphanumerical data. In a limited number of lpsolve routines, alphanumerical data is required or returned and in some also multiple elements. An example is set_col_name. For this, MATLAB sets are used. To specify a set of alphanumerical elements, the following notation is used: { 'element1', 'element2', ... }. Note the { and } symbols instead of [ and ] that are used with matrices.

Maximum usage of matrices/sets with mxlpsolve

Because MATLAB is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the mxlpsolve MATLAB driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The mxlpsolve MATLAB driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = mxlpsolve('set_int', lp_handle, column, must_be_int). The matrix version of this call is: return = mxlpsolve('set_int', lp_handle, [must_be_int]). The API call to return the integer status of a variable is: return = mxlpsolve('is_int', lp_handle, column). The matrix version of this call is: [is_int] = mxlpsolve('is_int', lp_handle)
Also note the get_mat and set_mat routines. In MATLAB these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just entering example2. This will execute example2.m. You can see its contents by entering type example2.m)

>> lp=mxlpsolve('make_lp', 0, 4);
>> mxlpsolve('set_verbose', lp, 3);
>> mxlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
>> mxlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
>> mxlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
>> mxlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
>> mxlpsolve('set_lowbo', lp, [28.6, 0, 0, 18]);
>> mxlpsolve('set_upbo', lp, [Inf, Inf, Inf, 48.98]);
>> mxlpsolve('set_col_name', lp, {'COLONE', 'COLTWO', 'COLTHREE', 'COLFOUR'});
>> mxlpsolve('set_row_name', lp, {'THISROW', 'THATROW', 'LASTROW'});
>> mxlpsolve('write_lp', lp, 'a.lp');
>> mxlpsolve('get_mat', lp)

ans =

         0   78.2600         0    2.9000
    0.2400         0   11.3100         0
   12.6800         0    0.0800    0.9000

>> mxlpsolve('solve', lp)

ans =

     0

>> mxlpsolve('get_objective', lp)

ans =

   31.7828

>> mxlpsolve('get_variables', lp)

ans =

   28.6000
         0
         0
   31.8276

>> mxlpsolve('get_constraints', lp)

ans =

   92.3000
    6.8640
  391.2928

Note the usage of Inf in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -Inf to express minus infinity. This can for example be used to create a free variable.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

>> A=mxlpsolve('get_mat', lp);
>> X=mxlpsolve('get_variables', lp);
>> B = A * X

B =
   92.3000
    6.8640
  391.2928

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

>> mxlpsolve('get_constraints', lp)

ans =

   92.3000
    6.8640
  391.2928

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

>> C=mxlpsolve('get_obj_fn', lp);
>> X=mxlpsolve('get_variables', lp);
>> obj = C * X

obj =

   31.7828

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

>> mxlpsolve('get_objective', lp)

ans =

   31.7828

Again exactly the same as the calculated obj value, as expected.

M-files

MATLAB can execute a sequence of statements stored in diskfiles. Such files are called "M-files" because they must have the file type of ".m" as the last part of their filename (extension). Much of your work with MATLAB will be in creating and refining M-files. M-files are usually created using your local editor.

M-files can be compared with batch files or scripts. You can put MATLAB commands in them and execute them at any time. The M-file is executed like any other command, by entering its name (without the .m extension).

The mxlpsolve MATLAB distribution contains some example M-files to demonstrate this.

To see the contents of such a file, enter the command 'type filename'. You can also edit these files with your favourite text editor (or notepad).

example1.m

Contains the commands as shown in the first example of this article.

example2.m

Contains the commands as shown in the second example of this article.

lp_solve.m

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file or type help lp_solve or just lp_solve to see its usage:

 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

>> [obj, x]=lp_solve([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])

obj =

     3

x =

     1
     2

lp_maker.m

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. See the beginning of the file or type help lp_maker or just lp_maker to see its usage:

>> help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            x >= vlb >= 0
            x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n sparse matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

>> lp=lp_maker([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])

lp =

     0

To solve the model and get the solution:

>> mxlpsolve('solve', lp)

ans =

     0

>> mxlpsolve('get_objective', lp)

ans =

     3

>> mxlpsolve('get_variables', lp)

ans =

     1
     2

Don't forget to free the handle and its associated memory when you are done:

>> mxlpsolve('delete_lp', lp);

lpdemo.m

Contains several examples to build and solve lp models.

ex.m

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution.

Overview of API routines

Note again that the MATLAB command 'help mxlpsolve' gives an overview of all functions that can be called via mxlpsolve with their arguments and return values.

  • add_column, add_columnex
    • return = mxlpsolve('add_column', lp_handle, [column])
    • return = mxlpsolve('add_columnex', lp_handle, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = mxlpsolve('add_constraint', lp_handle, [row], constr_type, rh)
    • return = mxlpsolve('add_constraintex', lp_handle, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = mxlpsolve('add_SOS', lp_handle, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in MATLAB since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = mxlpsolve('column_in_lp', lp_handle, [column])
    • No special considerations.
  • default_basis
    • mxlpsolve('default_basis', lp_handle)
    • No special considerations.
  • del_column
    • return = mxlpsolve('del_column', lp_handle, column)
    • No special considerations.
  • del_constraint
    • return = mxlpsolve('del_constraint', lp_handle, del_row)
    • No special considerations.
  • delete_lp
    • mxlpsolve('delete_lp', lp_handle)
    • No special considerations.
  • free_lp
    • mxlpsolve('free_lp', lp_handle)
    • lp_handle is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = mxlpsolve('get_anti_degen', lp_handle)
    • No special considerations.
  • get_basis
    • [bascolumn] = mxlpsolve('get_basis', lp_handle {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in MATLAB. If not provided, then 0 is used.
  • get_basiscrash
    • return = mxlpsolve('get_basiscrash', lp_handle)
    • No special considerations.
  • get_bb_depthlimit
    • return = mxlpsolve('get_bb_depthlimit', lp_handle)
    • No special considerations.
  • get_bb_floorfirst
    • return = mxlpsolve('get_bb_floorfirst', lp_handle)
    • No special considerations.
  • get_bb_rule
    • return = mxlpsolve('get_bb_rule', lp_handle)
    • No special considerations.
  • get_bounds_tighter
    • return = mxlpsolve('get_bounds_tighter', lp_handle)
    • No special considerations.
  • get_break_at_value
    • return = mxlpsolve('get_break_at_value', lp_handle)
    • No special considerations.
  • get_col_name
    • name = mxlpsolve('get_col_name', lp_handle, column)
    • [names] = mxlpsolve('get_col_name', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_column
    • [column, return] = mxlpsolve('get_column', lp_handle, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = mxlpsolve('get_constr_type', lp_handle, row)
    • [constr_type] = mxlpsolve('get_constr_type', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_constraints
    • [constr, return] = mxlpsolve('get_constraints', lp_handle)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = mxlpsolve('get_dual_solution', lp_handle)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = mxlpsolve('get_epsb', lp_handle)
    • No special considerations.
  • get_epsd
    • return = mxlpsolve('get_epsd', lp_handle)
    • No special considerations.
  • get_epsel
    • return = mxlpsolve('get_epsel', lp_handle)
    • No special considerations.
  • get_epsint
    • return = mxlpsolve('get_epsint', lp_handle)
    • No special considerations.
  • get_epsperturb
    • return = mxlpsolve('get_epsperturb', lp_handle)
    • No special considerations.
  • get_epspivot
    • return = mxlpsolve('get_epspivot', lp_handle)
    • No special considerations.
  • get_improve
    • return = mxlpsolve('get_improve', lp_handle)
    • No special considerations.
  • get_infinite
    • return = mxlpsolve('get_infinite', lp_handle)
    • No special considerations.
  • get_lowbo
    • return = mxlpsolve('get_lowbo', lp_handle, column)
    • [return] = mxlpsolve('get_lowbo', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_lp_index
    • return = mxlpsolve('get_lp_index', lp_handle, orig_index)
    • No special considerations.
  • get_lp_name
    • name = mxlpsolve('get_lp_name', lp_handle)
    • No special considerations.
  • get_mat
    • value = mxlpsolve('get_mat', lp_handle, row, col)
    • [matrix, return] = mxlpsolve('get_mat', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix in the first return value. The return code of the call is the second return value.
  • get_max_level
    • return = mxlpsolve('get_max_level', lp_handle)
    • No special considerations.
  • get_maxpivot
    • return = mxlpsolve('get_maxpivot', lp_handle)
    • No special considerations.
  • get_mip_gap
    • return = mxlpsolve('get_mip_gap', lp_handle, absolute)
    • No special considerations.
  • get_nameindex
    • return = mxlpsolve('get_nameindex', lp_handle, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = mxlpsolve('get_Ncolumns', lp_handle)
    • No special considerations.
  • get_negrange
    • return = mxlpsolve('get_negrange', lp_handle)
    • No special considerations.
  • get_nonzeros
    • return = mxlpsolve('get_nonzeros', lp_handle)
    • No special considerations.
  • get_Norig_columns
    • return = mxlpsolve('get_Norig_columns', lp_handle)
    • No special considerations.
  • get_Norig_rows
    • return = mxlpsolve('get_Norig_rows', lp_handle)
    • No special considerations.
  • get_Nrows
    • return = mxlpsolve('get_Nrows', lp_handle)
    • No special considerations.
  • get_obj_bound
    • return = mxlpsolve('get_obj_bound', lp_handle)
    • No special considerations.
  • get_objective
    • return = mxlpsolve('get_objective', lp_handle)
    • No special considerations.
  • get_orig_index
    • return = mxlpsolve('get_orig_index', lp_handle, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = mxlpsolve('get_origcol_name', lp_handle, column)
    • [names] = mxlpsolve('get_origcol_name', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_origrow_name
    • name = mxlpsolve('get_origrow_name', lp_handle, row)
    • [names] = mxlpsolve('get_origrow_name', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_pivoting
    • return = mxlpsolve('get_pivoting', lp_handle)
    • No special considerations.
  • get_presolve
    • return = mxlpsolve('get_presolve', lp_handle)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = mxlpsolve('get_primal_solution', lp_handle)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = mxlpsolve('get_print_sol', lp_handle)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = mxlpsolve('get_rh', lp_handle, row)
    • [rh] = mxlpsolve('get_rh', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix. Note that in this case, the value of row 0 is not returned.
  • get_rh_range
    • return = mxlpsolve('get_rh_range', lp_handle, row)
    • [rh_ranges] = mxlpsolve('get_rh_range', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_row
    • [row, return] = mxlpsolve('get_row', lp_handle, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = mxlpsolve('get_row_name', lp_handle, row)
    • [names] = mxlpsolve('get_row_name', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_scalelimit
    • return = mxlpsolve('get_scalelimit', lp_handle)
    • No special considerations.
  • get_scaling
    • return = mxlpsolve('get_scaling', lp_handle)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = mxlpsolve('get_sensitivity_obj', lp_handle)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = mxlpsolve('get_sensitivity_objex', lp_handle)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that MATLAB allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = mxlpsolve('get_sensitivity_obj', lp_handle). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, MATLAB always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = mxlpsolve('get_sensitivity_rhs', lp_handle)
    • [duals, dualsfrom, dualstill, return] = mxlpsolve('get_sensitivity_rhsex', lp_handle)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that MATLAB allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = mxlpsolve('get_sensitivity_rhs', lp_handle). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = mxlpsolve('get_simplextype', lp_handle)
    • No special considerations.
  • get_solutioncount
    • return = mxlpsolve('get_solutioncount', lp_handle)
    • No special considerations.
  • get_solutionlimit
    • return = mxlpsolve('get_solutionlimit', lp_handle)
    • No special considerations.
  • get_status
    • return = mxlpsolve('get_status', lp_handle)
    • No special considerations.
  • get_statustext
    • return = mxlpsolve('get_statustext', lp_handle, statuscode)
    • No special considerations.
  • get_timeout
    • return = mxlpsolve('get_timeout', lp_handle)
    • No special considerations.
  • get_total_iter
    • return = mxlpsolve('get_total_iter', lp_handle)
    • No special considerations.
  • get_total_nodes
    • return = mxlpsolve('get_total_nodes', lp_handle)
    • No special considerations.
  • get_upbo
    • return = mxlpsolve('get_upbo', lp_handle, column)
    • [upbo] = mxlpsolve('get_upbo', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_var_branch
    • return = mxlpsolve('get_var_branch', lp_handle, column)
    • [var_branch] = mxlpsolve('get_var_branch', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_var_dualresult
    • return = mxlpsolve('get_var_dualresult', lp_handle, index)
    • No special considerations.
  • get_var_primalresult
    • return = mxlpsolve('get_var_primalresult', lp_handle, index)
    • No special considerations.
  • get_var_priority
    • return = mxlpsolve('get_var_priority', lp_handle, column)
    • [var_priority] = mxlpsolve('get_var_priority', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_variables
    • [var, return] = mxlpsolve('get_variables', lp_handle)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = mxlpsolve('get_verbose', lp_handle)
    • No special considerations.
  • get_working_objective
    • return = mxlpsolve('get_working_objective', lp_handle)
    • No special considerations.
  • has_BFP
    • return = mxlpsolve('has_BFP', lp_handle)
    • No special considerations.
  • has_XLI
    • return = mxlpsolve('has_XLI', lp_handle)
    • No special considerations.
  • is_add_rowmode
    • return = mxlpsolve('is_add_rowmode', lp_handle)
    • No special considerations.
  • is_anti_degen
    • return = mxlpsolve('is_anti_degen', lp_handle, testmask)
    • No special considerations.
  • is_binary
    • return = mxlpsolve('is_binary', lp_handle, column)
    • [binary] = mxlpsolve('is_binary', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_break_at_first
    • return = mxlpsolve('is_break_at_first', lp_handle)
    • No special considerations.
  • is_constr_type
    • return = mxlpsolve('is_constr_type', lp_handle, row, mask)
    • No special considerations.
  • is_debug
    • return = mxlpsolve('is_debug', lp_handle)
    • No special considerations.
  • is_feasible
    • return = mxlpsolve('is_feasible', lp_handle, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free
    • return = mxlpsolve('is_free', lp_handle, column)
    • [free] = mxlpsolve('is_free', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_infinite
    • return = mxlpsolve('is_infinite', lp_handle, value)
    • No special considerations.
  • is_int
    • return = mxlpsolve('is_int', lp_handle, column)
    • [int] = mxlpsolve('is_int', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_integerscaling
    • return = mxlpsolve('is_integerscaling', lp_handle)
    • No special considerations.
  • is_maxim
    • return = mxlpsolve('is_maxim', lp_handle)
    • No special considerations.
  • is_nativeBFP
    • return = mxlpsolve('is_nativeBFP', lp_handle)
    • No special considerations.
  • is_nativeXLI
    • return = mxlpsolve('is_nativeXLI', lp_handle)
    • No special considerations.
  • is_negative
    • return = mxlpsolve('is_negative', lp_handle, column)
    • [negative] = mxlpsolve('is_negative', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_piv_mode
    • return = mxlpsolve('is_piv_mode', lp_handle, testmask)
    • No special considerations.
  • is_piv_rule
    • return = mxlpsolve('is_piv_rule', lp_handle, rule)
    • No special considerations.
  • is_presolve
    • return = mxlpsolve('is_presolve', lp_handle, testmask)
    • No special considerations.
  • is_scalemode
    • return = mxlpsolve('is_scalemode', lp_handle, testmask)
    • No special considerations.
  • is_scaletype
    • return = mxlpsolve('is_scaletype', lp_handle, scaletype)
    • No special considerations.
  • is_semicont
    • return = mxlpsolve('is_semicont', lp_handle, column)
    • [semicont] = mxlpsolve('is_semicont', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_SOS_var
    • return = mxlpsolve('is_SOS_var', lp_handle, column)
    • [SOS_var] = mxlpsolve('is_SOS_var', lp_handle)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_trace
    • return = mxlpsolve('is_trace', lp_handle)
    • No special considerations.
  • lp_solve_version
    • versionstring = mxlpsolve('lp_solve_version')
    • The mxlpsolve API routine returns the version information in 4 provided argument variables while the MATLAB version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = mxlpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • mxlpsolve('print_constraints', lp_handle {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
    • The same information can also be obtained via mxlpsolve('get_constraints', lp_handle). This shows the result on screen.
  • print_debugdump
    • return = mxlpsolve('print_debugdump', lp_handle, filename)
    • No special considerations.
  • print_duals
    • mxlpsolve('print_duals', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
    • The same information can be obtained via mxlpsolve('get_dual_solution', lp_handle). This shows the result on screen.
  • print_lp
    • mxlpsolve('print_lp', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
  • print_objective
    • mxlpsolve('print_objective', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
    • The same information can be obtained via mxlpsolve('get_objective', lp_handle). This shows the result on screen.
  • print_scales
    • mxlpsolve('print_scales', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
  • print_solution
    • mxlpsolve('print_solution', lp_handle {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
    • The same information can also be obtained via mxlpsolve('get_variables', lp_handle). This shows the result on screen.
  • print_str
    • mxlpsolve('print_str', lp_handle, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
  • print_tableau
    • mxlpsolve('print_tableau', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the mxlpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows MATLAB) to the command window of MATLAB. As such, all reported output can be seen in MATLAB. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_freemps, read_freeMPS
    • lp_handle = mxlpsolve('read_freemps', filename {, verbose})
    • lp_handle = mxlpsolve('read_freeMPS', filename {, verbose})
    • In the lpsolve API, read_freemps needs a FILE handle. In MATLAB it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = mxlpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = mxlpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In MATLAB it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = mxlpsolve('read_mps', filename {, verbose})
    • lp_handle = mxlpsolve('read_MPS', filename {, verbose})
    • In the lpsolve API, read_mps needs a FILE handle. In MATLAB it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not specified, then NORMAL is used.
  • read_XLI
    • lp_handle = mxlpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
    • Not implemented.
    • Use default_basis
  • set_add_rowmode
    • return = mxlpsolve('set_add_rowmode', lp_handle, turnon)
    • No special considerations.
  • set_anti_degen
    • mxlpsolve('set_anti_degen', lp_handle, anti_degen)
    • No special considerations.
  • set_basis
    • return = mxlpsolve('set_basis', lp_handle, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
  • set_basiscrash
    • mxlpsolve('set_basiscrash', lp_handle, mode)
    • No special considerations.
  • set_bb_depthlimit
    • mxlpsolve('set_bb_depthlimit', lp_handle, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • mxlpsolve('set_bb_floorfirst', lp_handle, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • mxlpsolve('set_bb_rule', lp_handle, bb_rule)
    • No special considerations.
  • set_BFP
    • return = mxlpsolve('set_BFP', lp_handle, filename)
    • No special considerations.
  • set_binary
    • return = mxlpsolve('set_binary', lp_handle, column, must_be_bin)
    • return = mxlpsolve('set_binary', lp_handle, [must_be_bin])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = mxlpsolve('set_bounds', lp_handle, column, lower, upper)
    • return = mxlpsolve('set_bounds', lp_handle, [lower], [upper])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • mxlpsolve('set_bounds_tighter', lp_handle, tighten)
    • No special considerations.
  • set_break_at_first
    • mxlpsolve('set_break_at_first', lp_handle, break_at_first)
    • No special considerations.
  • set_break_at_value
    • mxlpsolve('set_break_at_value', lp_handle, break_at_value)
    • No special considerations.
  • set_col_name
    • return = mxlpsolve('set_col_name', lp_handle, column, name)
    • return = mxlpsolve('set_col_name', lp_handle, [names])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = mxlpsolve('set_column', lp_handle, col_no, [column])
    • return = mxlpsolve('set_columnex', lp_handle, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = mxlpsolve('set_constr_type', lp_handle, row, con_type)
    • return = mxlpsolve('set_constr_type', lp_handle, [con_type])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • mxlpsolve('set_debug', lp_handle, debug)
    • No special considerations.
  • set_epsb
    • mxlpsolve('set_epsb', lp_handle, epsb)
    • No special considerations.
  • set_epsd
    • mxlpsolve('set_epsd', lp_handle, epsd)
    • No special considerations.
  • set_epsel
    • mxlpsolve('set_epsel', lp_handle, epsel)
    • No special considerations.
  • set_epsint
    • mxlpsolve('set_epsint', lp_handle, epsint)
    • No special considerations.
  • set_epsperturb
    • mxlpsolve('set_epsperturb', lp_handle, epsperturb)
    • No special considerations.
  • set_epspivot
    • mxlpsolve('set_epspivot', lp_handle, epspivot)
    • No special considerations.
  • set_free
    • return = mxlpsolve('set_free', lp_handle, column)
    • No special considerations.
  • set_improve
    • mxlpsolve('set_improve', lp_handle, improve)
    • No special considerations.
  • set_infinite
    • mxlpsolve('set_infinite', lp_handle, infinite)
    • No special considerations.
  • set_int
    • return = mxlpsolve('set_int', lp_handle, column, must_be_int)
    • return = mxlpsolve('set_int', lp_handle, [must_be_int])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = mxlpsolve('set_lowbo', lp_handle, column, value)
    • return = mxlpsolve('set_lowbo', lp_handle, [values])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = mxlpsolve('set_lp_name', lp_handle, name)
    • No special considerations.
  • set_mat
    • return = mxlpsolve('set_mat', lp_handle, row, column, value)
    • return = mxlpsolve('set_mat', lp_handle, [matrix])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. Consider using a MATLAB sparse matrix for maximum performance and least memory usage. The matrix must be two-dimentional.
  • set_maxim
    • mxlpsolve('set_maxim', lp_handle)
    • No special considerations.
  • set_maxpivot
    • mxlpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • mxlpsolve('set_minim', lp_handle)
    • No special considerations.
  • set_mip_gap
    • mxlpsolve('set_mip_gap', lp_handle, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • mxlpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = mxlpsolve('set_obj', lp_handle, column, value)
    • return = mxlpsolve('set_obj', lp_handle, [values])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • mxlpsolve('set_obj_bound', lp_handle, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = mxlpsolve('set_obj_fn', lp_handle, [row])
    • return = mxlpsolve('set_obj_fnex', lp_handle, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
  • set_outputfile
    • return = mxlpsolve('set_outputfile', lp_handle, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In MATLAB under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • mxlpsolve('set_pivoting', lp_handle, pivoting)
    • No special considerations.
  • set_preferdual
    • mxlpsolve('set_preferdual', lp_handle, dodual)
    • No special considerations.
  • set_presolve
    • mxlpsolve('set_presolve', lp_handle, do_presolve)
    • No special considerations.
  • set_print_sol
    • mxlpsolve('set_print_sol', lp_handle, print_sol)
    • No special considerations.
  • set_rh
    • return = mxlpsolve('set_rh', lp_handle, row, value)
    • return = mxlpsolve('set_rh', lp_handle, [values])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = mxlpsolve('set_rh_range', lp_handle, row, deltavalue)
    • return = mxlpsolve('set_rh_range', lp_handle, [deltavalues])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • mxlpsolve('set_rh_vec', lp_handle, [rh])
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = mxlpsolve('set_row', lp_handle, row_no, [row])
    • return = mxlpsolve('set_rowex', lp_handle, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
  • set_row_name
    • return = mxlpsolve('set_row_name', lp_handle, row, name)
    • return = mxlpsolve('set_row_name', lp_handle, [names])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • mxlpsolve('set_scalelimit', lp_handle, scalelimit)
    • No special considerations.
  • set_scaling
    • mxlpsolve('set_scaling', lp_handle, scalemode)
    • No special considerations.
  • set_semicont
    • return = mxlpsolve('set_semicont', lp_handle, column, must_be_sc)
    • return = mxlpsolve('set_semicont', lp_handle, [must_be_sc])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • mxlpsolve('set_sense', lp_handle, maximize)
    • No special considerations.
  • set_simplextype
    • mxlpsolve('set_simplextype', lp_handle, simplextype)
    • No special considerations.
  • set_solutionlimit
    • mxlpsolve('set_solutionlimit', lp_handle, simplextype)
    • No special considerations.
  • set_timeout
    • mxlpsolve('set_timeout', lp_handle, sectimeout)
    • No special considerations.
  • set_trace
    • mxlpsolve('set_trace', lp_handle, trace)
    • No special considerations.
  • set_upbo
    • return = mxlpsolve('set_upbo', lp_handle, column, value)
    • return = mxlpsolve('set_upbo', lp_handle, [values])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_branch
    • return = mxlpsolve('set_var_branch', lp_handle, column, branch_mode)
    • return = mxlpsolve('set_var_branch', lp_handle, [branch_mode])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = mxlpsolve('set_var_weights', lp_handle, [weights])
    • No special considerations.
  • set_verbose
    • mxlpsolve('set_verbose', lp_handle, verbose)
    • No special considerations.
  • set_XLI
    • return = mxlpsolve('set_XLI', lp_handle, filename)
    • No special considerations.
  • solve
    • result = mxlpsolve('solve', lp_handle)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = mxlpsolve('time_elapsed', lp_handle)
    • No special considerations.
  • unscale
    • mxlpsolve('unscale', lp_handle)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = mxlpsolve('write_freemps', lp_handle, filename)
    • return = mxlpsolve('write_freeMPS', lp_handle, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In MATLAB it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = mxlpsolve('write_lp', lp_handle, filename)
    • return = mxlpsolve('write_LP', lp_handle, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In MATLAB it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = mxlpsolve('write_mps', lp_handle, filename)
    • return = mxlpsolve('write_MPS', lp_handle, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In MATLAB it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = mxlpsolve('write_XLI', lp_handle, filename {, options {, results}})
    • No special considerations.

Extra MATLAB routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = mxlpsolve('get_col_names', lp_handle)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = mxlpsolve('get_constr_types', lp_handle)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = mxlpsolve('get_int', lp_handle)
    • The same as is_int. Implemented for backwards compatibility.
  • return = mxlpsolve('get_no_cols', lp_handle)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = mxlpsolve('get_no_rows', lp_handle)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = mxlpsolve('get_objective_name', lp_handle)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = mxlpsolve('get_obj_fn', lp_handle)
    [row_vec, return] = mxlpsolve('get_obj_fun', lp_handle)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = mxlpsolve('get_problem_name', lp_handle)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = mxlpsolve('get_reduced_costs', lp_handle)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = mxlpsolve('get_row_names', lp_handle)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = mxlpsolve('get_solution', lp_handle)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = mxlpsolve('mat_elm', lp_handle)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = mxlpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = mxlpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.

Compile the mxlpsolve driver

Windows

Under Windows, the mxlpsolve MATLAB driver is a dll: mxlpsolve.dll
This dll is an interface to the lpsolve51.dll lpsolve dll that contains the implementation of lp_solve. lpsolve51.dll is distributed with the lp_solve package. The mxlpsolve MATLAB driver dll (mxlpsolve.dll) is just a wrapper between MATLAB and lp_solve to translate the input/output to/from MATLAB and the lp_solve library.

The mxlpsolve MATLAB driver is written in C. To compile this code, the MATLAB compiler is needed (mex). This compiler must be called from MATLAB. To make the compilation process easier, a makefile can be used: MakefileWin.m
Enter 'help MakefileWin' from the MATLAB command window to see a list of options.
It may be necessary to edit this file first to change the path where lp_solve is installed. Change at the beginning lpsolvepath.
To make for release, just enter MakefileWin and everything is build.
This compiles two source files: lpsolve.c and hash.c
Then these are linked with the library lp_explicit.lib to generate the mxlpsolve.dll file. The lp_explicit.lib file is a wrapper library between the lp_solve dll and the compiled application. This wrapper is needed because the lp_solve dll uses __stdcall calling convention. There seems to be a problem in MATLAB to call __stdcall functions directly (unexpected crashes). The lp_explicit library uses __cdecl calling convention and this then calls the lp_solve dll which uses __stdcall calling convention. Looks a bit complex, but it works without any problem.
The optional arguments to MakefileWin are used for development. The first argument allows specifying a filename so that only this file is build. For example hash.c should only be compiled once while developing. So specifying 'lpsolve.c' as first argument will only compile this file and then link everything. This makes the build process a bit faster. The second argument is by default 0. When set to 1, then extra argument checking is done and while executing, some debug information is printed. Should only be used for debugging purposes. When released, this parameter should be 0. The third argument is by default 1. When set to 0, the makefile will not ask to press enter to start building.

There appears to be another way to compile MATLAB mex files with gcc for Windows. This is not tested. See Compiling Matlab mex files with gcc for Windows.

Unix/Linux

Untested! Should be something like.

<MATLAB-DIR>/bin/mex -I../../.. -L../../../lpsolve51 -O3 lpsolve.c hash.c -llpsolve51 -lm

Note: A full path to mex has been given in case teTeX is installed and so there is another mex:

$ which mex
/usr/local/teTeX/bin/mex

If anyone has made this work, please let know to Peter Notebaert to update this document.

See also Using lpsolve from Scilab, Using lpsolve from O-Matrix


Using lpsolve from O-Matrix

O-Matrix?

O-Matrix is an integrated environment for analysing and visualizing data, and building turnkey scientific and engineering computing solutions. The program includes hundreds of engineering and statistical functions for solving a broad range of technical computing problems. Easy-to-use and flexible plotting commands enable you to rapidly build design prototypes, and implement sophisticated systems.

The foundation of O-Matrix is a high-performance matrix language that is specifically designed for high-performance technical computing. The notation of this language will dramatically reduce your design and implementation efforts, and enable the construction of systems that execute far quicker than other interpreted environments. O-Matrix also provides a compatibility mode that enables you to run MATLAB© m-files. This enables you to leverage existing m-files, and simplifies the transition to O-Matrix for users experienced with MATLAB.

The O-Matrix environment is interpreted which means your commands are immediately executed as you enter them. Textual output is displayed in the Command window, and plotting commands are displayed in one or more Graphic windows. The environment provides a debugger for debugging, analysing, and profiling complex algorithms.

We will not discuss the specifics of O-Matrix here but instead refer the reader to the O-Matrix website.

O-Matrix and lpsolve

lpsolve is callable from O-Matrix via a dynamic linked DLL function. As such, it looks like lpsolve is fully integrated with O-Matrix. Matrices can directly be transferred between O-Matrix and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for O-Matrix (especially for matrix support). So you have full control to the complete lpsolve functionality via the omlpsolve O-Matrix driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level script files that can make things a lot easier. See further in this article.

Quickstart

Compile and build omlpsolve:
----------------------------

1. Under Windows, the Microsoft Visual C/C++ compiler must be installed
   and the environment variables must be active do that when a command prompt
   is opened, the cl and nmake commands can be executed.

2. Go to directory lp_solve_5.1\extra\O-Matrix\lpsolve

3. To compile and build omlpsolve, enter the following command:
      cvc

Load the omlpsolve driver in the O-Matrix memory space:
-------------------------------------------------------

1. Under Windows, make sure that the lpsolve51.dll file is somewhere in the path

2. A precompiled library is provided for Windows (omlpsolve.dll).

3. Start O-Matrix

4. Enter the following command in O-Matrix:
      O> dll <path>\omlpsolve.dll, omlpsolve
   This can also be added in autoexec.oms to automatically load the omlpsolve driver.

Note that O-Matrix version 5.8 or above is strongly recommended. Lower versions (at least 5.7) should work with this driver, but these versions don't have the ability to print information on the command prompt. For example default while a solve is done, information is printed to the command window. This will only be visible from version 5.8 or above.

Installation

To make this possible, a driver program is needed: omlpsolve (omlpsolve.dll under Windows). This driver must be loaded in O-Matrix and O-Matrix can call the omlpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve51.dll under Windows). This has the advantage that the omlpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows path.

So note the difference between the O-Matrix lpsolve driver that is called omlpsolve and the lpsolve library that implements the API that is called lpsolve51.

There are also some O-Matrix script files (.oms) as a quick start.

The first thing that must be done, each time O-Matrix is restarted and you want to use lpsolve is load the omlpsolve driver into the O-Matrix workspace. This is done via the dll command. Suppose that omlpsolve.dll is installed in c:\omwin\dll, then the following command must be used to load the driver:

dll c:\omwin\dll\omlpsolve.dll, omlpsolve

That is basically all you need to do. From now on, you can use the library. This until a clear command is given or O-Matrix is restarted. Then this command must be given again to reload the library.

To make things easier, you can edit the file autoexec.oms with your favourite editor (or notepad) in the omwin folder and add above line at the end of this file (before the last end). That will automatically load the lpsolve driver in memory when O-Matrix is started and also when a clear command is executed. So it will appear as if the omlpsolve command is then always available.

To test if everything is installed correctly, enter omlpsolve in the O-Matrix command prompt. If it gives the following, then everything is ok:

omlpsolve O-Matrix Interface version 5.1.0.0
using lpsolve version 5.1.1.2

Usage: [ret1, ret2, ...] = omlpsolve("functionname", arg1, arg2, ...)

Possibly, this is followed with:

No printing capability to command window available.
You need to upgrade to version 5.8 for this feature.

Then you are working with an O-Matrix version lower than 5.8. The driver should work, but nothing is printed on the command window when lpsolve has something to report (for example while solving).

However, if you get a message box with the following:

The identifier omlpsolve is not defined.

Then either the dll command that was previous given was unsuccessful (or not given at all) or something was misspelled after the ,

If you get the following:

This application has failed to start because lpsolve51.dll was not found. Re-installing the application may fix this problem.

Then O-Matrix can find the omlpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve51.dll and should be on your system in a directory that in the PATH environment variable. This path can be shown via the command getenv("PATH")

The lpsolve51.dll files must be in one of these specified directories. It is common to place this in the WINDOWS\system32 folder.

All this is developed and tested with O-Matrix version 5.7. This is the minimum supported release. Older releases are unsupported.

Solve an lp model from O-Matrix via omlpsolve

In the following text, O> before the O-Matrix commands is the O-Matrix command line. Only the text after O> must be entered.

To call an lpsolve function, the following syntax must be used:

O> [ret1, ret2, ...] = omlpsolve("functionname", arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between double quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra O-Matrix specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in O-Matrix, this structure is replaced by a handle. This is an incrementing number starting from 0 and the lprec structures are maintained internally by the omlpsolve driver. However you will see not much (if any) difference in the use of it.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the O-Matrix functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from O-Matrix, nothing must be dimensioned in advance. The omlpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to omlpsolve. Never as argument to the routine. This can be a single value as for get_objective (although O-Matrix stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

An example

(Note that you can execute this example by entering command per command as shown below or by just entering example1. This will execute example1.oms.)

O> lp=omlpsolve("make_lp", 0, 4);
O> omlpsolve("set_verbose", lp, 3);
O> omlpsolve("set_obj_fn", lp, [1, 3, 6.24, 0.1]);
O> omlpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], 2, 92.3);
O> omlpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);
O> omlpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], 2, 4);
O> omlpsolve("set_lowbo", lp, 1, 28.6);
O> omlpsolve("set_lowbo", lp, 4, 18);
O> omlpsolve("set_upbo", lp, 4, 48.98);
O> omlpsolve("set_col_name", lp, 1, "COLONE");
O> omlpsolve("set_col_name", lp, 2, "COLTWO");
O> omlpsolve("set_col_name", lp, 3, "COLTHREE");
O> omlpsolve("set_col_name", lp, 4, "COLFOUR");
O> omlpsolve("set_row_name", lp, 1, "THISROW");
O> omlpsolve("set_row_name", lp, 2, "THATROW");
O> omlpsolve("set_row_name", lp, 3, "LASTROW");
O> omlpsolve("write_lp", lp, "a.lp");
O> omlpsolve("get_mat", lp, 1, 2)
   78.2600
O> omlpsolve("solve", lp)
     0
O> omlpsolve("get_objective", lp)
   31.7828
O> omlpsolve("get_variables", lp)
{
28.6
0
0
31.8276
}

O> omlpsolve("get_constraints", lp)
{
92.3
6.8640
391.293
}

O> omlpsolve("delete_lp", lp);

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. In that case the result is never shown. With or without a terminating semicolon. For example:

O> obj=omlpsolve("get_objective", lp)

Or:

O> obj=omlpsolve("get_objective", lp);

Both will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

O> x=omlpsolve("get_variables", lp);
O> b=omlpsolve("get_constraints", lp);

It is always possible to show the contents of a variable by just giving it as command:

O> x
{
28.6
0
0
31.8276
}

Matrices

In O-Matrix, all numerical data is stored in matrices; even a scalar variable. O-Matrix also supports complex numbers. omlpsolve can only work with real numbers. For example:
O> omlpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);

Most of the time, variables are used to provide the data:

O> omlpsolve("add_constraint", lp, a1, 1, 14.8);

Where a1 is a matrix variable.

Matrices with too few or too much elements gives an 'invalid vector.' error.

Most of the time, omlpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

O> omlpsolve("add_constraint", lp, {0.24, 0, 11.31, 0}, 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the O-Matrix interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the O-Matrix matrix.

Maximum usage of matrices with omlpsolve

Because O-Matrix is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the omlpsolve O-Matrix driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The omlpsolve O-Matrix driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = omlpsolve("set_int", lp_handle, column, must_be_int). The matrix version of this call is: return = omlpsolve("set_int", lp_handle, [must_be_int]). The API call to return the integer status of a variable is: return = omlpsolve("is_int", lp_handle, column). The matrix version of this call is: [is_int] = omlpsolve("is_int", lp_handle)
Also note the get_mat and set_mat routines. In O-Matrix these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just entering example2. This will execute example2.oms.)

O> lp=omlpsolve("make_lp", 0, 4);
O> omlpsolve("set_verbose", lp, 3);
O> omlpsolve("set_obj_fn", lp, [1, 3, 6.24, 0.1]);
O> omlpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], 2, 92.3);
O> omlpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);
O> omlpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], 2, 4);
O> omlpsolve("set_lowbo", lp, [28.6, 0, 0, 18]);
O> omlpsolve("set_upbo", lp, [INF, INF, INF, 48.98]);
O> omlpsolve("set_col_name", lp, {"COLONE", "COLTWO", "COLTHREE", "COLFOUR"});
O> omlpsolve("set_row_name", lp, {"THISROW", "THATROW", "LASTROW"});
O> omlpsolve("write_lp", lp, "a.lp");
O> omlpsolve("get_mat", lp)
{
[ 0 , 78.26 , 0 , 2.9 ]
[ 0.24 , 0 , 11.31 , 0 ]
[ 12.68 , 0 , 0.08 , 0.9 ]
}

O> omlpsolve("solve", lp)
0
O> omlpsolve("get_objective", lp)
31.7828
O> omlpsolve("get_variables", lp)
{
28.6
0
0
31.8276
}

O> omlpsolve("get_constraints", lp)
{
92.3
6.8640
391.293
}

Note the usage of INF in set_upbo. This stands for "infinity". Meaning an infinite upper bound. It is also possible to use -INF to express minus infinity. This can for example be used to create a free variable.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

O> A=omlpsolve("get_mat", lp);
O> X=omlpsolve("get_variables", lp);
O> B = A * X
O> B
{
92.3
6.864
391.293
}

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

O> omlpsolve("get_constraints", lp)
{
92.3
6.864
391.293
}

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

O> C=omlpsolve("get_obj_fn", lp);
O> X=omlpsolve("get_variables", lp);
O> obj = C * X
O> obj
31.7828

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

O> omlpsolve("get_objective", lp)
31.7828

Again exactly the same as the calculated obj value, as expected.

oms scripts

O-Matrix can execute a sequence of statements stored in files. Such files are called oms files because they must have the file type of ".oms" as the last part of their filename (extension).

oms scripts can be compared with batch files or scripts. You can put O-Matrix commands in them and execute them at any time. The oms script is executed like any other command, by entering its name (without the .oms extension).

The omlpsolve O-Matrix distribution contains some example oms scripts to demonstrate this.

You can also edit these files with your favourite text editor (or notepad).

example1.oms

Contains the commands as shown in the first example of this article. To execute and also see which commands are executed in the debug window, use following commands:

O> stop
O> trace on example1.oms
O> quit
O> example1

Note however that execution is much slower when trace is on. It is only used here to see the statements executed.

example2.oms

Contains the commands as shown in the second example of this article. To execute and also see which commands are executed in the debug window, use following commands:

O> stop
O> trace on example2.oms
O> quit
O> example2

Note however that execution is much slower when trace is on. It is only used here to see the statements executed.

lp_solve.oms

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file to see its usage:

 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

O> include lp_solve.oms
O> [obj, x]=lp_solve([-1, 2], {[2, 1], [-4, 4]}, [5, 5], [-1, -1], [], [], [1, 2])
O> obj
3
O> x
{
1
2
}

lp_maker.oms

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. See the beginning of the file to see its usage:

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            x >= vlb >= 0
            x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n sparse matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

O> include lp_maker.oms
O> lp=lp_maker([-1, 2], {[2, 1], [-4, 4]}, [5, 5], [-1, -1], [], [], [1, 2])
O> lp
0

To solve the model and get the solution:

O> omlpsolve("solve", lp)
0
O> omlpsolve("get_objective", lp)
3
O> omlpsolve("get_variables", lp)
{
1
2
}

Don't forget to free the handle and its associated memory when you are done:

O> omlpsolve("delete_lp", lp);

lpdemo.oms

Contains several examples to build and solve lp models. To execute and also see which commands are executed in the debug window, use following commands:

O> stop
O> trace on lpdemo.oms
O> quit
O> lpdemo

Note however that execution is much slower when trace is on. It is only used here to see the statements executed.

ex.oms

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution. To execute and also see which commands are executed in the debug window, use following commands:

O> stop
O> trace on ex.oms
O> quit
O> ex

Note however that execution is much slower when trace is on. It is only used here to see the statements executed.

Overview of API routines

  • add_column, add_columnex
    • return = omlpsolve("add_column", lp_handle, [column])
    • return = omlpsolve("add_columnex", lp_handle, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = omlpsolve("add_constraint", lp_handle, [row], constr_type, rh)
    • return = omlpsolve("add_constraintex", lp_handle, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = omlpsolve("add_SOS", lp_handle, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in O-Matrix since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = omlpsolve("column_in_lp", lp_handle, [column])
    • No special considerations.
  • default_basis
    • omlpsolve("default_basis", lp_handle)
    • No special considerations.
  • del_column
    • return = omlpsolve("del_column", lp_handle, column)
    • No special considerations.
  • del_constraint
    • return = omlpsolve("del_constraint", lp_handle, del_row)
    • No special considerations.
  • delete_lp
    • omlpsolve("delete_lp", lp_handle)
    • No special considerations.
  • free_lp
    • omlpsolve("free_lp", lp_handle)
    • lp_handle is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = omlpsolve("get_anti_degen", lp_handle)
    • No special considerations.
  • get_basis
    • [bascolumn] = omlpsolve("get_basis", lp_handle {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in O-Matrix. If not provided, then 0 is used.
  • get_basiscrash
    • return = omlpsolve("get_basiscrash", lp_handle)
    • No special considerations.
  • get_bb_depthlimit
    • return = omlpsolve("get_bb_depthlimit", lp_handle)
    • No special considerations.
  • get_bb_floorfirst
    • return = omlpsolve("get_bb_floorfirst", lp_handle)
    • No special considerations.
  • get_bb_rule
    • return = omlpsolve("get_bb_rule", lp_handle)
    • No special considerations.
  • get_bounds_tighter
    • return = omlpsolve("get_bounds_tighter", lp_handle)
    • No special considerations.
  • get_break_at_value
    • return = omlpsolve("get_break_at_value", lp_handle)
    • No special considerations.
  • get_col_name
    • name = omlpsolve("get_col_name", lp_handle, column)
    • [names] = omlpsolve("get_col_name", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_column
    • [column, return] = omlpsolve("get_column", lp_handle, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = omlpsolve("get_constr_type", lp_handle, row)
    • [constr_type] = omlpsolve("get_constr_type", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_constraints
    • [constr, return] = omlpsolve("get_constraints", lp_handle)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = omlpsolve("get_dual_solution", lp_handle)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In O-Matrix, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = omlpsolve("get_epsb", lp_handle)
    • No special considerations.
  • get_epsd
    • return = omlpsolve("get_epsd", lp_handle)
    • No special considerations.
  • get_epsel
    • return = omlpsolve("get_epsel", lp_handle)
    • No special considerations.
  • get_epsint
    • return = omlpsolve("get_epsint", lp_handle)
    • No special considerations.
  • get_epsperturb
    • return = omlpsolve("get_epsperturb", lp_handle)
    • No special considerations.
  • get_epspivot
    • return = omlpsolve("get_epspivot", lp_handle)
    • No special considerations.
  • get_improve
    • return = omlpsolve("get_improve", lp_handle)
    • No special considerations.
  • get_infinite
    • return = omlpsolve("get_infinite", lp_handle)
    • No special considerations.
  • get_lowbo
    • return = omlpsolve("get_lowbo", lp_handle, column)
    • [return] = omlpsolve("get_lowbo", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_lp_index
    • return = omlpsolve("get_lp_index", lp_handle, orig_index)
    • No special considerations.
  • get_lp_name
    • name = omlpsolve("get_lp_name", lp_handle)
    • No special considerations.
  • get_mat
    • value = omlpsolve("get_mat", lp_handle, row, col)
    • [matrix, return] = omlpsolve("get_mat", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix in the first return value. The return code of the call is the second return value.
  • get_max_level
    • return = omlpsolve("get_max_level", lp_handle)
    • No special considerations.
  • get_maxpivot
    • return = omlpsolve("get_maxpivot", lp_handle)
    • No special considerations.
  • get_mip_gap
    • return = omlpsolve("get_mip_gap", lp_handle, absolute)
    • No special considerations.
  • get_nameindex
    • return = omlpsolve("get_nameindex", lp_handle, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = omlpsolve("get_Ncolumns", lp_handle)
    • No special considerations.
  • get_negrange
    • return = omlpsolve("get_negrange", lp_handle)
    • No special considerations.
  • get_nonzeros
    • return = omlpsolve("get_nonzeros", lp_handle)
    • No special considerations.
  • get_Norig_columns
    • return = omlpsolve("get_Norig_columns", lp_handle)
    • No special considerations.
  • get_Norig_rows
    • return = omlpsolve("get_Norig_rows", lp_handle)
    • No special considerations.
  • get_Nrows
    • return = omlpsolve("get_Nrows", lp_handle)
    • No special considerations.
  • get_obj_bound
    • return = omlpsolve("get_obj_bound", lp_handle)
    • No special considerations.
  • get_objective
    • return = omlpsolve("get_objective", lp_handle)
    • No special considerations.
  • get_orig_index
    • return = omlpsolve("get_orig_index", lp_handle, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = omlpsolve("get_origcol_name", lp_handle, column)
    • [names] = omlpsolve("get_origcol_name", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_origrow_name
    • name = omlpsolve("get_origrow_name", lp_handle, row)
    • [names] = omlpsolve("get_origrow_name", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_pivoting
    • return = omlpsolve("get_pivoting", lp_handle)
    • No special considerations.
  • get_presolve
    • return = omlpsolve("get_presolve", lp_handle)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = omlpsolve("get_primal_solution", lp_handle)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = omlpsolve("get_print_sol", lp_handle)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = omlpsolve("get_rh", lp_handle, row)
    • [rh] = omlpsolve("get_rh", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix. Note that in this case, the value of row 0 is not returned.
  • get_rh_range
    • return = omlpsolve("get_rh_range", lp_handle, row)
    • [rh_ranges] = omlpsolve("get_rh_range", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_row
    • [row, return] = omlpsolve("get_row", lp_handle, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In O-Matrix, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = omlpsolve("get_row_name", lp_handle, row)
    • [names] = omlpsolve("get_row_name", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_scalelimit
    • return = omlpsolve("get_scalelimit", lp_handle)
    • No special considerations.
  • get_scaling
    • return = omlpsolve("get_scaling", lp_handle)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = omlpsolve("get_sensitivity_obj", lp_handle)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = omlpsolve("get_sensitivity_objex", lp_handle)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that O-Matrix allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = omlpsolve("get_sensitivity_obj", lp_handle). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, O-Matrix always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = omlpsolve("get_sensitivity_rhs", lp_handle)
    • [duals, dualsfrom, dualstill, return] = omlpsolve("get_sensitivity_rhsex", lp_handle)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that O-Matrix allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = omlpsolve("get_sensitivity_rhs", lp_handle). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = omlpsolve("get_simplextype", lp_handle)
    • No special considerations.
  • get_solutioncount
    • return = omlpsolve("get_solutioncount", lp_handle)
    • No special considerations.
  • get_solutionlimit
    • return = omlpsolve("get_solutionlimit", lp_handle)
    • No special considerations.
  • get_status
    • return = omlpsolve("get_status", lp_handle)
    • No special considerations.
  • get_statustext
    • return = omlpsolve("get_statustext", lp_handle, statuscode)
    • No special considerations.
  • get_timeout
    • return = omlpsolve("get_timeout", lp_handle)
    • No special considerations.
  • get_total_iter
    • return = omlpsolve("get_total_iter", lp_handle)
    • No special considerations.
  • get_total_nodes
    • return = omlpsolve("get_total_nodes", lp_handle)
    • No special considerations.
  • get_upbo
    • return = omlpsolve("get_upbo", lp_handle, column)
    • [upbo] = omlpsolve("get_upbo", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_var_branch
    • return = omlpsolve("get_var_branch", lp_handle, column)
    • [var_branch] = omlpsolve("get_var_branch", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_var_dualresult
    • return = omlpsolve("get_var_dualresult", lp_handle, index)
    • No special considerations.
  • get_var_primalresult
    • return = omlpsolve("get_var_primalresult", lp_handle, index)
    • No special considerations.
  • get_var_priority
    • return = omlpsolve("get_var_priority", lp_handle, column)
    • [var_priority] = omlpsolve("get_var_priority", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • get_variables
    • [var, return] = omlpsolve("get_variables", lp_handle)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = omlpsolve("get_verbose", lp_handle)
    • No special considerations.
  • get_working_objective
    • return = omlpsolve("get_working_objective", lp_handle)
    • No special considerations.
  • has_BFP
    • return = omlpsolve("has_BFP", lp_handle)
    • No special considerations.
  • has_XLI
    • return = omlpsolve("has_XLI", lp_handle)
    • No special considerations.
  • is_add_rowmode
    • return = omlpsolve("is_add_rowmode", lp_handle)
    • No special considerations.
  • is_anti_degen
    • return = omlpsolve("is_anti_degen", lp_handle, testmask)
    • No special considerations.
  • is_binary
    • return = omlpsolve("is_binary", lp_handle, column)
    • [binary] = omlpsolve("is_binary", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • is_break_at_first
    • return = omlpsolve("is_break_at_first", lp_handle)
    • No special considerations.
  • is_constr_type
    • return = omlpsolve("is_constr_type", lp_handle, row, mask)
    • No special considerations.
  • is_debug
    • return = omlpsolve("is_debug", lp_handle)
    • No special considerations.
  • is_feasible
    • return = omlpsolve("is_feasible", lp_handle, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free
    • return = omlpsolve("is_free", lp_handle, column)
    • [free] = omlpsolve("is_free", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • is_infinite
    • return = omlpsolve("is_infinite", lp_handle, value)
    • No special considerations.
  • is_int
    • return = omlpsolve("is_int", lp_handle, column)
    • [int] = omlpsolve("is_int", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • is_integerscaling
    • return = omlpsolve("is_integerscaling", lp_handle)
    • No special considerations.
  • is_maxim
    • return = omlpsolve("is_maxim", lp_handle)
    • No special considerations.
  • is_nativeBFP
    • return = omlpsolve("is_nativeBFP", lp_handle)
    • No special considerations.
  • is_nativeXLI
    • return = omlpsolve("is_nativeXLI", lp_handle)
    • No special considerations.
  • is_negative
    • return = omlpsolve("is_negative", lp_handle, column)
    • [negative] = omlpsolve("is_negative", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • is_piv_mode
    • return = omlpsolve("is_piv_mode", lp_handle, testmask)
    • No special considerations.
  • is_piv_rule
    • return = omlpsolve("is_piv_rule", lp_handle, rule)
    • No special considerations.
  • is_presolve
    • return = omlpsolve("is_presolve", lp_handle, testmask)
    • No special considerations.
  • is_scalemode
    • return = omlpsolve("is_scalemode", lp_handle, testmask)
    • No special considerations.
  • is_scaletype
    • return = omlpsolve("is_scaletype", lp_handle, scaletype)
    • No special considerations.
  • is_semicont
    • return = omlpsolve("is_semicont", lp_handle, column)
    • [semicont] = omlpsolve("is_semicont", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • is_SOS_var
    • return = omlpsolve("is_SOS_var", lp_handle, column)
    • [SOS_var] = omlpsolve("is_SOS_var", lp_handle)
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a O-Matrix matrix.
  • is_trace
    • return = omlpsolve("is_trace", lp_handle)
    • No special considerations.
  • lp_solve_version
    • versionstring = omlpsolve("lp_solve_version")
    • The omlpsolve API routine returns the version information in 4 provided argument variables while the O-Matrix version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = omlpsolve("make_lp", rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • omlpsolve("print_constraints", lp_handle {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under O-Matrix (Windows) this means that the output is not shown.
    • The same information can also be obtained via omlpsolve("get_constraints", lp_handle). This shows the result on screen.
  • print_debugdump
    • return = omlpsolve("print_debugdump", lp_handle, filename)
    • No special considerations.
  • print_duals
    • omlpsolve("print_duals", lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under O-Matrix (Windows) this means that the output is not shown.
    • The same information can be obtained via omlpsolve("get_dual_solution", lp_handle). This shows the result on screen.
  • print_lp
    • omlpsolve("print_lp", lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under O-Matrix (Windows) this means that the output is not shown.
  • print_objective
    • omlpsolve("print_objective", lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under O-Matrix (Windows) this means that the output is not shown.
    • The same information can be obtained via omlpsolve("get_objective", lp_handle). This shows the result on screen.
  • print_scales
    • omlpsolve("print_scales", lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under O-Matrix (Windows) this means that the output is not shown.
  • print_solution
    • omlpsolve("print_solution", lp_handle {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under O-Matrix (Windows) this means that the output is not shown.
    • The same information can also be obtained via omlpsolve("get_variables", lp_handle). This shows the result on screen.
  • print_str
    • omlpsolve("print_str", lp_handle, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under O-Matrix (Windows) this means that the output is not shown.
  • print_tableau
    • omlpsolve("print_tableau", lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under O-Matrix (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the omlpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows MATLAB) to the command window of O-Matrix. As such, all reported output can be seen in O-Matrix. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines. Note that at least O-Matrix version 5.8 is needed to see this information on the command window. Older versions will not print information on the command window.
  • put_msgfunc
    • Not implemented.
  • read_freemps, read_freeMPS
    • lp_handle = omlpsolve("read_freemps", filename {, verbose})
    • lp_handle = omlpsolve("read_freeMPS", filename {, verbose})
    • In the lpsolve API, read_freemps needs a FILE handle. In O-Matrix it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = omlpsolve("read_lp", filename {, verbose {, lp_name}})
    • lp_handle = omlpsolve("read_LP", filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In O-Matrix it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = omlpsolve("read_mps", filename {, verbose})
    • lp_handle = omlpsolve("read_MPS", filename {, verbose})
    • In the lpsolve API, read_mps needs a FILE handle. In O-Matrix it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not specified, then NORMAL is used.
  • read_XLI
    • lp_handle = omlpsolve("read_XLI", xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
    • Not implemented.
    • Use default_basis
  • set_add_rowmode
    • return = omlpsolve("set_add_rowmode", lp_handle, turnon)
    • No special considerations.
  • set_anti_degen
    • omlpsolve("set_anti_degen", lp_handle, anti_degen)
    • No special considerations.
  • set_basis
    • return = omlpsolve("set_basis", lp_handle, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In O-Matrix, there is no unused element in the matrix.
  • set_basiscrash
    • omlpsolve("set_basiscrash", lp_handle, mode)
    • No special considerations.
  • set_bb_depthlimit
    • omlpsolve("set_bb_depthlimit", lp_handle, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • omlpsolve("set_bb_floorfirst", lp_handle, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • omlpsolve("set_bb_rule", lp_handle, bb_rule)
    • No special considerations.
  • set_BFP
    • return = omlpsolve("set_BFP", lp_handle, filename)
    • No special considerations.
  • set_binary
    • return = omlpsolve("set_binary", lp_handle, column, must_be_bin)
    • return = omlpsolve("set_binary", lp_handle, [must_be_bin])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = omlpsolve("set_bounds", lp_handle, column, lower, upper)
    • return = omlpsolve("set_bounds", lp_handle, [lower], [upper])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • omlpsolve("set_bounds_tighter", lp_handle, tighten)
    • No special considerations.
  • set_break_at_first
    • omlpsolve("set_break_at_first", lp_handle, break_at_first)
    • No special considerations.
  • set_break_at_value
    • omlpsolve("set_break_at_value", lp_handle, break_at_value)
    • No special considerations.
  • set_col_name
    • return = omlpsolve("set_col_name", lp_handle, column, name)
    • return = omlpsolve("set_col_name", lp_handle, [names])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = omlpsolve("set_column", lp_handle, col_no, [column])
    • return = omlpsolve("set_columnex", lp_handle, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = omlpsolve("set_constr_type", lp_handle, row, con_type)
    • return = omlpsolve("set_constr_type", lp_handle, [con_type])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • omlpsolve("set_debug", lp_handle, debug)
    • No special considerations.
  • set_epsb
    • omlpsolve("set_epsb", lp_handle, epsb)
    • No special considerations.
  • set_epsd
    • omlpsolve("set_epsd", lp_handle, epsd)
    • No special considerations.
  • set_epsel
    • omlpsolve("set_epsel", lp_handle, epsel)
    • No special considerations.
  • set_epsint
    • omlpsolve("set_epsint", lp_handle, epsint)
    • No special considerations.
  • set_epsperturb
    • omlpsolve("set_epsperturb", lp_handle, epsperturb)
    • No special considerations.
  • set_epspivot
    • omlpsolve("set_epspivot", lp_handle, epspivot)
    • No special considerations.
  • set_free
    • return = omlpsolve("set_free", lp_handle, column)
    • No special considerations.
  • set_improve
    • omlpsolve("set_improve", lp_handle, improve)
    • No special considerations.
  • set_infinite
    • omlpsolve("set_infinite", lp_handle, infinite)
    • No special considerations.
  • set_int
    • return = omlpsolve("set_int", lp_handle, column, must_be_int)
    • return = omlpsolve("set_int", lp_handle, [must_be_int])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = omlpsolve("set_lowbo", lp_handle, column, value)
    • return = omlpsolve("set_lowbo", lp_handle, [values])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = omlpsolve("set_lp_name", lp_handle, name)
    • No special considerations.
  • set_mat
    • return = omlpsolve("set_mat", lp_handle, row, column, value)
    • return = omlpsolve("set_mat", lp_handle, [matrix])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. Consider using a O-Matrix sparse matrix for maximum performance and least memory usage. The matrix must be two-dimentional.
  • set_maxim
    • omlpsolve("set_maxim", lp_handle)
    • No special considerations.
  • set_maxpivot
    • omlpsolve("set_maxpivot", max_num_inv)
    • No special considerations.
  • set_minim
    • omlpsolve("set_minim", lp_handle)
    • No special considerations.
  • set_mip_gap
    • omlpsolve("set_mip_gap", lp_handle, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • omlpsolve("set_negrange", negrange)
    • No special considerations.
  • set_obj
    • return = omlpsolve("set_obj", lp_handle, column, value)
    • return = omlpsolve("set_obj", lp_handle, [values])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • omlpsolve("set_obj_bound", lp_handle, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = omlpsolve("set_obj_fn", lp_handle, [row])
    • return = omlpsolve("set_obj_fnex", lp_handle, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In O-Matrix, there is no unused element in the matrix.
  • set_outputfile
    • return = omlpsolve("set_outputfile", lp_handle, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In O-Matrix under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • omlpsolve("set_pivoting", lp_handle, pivoting)
    • No special considerations.
  • set_preferdual
    • omlpsolve("set_preferdual", lp_handle, dodual)
    • No special considerations.
  • set_presolve
    • omlpsolve("set_presolve", lp_handle, do_presolve)
    • No special considerations.
  • set_print_sol
    • omlpsolve("set_print_sol", lp_handle, print_sol)
    • No special considerations.
  • set_rh
    • return = omlpsolve("set_rh", lp_handle, row, value)
    • return = omlpsolve("set_rh", lp_handle, [values])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = omlpsolve("set_rh_range", lp_handle, row, deltavalue)
    • return = omlpsolve("set_rh_range", lp_handle, [deltavalues])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • omlpsolve("set_rh_vec", lp_handle, [rh])
    • In the API, element 0 is not used and values start from element 1. In O-Matrix, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = omlpsolve("set_row", lp_handle, row_no, [row])
    • return = omlpsolve("set_rowex", lp_handle, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In O-Matrix, there is no unused element in the matrix.
  • set_row_name
    • return = omlpsolve("set_row_name", lp_handle, row, name)
    • return = omlpsolve("set_row_name", lp_handle, [names])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • omlpsolve("set_scalelimit", lp_handle, scalelimit)
    • No special considerations.
  • set_scaling
    • omlpsolve("set_scaling", lp_handle, scalemode)
    • No special considerations.
  • set_semicont
    • return = omlpsolve("set_semicont", lp_handle, column, must_be_sc)
    • return = omlpsolve("set_semicont", lp_handle, [must_be_sc])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • omlpsolve("set_sense", lp_handle, maximize)
    • No special considerations.
  • set_simplextype
    • omlpsolve("set_simplextype", lp_handle, simplextype)
    • No special considerations.
  • set_solutionlimit
    • omlpsolve("set_solutionlimit", lp_handle, simplextype)
    • No special considerations.
  • set_timeout
    • omlpsolve("set_timeout", lp_handle, sectimeout)
    • No special considerations.
  • set_trace
    • omlpsolve("set_trace", lp_handle, trace)
    • No special considerations.
  • set_upbo
    • return = omlpsolve("set_upbo", lp_handle, column, value)
    • return = omlpsolve("set_upbo", lp_handle, [values])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_branch
    • return = omlpsolve("set_var_branch", lp_handle, column, branch_mode)
    • return = omlpsolve("set_var_branch", lp_handle, [branch_mode])
    • In O-Matrix, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = omlpsolve("set_var_weights", lp_handle, [weights])
    • No special considerations.
  • set_verbose
    • omlpsolve("set_verbose", lp_handle, verbose)
    • No special considerations.
  • set_XLI
    • return = omlpsolve("set_XLI", lp_handle, filename)
    • No special considerations.
  • solve
    • result = omlpsolve("solve", lp_handle)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = omlpsolve("time_elapsed", lp_handle)
    • No special considerations.
  • unscale
    • omlpsolve("unscale", lp_handle)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = omlpsolve("write_freemps", lp_handle, filename)
    • return = omlpsolve("write_freeMPS", lp_handle, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In O-Matrix it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = omlpsolve("write_lp", lp_handle, filename)
    • return = omlpsolve("write_LP", lp_handle, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In O-Matrix it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = omlpsolve("write_mps", lp_handle, filename)
    • return = omlpsolve("write_MPS", lp_handle, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In O-Matrix it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = omlpsolve("write_XLI", lp_handle, filename {, options {, results}})
    • No special considerations.

Extra O-Matrix routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = omlpsolve("get_col_names", lp_handle)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = omlpsolve("get_constr_types", lp_handle)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = omlpsolve("get_int", lp_handle)
    • The same as is_int. Implemented for backwards compatibility.
  • return = omlpsolve("get_no_cols", lp_handle)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = omlpsolve("get_no_rows", lp_handle)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = omlpsolve("get_objective_name", lp_handle)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = omlpsolve("get_obj_fn", lp_handle)
    [row_vec, return] = omlpsolve("get_obj_fun", lp_handle)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = omlpsolve("get_problem_name", lp_handle)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = omlpsolve("get_reduced_costs", lp_handle)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = omlpsolve("get_row_names", lp_handle)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = omlpsolve("get_solution", lp_handle)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = omlpsolve("mat_elm", lp_handle)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = omlpsolve("print_handle")
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = omlpsolve("read_lp_file", filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.

Compile the omlpsolve driver

Windows

Under Windows, the omlpsolve O-Matrix driver is a dll: omlpsolve.dll
This dll is an interface to the lpsolve51.dll lpsolve dll that contains the implementation of lp_solve. lpsolve51.dll is distributed with the lp_solve package. The omlpsolve O-Matrix driver dll (omlpsolve.dll) is just a wrapper between O-Matrix and lp_solve to translate the input/output to/from O-Matrix and the lp_solve library.

The omlpsolve O-Matrix driver is written in C. To compile this code, Microsoft compiler is needed. Other compilers might also work, but this is untested. To make the compilation process easier, a batch file can be used: cvc.bat
It may be necessary to edit this file first to change the path where lp_solve and the O-Matrix dll sources are installed. Change at the beginning lpsolvepath and dllsrcpath. dllsrcpath must point to the folder where dll.h is located.
To make for release, just enter cvc and everything is build.
This compiles two source files: lpsolve.c and hash.c
Then these are linked with the library lpsolve51.lib to generate the omlpsolve.dll file.
The optional arguments to cvc are used for development. Source files can be provided and then only these are compiled. For example hash.c should only be compiled once while developing. So specifying lpsolve.c as first argument will only compile this file and then link everything. This makes the build process a bit faster. Also the option -DDEMO can be added to add the demo command to test some functionality of lpsolve. This is also only for debugging. Also the option -DDEBUG can be added. This to print some debug information while executing omlpsolve. Should only be used for debugging purposes.

Note that the omlpsolve.dll file can be locked by O-Matrix. Then the build process will fail because the dll can not be overwritten. This can be solved by giving the clear command in O-Matrix. This will free the dll.

Unix/Linux

At this moment, there is no O-Matrix version for this platform.

See also Using lpsolve from MATLAB, Using lpsolve from Scilab


Using lpsolve from Scilab

Scilab?

Developed at INRIA, Scilab has been developed for system control and signal processing applications. It is freely distributed in source code format.

Scilab is made of three distinct parts: an interpreter, libraries of functions (Scilab procedures) and libraries of Fortran and C routines. These routines (which, strictly speaking, do not belong to Scilab but are interactively called by the interpreter) are of independent interest and most of them are available through Netlib. A few of them have been slightly modified for better compatibility with Scilab's interpreter. A key feature of the Scilab syntax is its ability to handle matrices: basic matrix manipulations such as concatenation, extraction or transpose are immediately performed as well as basic operations such as addition or multiplication. Scilab also aims at handling more complex objects than numerical matrices. For instance, control people may want to manipulate rational or polynomial transfer matrices. This is done in Scilab by manipulating lists and typed lists which allows a natural symbolic representation of complicated mathematical objects such as transfer functions, linear systems or graphs.

Polynomials, polynomials matrices and transfer matrices are also defined and the syntax used for manipulating these matrices is identical to that used for manipulating constant vectors and matrices.

Scilab provides a variety of powerful primitives for the analysis of non-linear systems. Integration of explicit and implicit dynamic systems can be accomplished numerically. The scicos toolbox allows the graphic definition and simulation of complex interconnected hybrid systems.

Scilab has an open programming environment where the creation of functions and libraries of functions is completely in the hands of the user. Functions are recognized as data objects in Scilab and, thus, can be manipulated or created as other data objects. For example, functions can be defined inside Scilab and passed as input or output arguments of other functions.

In addition Scilab supports a character string data type which, in particular, allows the on-line creation of functions. Matrices of character strings are also manipulated with the same syntax as ordinary matrices.

Finally, Scilab is easily interfaced with Fortran or C subprograms. This allows use of standardized packages and libraries in the interpreted environment of Scilab.

The general philosophy of Scilab is to provide the following sort of computing environment:

  • To have data types which are varied and flexible with a syntax which is natural and easy to use.
  • To provide a reasonable set of primitives which serve as a basis for a wide variety of calculations.
  • To have an open programming environment where new primitives are easily added. A useful tool distributed with Scilab is intersci which is a tool for building interface programs to add new primitives i.e. to add new modules of Fortran or C code into Scilab.
  • To support library development through ``toolboxes'' of functions devoted to specific applications (linear control, signal processing, network analysis, non-linear control, etc.)

We will not discuss the specifics of Scilab here but instead refer the reader to the Scilab website and documentation.

Scilab and lpsolve

lpsolve is callable from Scilab via an external interface. As such, it looks like lpsolve is fully integrated with Scilab. Matrices can directly be transferred between Scilab and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for Scilab (especially for matrix support). So you have full control to the complete lpsolve functionality via the sclpsolve Scilab driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level scripts that can make things a lot easier. See further in this article.

Quickstart

Compile and build sclpsolve:
----------------------------

1. Under Windows, the Microsoft Visual C/C++ compiler must be installed
   and the environment variables must be active do that when a command prompt
   is opened, the cl and nmake commands can be executed.
   Under Unix/Linux, the standard c compiler is used.

2. Edit the file Path.incl and change pathnames as needed.

3. Start scilab

4. Check under scilab that the current directory is the lpsolve directory.
   Use the scilab pwd command to show the current directory.
   With the chdir command, you can change the current directory.
   This current directory must be lp_solve_5.1/extra/scilab/lpsolve
   example: chdir('/lp_solve/lp_solve_5.1/extra/scilab/lpsolve')

5. To compile and build sclpsolve, enter the following command in scilab:
      -->exec builder.sce
   This should be done once to build the sclpsolve driver and to produce
   the file loader.sce.

Load the sclpsolve driver in the scilab memory space:
-----------------------------------------------------

1. Under Windows, make sure that the lpsolve51.dll file is somewhere in the path
   Under Unix/Linux, make sure that the liblpsolve51.so shared library is in /usr/lib
   or /lib so that Unix can find it.

2. A precompiled library is provided for Windows (sclpsolve.dll).
   For Unix/Linux, it is required that the sclpsolve driver is first build.
   That must be done only once. So if you haven't taken the steps yet
   to build the sclpsolve driver, then do this first as described at
   the beginning of this file.

3. Start scilab

4. Check under scilab that the current directory is the lpsolve directory.
   Use the scilab pwd command to show the current directory.
   With the chdir command, you can change the current directory.
   This current directory must be lp_solve_5.1/extra/scilab/lpsolve
   example: chdir('/lp_solve/lp_solve_5.1/extra/scilab/lpsolve')

5. Enter the following command in scilab:
      -->exec loader.sce

Installation

To make this possible, a driver program is needed: sclpsolve (sclpsolve.dll under Windows, sclpsolve.a under Unix/Linux). This driver must be put in a directory known to Scilab and Scilab can call the sclpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve51.dll under Windows and liblpsolve51.so under Unix/Linux). This has the advantage that the sclpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. For Windows, the lpsolve51.dll file must be somewhere in the path. For Unix, the lpsolve shared library (liblpsolve51.so) must be in the /usr/lib or /lib directory.

So note the difference between the Scilab lpsolve driver that is called sclpsolve and the lpsolve library that implements the API that is called lpsolve51.

There are also some Scilab script files (*.sce, *.sci) as a quick start.

The first thing that must be done, each time Scilab is restarted and you want to use lpsolve is load the sclpsolve driver into the Scilab workspace. This can be done via the script loader.sce. The following command must be used to load the driver:

exec loader.sce

It is assumed here that the current directory is the Scilab lpsolve directory (lp_solve_5.1/extra/scilab/lpsolve), but this is not a requirement. You can also provide the full path to the script files. The current directory can be shown via the pwd command in Scilab:

pwd

That is basically all you need to do. From now on, you can use the library. This until Scilab is restarted. Then this command must be given again to reload the library.

To make things easier, you can edit the file scilab.star with your favourite editor (or notepad/vi) in the Scilab directory and add above line at the end of this file. That will automatically load the lpsolve driver in memory when Scilab is started. So it will appear as if the sclpsolve command is then always available.

If you get an error simular to below, then probably the lpsolve library can not be found:

link failed for dll c:\lp_solve\lp_solve_5.1\extra\scilab\lpsolve\libs\sclpsolve.dll
addinter(liblpmex,'lpmex_gateway','sclpsolve')
                                               !--error   236
link: the shared archive was not loaded

Under Windows, the lpsolve51.dll file must be in one of the directories specified by the PATH environment variable. This path can be seen in Scilab via the command getenv("PATH"). It is common to place dlls in the WINDOWS\system32 folder.

Under Unix/Linux, the liblpsolve51.so file must be in the directory /usr/lib or /lib.

To test if everything is installed correctly, enter sclpsolve() in the Scilab command window. If it gives the following, then everything is ok:

sclpsolve  scilab Interface version 5.1.0.0
using lpsolve version 5.1.1.2

Usage: [ret1, ret2, ...] = sclpsolve('functionname', arg1, arg2, ...)

All this is developed and tested with Scilab versions 2.7 and 3.0 both under Windows and Linux (RedHat).

Solve an lp model from Scilab via sclpsolve

In the following text, --> before the Scilab commands is the Scilab prompt. Only the text after --> must be entered.

To call an lpsolve function, the following syntax must be used:

-->[ret1, ret2, ...] = sclpsolve('functionname', arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between (single or double) quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra Scilab specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in Scilab, this structure is replaced by a handle. This is an incrementing number starting from 0 and the lprec structures are maintained internally by the sclpsolve driver. However you will see not much (if any) difference in the use of it.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the Scilab functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from Scilab, nothing must be dimensioned in advance. The sclpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to sclpsolve. Never as argument to the routine. This can be a single value as for get_objective (although Scilab stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Note that you can get an overview of the available functionnames and their arguments by entering the following in Scilab:

-->help sclpsolve

An example

(Note that you can execute this example by entering command per command as shown below or by just entering exec example1.sce. This will execute example1.sce.)

-->lp=sclpsolve('make_lp', 0, 4);
-->sclpsolve('set_verbose', lp, 3);
-->sclpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
-->sclpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
-->sclpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
-->sclpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
-->sclpsolve('set_lowbo', lp, 1, 28.6);
-->sclpsolve('set_lowbo', lp, 4, 18);
-->sclpsolve('set_upbo', lp, 4, 48.98);
-->sclpsolve('set_col_name', lp, 1, 'COLONE');
-->sclpsolve('set_col_name', lp, 2, 'COLTWO');
-->sclpsolve('set_col_name', lp, 3, 'COLTHREE');
-->sclpsolve('set_col_name', lp, 4, 'COLFOUR');
-->sclpsolve('set_row_name', lp, 1, 'THISROW');
-->sclpsolve('set_row_name', lp, 2, 'THATROW');
-->sclpsolve('set_row_name', lp, 3, 'LASTROW');
-->sclpsolve('write_lp', lp, 'a.lp');
-->sclpsolve('get_mat', lp, 1, 2)
 ans  =

    78.26

-->sclpsolve('solve', lp)
 ans  =

     0.

-->sclpsolve('get_objective', lp)
 ans  =

   31.782759

-->sclpsolve('get_variables', lp)
 ans  =

!   28.6      !
!   0.        !
!   0.        !
!   31.827586 !

-->sclpsolve('get_constraints', lp)
 ans  =

!   92.3      !
!   6.864     !
!   391.29283 !

-->sclpsolve('delete_lp', lp);

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. For example:

-->obj=sclpsolve('get_objective', lp)
 obj  =

    31.782759

Or without echoing on screen:

-->obj=sclpsolve('get_objective', lp);

The last command will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

-->x=sclpsolve('get_variables', lp);

-->b=sclpsolve('get_constraints', lp);

It is always possible to show the contents of a variable by just giving it as command:

-->x

 x  =
!   28.6      !
!   0.        !
!   0.        !
!   31.827586 !

Matrices

In Scilab, all numerical data is stored in matrices; even a scalar variable. Scilab also supports complex numbers (a + b * %i with %i=SQRT(-1)). sclpsolve can only work with real numbers. Scilab also supports sparse matrices. Sparse matrices are matrices where only the non-zero elements are provided and stored. This results in both less storage and faster calculation if there are a sufficient number of zero values in the matrix and there usually are. The sclpsolve driver supports both dense and sparse matrices and their use is totally transparent to the user. Everywhere a matrix can be provided, it can be dense or sparse. However, Scilab requires for interface programs that sparse matrixes are converted to MATLAB sparse matrices via the function mtlb_sparse(mat). In the above example all matrices were dense. For example:
-->sclpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);

In sparse matrix notation, this can be written:

-->sclpsolve('add_constraint', lp, mtlb_sparse(sparse([0.24, 0, 11.31, 0])), 1, 14.8);

Most of the time, variables are used to provide the data:

-->sclpsolve('add_constraint', lp, a1, 1, 14.8);

Where a1 is a dense matrix variable. A sparse matrix is then provided as follows:

-->sclpsolve('add_constraint', lp, mtlb_sparse(a1), 1, 14.8);

The sclpsolve driver sees all provided matrices as sparse matrices. sclpsolve also uses sparse matrices internally and data can be provided sparse via the ex routines. For example add_constraintex. The sclpsolve driver always uses the ex routines to provide the data to lpsolve. Even if you call from Scilab the routine names that would require a dense matrix (for example add_constraint), the sclpsolve driver will always call the sparse version of the routine (for example add_constraintex). This results in the most performing behaviour. Note that if a dense matrix is provided, the dimension must exactly match the dimension that is expected by sclpsolve. Matrices with too few or too much elements gives an 'invalid vector.' error. Sparse matrices can off course provide less elements (the non provided elements are seen as zero). However if too many elements are provided or an element with a too large index, again an 'invalid vector.' error is raised.

Most of the time, sclpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

-->sclpsolve('add_constraint', lp, [0.24; 0; 11.31; 0], 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the Scilab interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the Scilab matrix.

Sets

All numerical data is stored in matrices. Alphanumerical data, however, is more difficult to store in matrices. Matrices require that each element has the same size (length) and that is difficult and unpractical for alphanumerical data. In a limited number of lpsolve routines, alphanumerical data is required or returned and in some also multiple elements. An example is set_col_name. For this, Scilab sets are used. To specify a set of alphanumerical elements, the following notation is used: { 'element1', 'element2', ... }. Note the { and } symbols instead of [ and ] that are used with matrices.

It is noted however that this doesn't seem to work very well in Scilab. Scilab allows to return string sets, but when a string set is provided to an interface program, the following error occurs:

                                                                           !--error  9999
Invalid string matrix (at most one column!)
                                                                           !--error   999
SIGSTP: aborting current computation

This is not an error generated by the sclpsolve driver, but from the Scilab parser. Hopefully, this problem will be corrected in the future.

Maximum usage of matrices/sets with sclpsolve

Because Scilab is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the sclpsolve Scilab driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The sclpsolve Scilab driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = sclpsolve('set_int', lp_handle, column, must_be_int). The matrix version of this call is: return = sclpsolve('set_int', lp_handle, [must_be_int]). The API call to return the integer status of a variable is: return = sclpsolve('is_int', lp_handle, column). The matrix version of this call is: [is_int] = sclpsolve('is_int', lp_handle)
Also note the get_mat and set_mat routines. In Scilab these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just entering exec example2.sce. This will execute example2.sce.)

-->lp=sclpsolve('make_lp', 0, 4);
-->sclpsolve('set_verbose', lp, 3);
-->sclpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
-->sclpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
-->sclpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
-->sclpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
-->sclpsolve('set_lowbo', lp, [28.6, 0, 0, 18]);
-->sclpsolve('set_upbo', lp, [%inf, %inf, %inf, 48.98]);
-->// sclpsolve('set_col_name', lp, {'COLONE', 'COLTWO', 'COLTHREE', 'COLFOUR'}); // gives a Scilab error with most releases :-(
-->// sclpsolve('set_row_name', lp, {'THISROW', 'THATROW', 'LASTROW'}); // gives a Scilab error with most releases :-(
-->sclpsolve('write_lp', lp, 'a.lp');
-->sclpsolve('get_mat', lp)
 ans  =

!   0.       78.26    0.       2.9 !
!    .24     0.       11.31    0.  !
!   12.68    0.        .08      .9 !

-->sclpsolve('solve', lp)
 ans  =

    0.

-->sclpsolve('get_objective', lp)
 ans  =

    31.782759

-->sclpsolve('get_variables', lp)
 ans  =

!   28.6      !
!   0.        !
!   0.        !
!   31.827586 !

-->sclpsolve('get_constraints', lp)
 ans  =

!   92.3      !
!   6.864     !
!   391.29283 !

Note the usage of %inf in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -%inf to express minus infinity. This can for example be used to create a free variable.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

-->A=sclpsolve('get_mat', lp);

-->X=sclpsolve('get_variables', lp);

-->B = A * X
 B  =

!   92.3      !
!   6.864     !
!   391.29283 !

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

-->sclpsolve('get_constraints', lp)
 ans  =

!   92.3      !
!   6.864     !
!   391.29283 !

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

-->C=sclpsolve('get_obj_fn', lp);

-->X=sclpsolve('get_variables', lp);

 obj  =

    31.782759

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

-->sclpsolve('get_objective', lp)

 ans  =

   31.7828

Again exactly the same as the calculated obj value, as expected.

Script files

Scilab can execute a sequence of statements stored in diskfiles. Scilab has two kinds of these. The first kinds are ASCII files where Scilab commands are written in the same way as in the command window. These files normally have the extension .sce. These script files must be executed via the exec command. For example:

exec example1.sce

The second kinds are binary files. However the user enters the commands first in an ASCII file (normally with extention .sci) and then these are translated to binary files via the Scilab genlib command. The .sci files also may only contain Scilab commands. There are two advantages of using these. The first is that you don't have to use the exec command or provide the extension to execute them. So it is as if you execute a regular Scilab command. The second advantage is that they are somewhat faster.

The lpsolve distribution contains some sample .sce files that must be executed via exec and also some .sci high-level routines that can be executed without exec. They are already precompiled.

example1.sce

Contains the commands as shown in the first example of this article. Execute via exec example1.sce

example2.sce

Contains the commands as shown in the second example of this article. Execute via exec example2.sce

lp_solve.sci

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file or type help lp_solve to see its usage:

 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

-->[obj, x]=lp_solve([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
 x  =

!   1. !
!   2. !
 obj  =

    3.

Note that you can also provide sparse matrices to this function without having to use mtlb_sparse. The script is taking care of this.

lp_maker.sci

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. See the beginning of the file or type help lp_maker or just lp_maker to see its usage:

-->help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            x >= vlb >= 0
            x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n sparse matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

-->lp=lp_maker([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
 lp  =

    0.

To solve the model and get the solution:

-->sclpsolve('solve', lp)
 ans  =

    0.

-->sclpsolve('get_objective', lp)
 ans  =

    3.

-->sclpsolve('get_variables', lp)
 ans  =

!   1. !
!   2. !

Don't forget to free the handle and its associated memory when you are done:

-->sclpsolve('delete_lp', lp);

Note that you can also provide sparse matrices to this function without having to use mtlb_sparse. The script is taking care of this.

lpdemo.sce

Contains several examples to build and solve lp models. Execute via exec lpdemo.sce

ex.sce

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution. Execute via exec ex.sce

Overview of API routines

  • add_column, add_columnex
    • return = sclpsolve('add_column', lp_handle, [column])
    • return = sclpsolve('add_columnex', lp_handle, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = sclpsolve('add_constraint', lp_handle, [row], constr_type, rh)
    • return = sclpsolve('add_constraintex', lp_handle, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = sclpsolve('add_SOS', lp_handle, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in Scilab since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = sclpsolve('column_in_lp', lp_handle, [column])
    • No special considerations.
  • default_basis
    • sclpsolve('default_basis', lp_handle)
    • No special considerations.
  • del_column
    • return = sclpsolve('del_column', lp_handle, column)
    • No special considerations.
  • del_constraint
    • return = sclpsolve('del_constraint', lp_handle, del_row)
    • No special considerations.
  • delete_lp
    • sclpsolve('delete_lp', lp_handle)
    • No special considerations.
  • free_lp
    • sclpsolve('free_lp', lp_handle)
    • lp_handle is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = sclpsolve('get_anti_degen', lp_handle)
    • No special considerations.
  • get_basis
    • [bascolumn] = sclpsolve('get_basis', lp_handle {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in Scilab. If not provided, then 0 is used.
  • get_basiscrash
    • return = sclpsolve('get_basiscrash', lp_handle)
    • No special considerations.
  • get_bb_depthlimit
    • return = sclpsolve('get_bb_depthlimit', lp_handle)
    • No special considerations.
  • get_bb_floorfirst
    • return = sclpsolve('get_bb_floorfirst', lp_handle)
    • No special considerations.
  • get_bb_rule
    • return = sclpsolve('get_bb_rule', lp_handle)
    • No special considerations.
  • get_bounds_tighter
    • return = sclpsolve('get_bounds_tighter', lp_handle)
    • No special considerations.
  • get_break_at_value
    • return = sclpsolve('get_break_at_value', lp_handle)
    • No special considerations.
  • get_col_name
    • name = sclpsolve('get_col_name', lp_handle, column)
    • [names] = sclpsolve('get_col_name', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_column
    • [column, return] = sclpsolve('get_column', lp_handle, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = sclpsolve('get_constr_type', lp_handle, row)
    • [constr_type] = sclpsolve('get_constr_type', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_constraints
    • [constr, return] = sclpsolve('get_constraints', lp_handle)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = sclpsolve('get_dual_solution', lp_handle)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = sclpsolve('get_epsb', lp_handle)
    • No special considerations.
  • get_epsd
    • return = sclpsolve('get_epsd', lp_handle)
    • No special considerations.
  • get_epsel
    • return = sclpsolve('get_epsel', lp_handle)
    • No special considerations.
  • get_epsint
    • return = sclpsolve('get_epsint', lp_handle)
    • No special considerations.
  • get_epsperturb
    • return = sclpsolve('get_epsperturb', lp_handle)
    • No special considerations.
  • get_epspivot
    • return = sclpsolve('get_epspivot', lp_handle)
    • No special considerations.
  • get_improve
    • return = sclpsolve('get_improve', lp_handle)
    • No special considerations.
  • get_infinite
    • return = sclpsolve('get_infinite', lp_handle)
    • No special considerations.
  • get_lowbo
    • return = sclpsolve('get_lowbo', lp_handle, column)
    • [return] = sclpsolve('get_lowbo', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_lp_index
    • return = sclpsolve('get_lp_index', lp_handle, orig_index)
    • No special considerations.
  • get_lp_name
    • name = sclpsolve('get_lp_name', lp_handle)
    • No special considerations.
  • get_mat
    • value = sclpsolve('get_mat', lp_handle, row, col)
    • [matrix, return] = sclpsolve('get_mat', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix in the first return value. The return code of the call is the second return value.
  • get_max_level
    • return = sclpsolve('get_max_level', lp_handle)
    • No special considerations.
  • get_maxpivot
    • return = sclpsolve('get_maxpivot', lp_handle)
    • No special considerations.
  • get_mip_gap
    • return = sclpsolve('get_mip_gap', lp_handle, absolute)
    • No special considerations.
  • get_nameindex
    • return = sclpsolve('get_nameindex', lp_handle, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = sclpsolve('get_Ncolumns', lp_handle)
    • No special considerations.
  • get_negrange
    • return = sclpsolve('get_negrange', lp_handle)
    • No special considerations.
  • get_nonzeros
    • return = sclpsolve('get_nonzeros', lp_handle)
    • No special considerations.
  • get_Norig_columns
    • return = sclpsolve('get_Norig_columns', lp_handle)
    • No special considerations.
  • get_Norig_rows
    • return = sclpsolve('get_Norig_rows', lp_handle)
    • No special considerations.
  • get_Nrows
    • return = sclpsolve('get_Nrows', lp_handle)
    • No special considerations.
  • get_obj_bound
    • return = sclpsolve('get_obj_bound', lp_handle)
    • No special considerations.
  • get_objective
    • return = sclpsolve('get_objective', lp_handle)
    • No special considerations.
  • get_orig_index
    • return = sclpsolve('get_orig_index', lp_handle, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = sclpsolve('get_origcol_name', lp_handle, column)
    • [names] = sclpsolve('get_origcol_name', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_origrow_name
    • name = sclpsolve('get_origrow_name', lp_handle, row)
    • [names] = sclpsolve('get_origrow_name', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_pivoting
    • return = sclpsolve('get_pivoting', lp_handle)
    • No special considerations.
  • get_presolve
    • return = sclpsolve('get_presolve', lp_handle)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = sclpsolve('get_primal_solution', lp_handle)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = sclpsolve('get_print_sol', lp_handle)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = sclpsolve('get_rh', lp_handle, row)
    • [rh] = sclpsolve('get_rh', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix. Note that in this case, the value of row 0 is not returned.
  • get_rh_range
    • return = sclpsolve('get_rh_range', lp_handle, row)
    • [rh_ranges] = sclpsolve('get_rh_range', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_row
    • [row, return] = sclpsolve('get_row', lp_handle, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = sclpsolve('get_row_name', lp_handle, row)
    • [names] = sclpsolve('get_row_name', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_scalelimit
    • return = sclpsolve('get_scalelimit', lp_handle)
    • No special considerations.
  • get_scaling
    • return = sclpsolve('get_scaling', lp_handle)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = sclpsolve('get_sensitivity_obj', lp_handle)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = sclpsolve('get_sensitivity_objex', lp_handle)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that Scilab allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = sclpsolve('get_sensitivity_obj', lp_handle). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, Scilab always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = sclpsolve('get_sensitivity_rhs', lp_handle)
    • [duals, dualsfrom, dualstill, return] = sclpsolve('get_sensitivity_rhsex', lp_handle)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that Scilab allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = sclpsolve('get_sensitivity_rhs', lp_handle). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = sclpsolve('get_simplextype', lp_handle)
    • No special considerations.
  • get_solutioncount
    • return = sclpsolve('get_solutioncount', lp_handle)
    • No special considerations.
  • get_solutionlimit
    • return = sclpsolve('get_solutionlimit', lp_handle)
    • No special considerations.
  • get_status
    • return = sclpsolve('get_status', lp_handle)
    • No special considerations.
  • get_statustext
    • return = sclpsolve('get_statustext', lp_handle, statuscode)
    • No special considerations.
  • get_timeout
    • return = sclpsolve('get_timeout', lp_handle)
    • No special considerations.
  • get_total_iter
    • return = sclpsolve('get_total_iter', lp_handle)
    • No special considerations.
  • get_total_nodes
    • return = sclpsolve('get_total_nodes', lp_handle)
    • No special considerations.
  • get_upbo
    • return = sclpsolve('get_upbo', lp_handle, column)
    • [upbo] = sclpsolve('get_upbo', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_var_branch
    • return = sclpsolve('get_var_branch', lp_handle, column)
    • [var_branch] = sclpsolve('get_var_branch', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_var_dualresult
    • return = sclpsolve('get_var_dualresult', lp_handle, index)
    • No special considerations.
  • get_var_primalresult
    • return = sclpsolve('get_var_primalresult', lp_handle, index)
    • No special considerations.
  • get_var_priority
    • return = sclpsolve('get_var_priority', lp_handle, column)
    • [var_priority] = sclpsolve('get_var_priority', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_variables
    • [var, return] = sclpsolve('get_variables', lp_handle)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = sclpsolve('get_verbose', lp_handle)
    • No special considerations.
  • get_working_objective
    • return = sclpsolve('get_working_objective', lp_handle)
    • No special considerations.
  • has_BFP
    • return = sclpsolve('has_BFP', lp_handle)
    • No special considerations.
  • has_XLI
    • return = sclpsolve('has_XLI', lp_handle)
    • No special considerations.
  • is_add_rowmode
    • return = sclpsolve('is_add_rowmode', lp_handle)
    • No special considerations.
  • is_anti_degen
    • return = sclpsolve('is_anti_degen', lp_handle, testmask)
    • No special considerations.
  • is_binary
    • return = sclpsolve('is_binary', lp_handle, column)
    • [binary] = sclpsolve('is_binary', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_break_at_first
    • return = sclpsolve('is_break_at_first', lp_handle)
    • No special considerations.
  • is_constr_type
    • return = sclpsolve('is_constr_type', lp_handle, row, mask)
    • No special considerations.
  • is_debug
    • return = sclpsolve('is_debug', lp_handle)
    • No special considerations.
  • is_feasible
    • return = sclpsolve('is_feasible', lp_handle, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free
    • return = sclpsolve('is_free', lp_handle, column)
    • [free] = sclpsolve('is_free', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_infinite
    • return = sclpsolve('is_infinite', lp_handle, value)
    • No special considerations.
  • is_int
    • return = sclpsolve('is_int', lp_handle, column)
    • [int] = sclpsolve('is_int', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_integerscaling
    • return = sclpsolve('is_integerscaling', lp_handle)
    • No special considerations.
  • is_maxim
    • return = sclpsolve('is_maxim', lp_handle)
    • No special considerations.
  • is_nativeBFP
    • return = sclpsolve('is_nativeBFP', lp_handle)
    • No special considerations.
  • is_nativeXLI
    • return = sclpsolve('is_nativeXLI', lp_handle)
    • No special considerations.
  • is_negative
    • return = sclpsolve('is_negative', lp_handle, column)
    • [negative] = sclpsolve('is_negative', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_piv_mode
    • return = sclpsolve('is_piv_mode', lp_handle, testmask)
    • No special considerations.
  • is_piv_rule
    • return = sclpsolve('is_piv_rule', lp_handle, rule)
    • No special considerations.
  • is_presolve
    • return = sclpsolve('is_presolve', lp_handle, testmask)
    • No special considerations.
  • is_scalemode
    • return = sclpsolve('is_scalemode', lp_handle, testmask)
    • No special considerations.
  • is_scaletype
    • return = sclpsolve('is_scaletype', lp_handle, scaletype)
    • No special considerations.
  • is_semicont
    • return = sclpsolve('is_semicont', lp_handle, column)
    • [semicont] = sclpsolve('is_semicont', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_SOS_var
    • return = sclpsolve('is_SOS_var', lp_handle, column)
    • [SOS_var] = sclpsolve('is_SOS_var', lp_handle)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_trace
    • return = sclpsolve('is_trace', lp_handle)
    • No special considerations.
  • lp_solve_version
    • versionstring = sclpsolve('lp_solve_version')
    • The sclpsolve API routine returns the version information in 4 provided argument variables while the Scilab version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = sclpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • sclpsolve('print_constraints', lp_handle {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
    • The same information can also be obtained via sclpsolve('get_constraints', lp_handle). This shows the result on screen.
  • print_debugdump
    • return = sclpsolve('print_debugdump', lp_handle, filename)
    • No special considerations.
  • print_duals
    • sclpsolve('print_duals', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
    • The same information can be obtained via sclpsolve('get_dual_solution', lp_handle). This shows the result on screen.
  • print_lp
    • sclpsolve('print_lp', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
  • print_objective
    • sclpsolve('print_objective', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
    • The same information can be obtained via sclpsolve('get_objective', lp_handle). This shows the result on screen.
  • print_scales
    • sclpsolve('print_scales', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
  • print_solution
    • sclpsolve('print_solution', lp_handle {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
    • The same information can also be obtained via sclpsolve('get_variables', lp_handle). This shows the result on screen.
  • print_str
    • sclpsolve('print_str', lp_handle, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
  • print_tableau
    • sclpsolve('print_tableau', lp_handle)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the sclpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows MATLAB) to the command window of Scilab. As such, all reported output can be seen in Scilab. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_freemps, read_freeMPS
    • lp_handle = sclpsolve('read_freemps', filename {, verbose})
    • lp_handle = sclpsolve('read_freeMPS', filename {, verbose})
    • In the lpsolve API, read_freemps needs a FILE handle. In Scilab it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = sclpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = sclpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In Scilab it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = sclpsolve('read_mps', filename {, verbose})
    • lp_handle = sclpsolve('read_MPS', filename {, verbose})
    • In the lpsolve API, read_mps needs a FILE handle. In Scilab it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not specified, then NORMAL is used.
  • read_XLI
    • lp_handle = sclpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
    • Not implemented.
    • Use default_basis
  • set_add_rowmode
    • return = sclpsolve('set_add_rowmode', lp_handle, turnon)
    • No special considerations.
  • set_anti_degen
    • sclpsolve('set_anti_degen', lp_handle, anti_degen)
    • No special considerations.
  • set_basis
    • return = sclpsolve('set_basis', lp_handle, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • set_basiscrash
    • sclpsolve('set_basiscrash', lp_handle, mode)
    • No special considerations.
  • set_bb_depthlimit
    • sclpsolve('set_bb_depthlimit', lp_handle, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • sclpsolve('set_bb_floorfirst', lp_handle, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • sclpsolve('set_bb_rule', lp_handle, bb_rule)
    • No special considerations.
  • set_BFP
    • return = sclpsolve('set_BFP', lp_handle, filename)
    • No special considerations.
  • set_binary
    • return = sclpsolve('set_binary', lp_handle, column, must_be_bin)
    • return = sclpsolve('set_binary', lp_handle, [must_be_bin])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = sclpsolve('set_bounds', lp_handle, column, lower, upper)
    • return = sclpsolve('set_bounds', lp_handle, [lower], [upper])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • sclpsolve('set_bounds_tighter', lp_handle, tighten)
    • No special considerations.
  • set_break_at_first
    • sclpsolve('set_break_at_first', lp_handle, break_at_first)
    • No special considerations.
  • set_break_at_value
    • sclpsolve('set_break_at_value', lp_handle, break_at_value)
    • No special considerations.
  • set_col_name
    • return = sclpsolve('set_col_name', lp_handle, column, name)
    • return = sclpsolve('set_col_name', lp_handle, [names])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = sclpsolve('set_column', lp_handle, col_no, [column])
    • return = sclpsolve('set_columnex', lp_handle, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = sclpsolve('set_constr_type', lp_handle, row, con_type)
    • return = sclpsolve('set_constr_type', lp_handle, [con_type])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • sclpsolve('set_debug', lp_handle, debug)
    • No special considerations.
  • set_epsb
    • sclpsolve('set_epsb', lp_handle, epsb)
    • No special considerations.
  • set_epsd
    • sclpsolve('set_epsd', lp_handle, epsd)
    • No special considerations.
  • set_epsel
    • sclpsolve('set_epsel', lp_handle, epsel)
    • No special considerations.
  • set_epsint
    • sclpsolve('set_epsint', lp_handle, epsint)
    • No special considerations.
  • set_epsperturb
    • sclpsolve('set_epsperturb', lp_handle, epsperturb)
    • No special considerations.
  • set_epspivot
    • sclpsolve('set_epspivot', lp_handle, epspivot)
    • No special considerations.
  • set_free
    • return = sclpsolve('set_free', lp_handle, column)
    • No special considerations.
  • set_improve
    • sclpsolve('set_improve', lp_handle, improve)
    • No special considerations.
  • set_infinite
    • sclpsolve('set_infinite', lp_handle, infinite)
    • No special considerations.
  • set_int
    • return = sclpsolve('set_int', lp_handle, column, must_be_int)
    • return = sclpsolve('set_int', lp_handle, [must_be_int])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = sclpsolve('set_lowbo', lp_handle, column, value)
    • return = sclpsolve('set_lowbo', lp_handle, [values])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = sclpsolve('set_lp_name', lp_handle, name)
    • No special considerations.
  • set_mat
    • return = sclpsolve('set_mat', lp_handle, row, column, value)
    • return = sclpsolve('set_mat', lp_handle, [matrix])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. Consider using a Scilab sparse matrix for maximum performance and least memory usage. The matrix must be two-dimentional.
  • set_maxim
    • sclpsolve('set_maxim', lp_handle)
    • No special considerations.
  • set_maxpivot
    • sclpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • sclpsolve('set_minim', lp_handle)
    • No special considerations.
  • set_mip_gap
    • sclpsolve('set_mip_gap', lp_handle, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • sclpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = sclpsolve('set_obj', lp_handle, column, value)
    • return = sclpsolve('set_obj', lp_handle, [values])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • sclpsolve('set_obj_bound', lp_handle, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = sclpsolve('set_obj_fn', lp_handle, [row])
    • return = sclpsolve('set_obj_fnex', lp_handle, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • set_outputfile
    • return = sclpsolve('set_outputfile', lp_handle, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In Scilab under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • sclpsolve('set_pivoting', lp_handle, pivoting)
    • No special considerations.
  • set_preferdual
    • sclpsolve('set_preferdual', lp_handle, dodual)
    • No special considerations.
  • set_presolve
    • sclpsolve('set_presolve', lp_handle, do_presolve)
    • No special considerations.
  • set_print_sol
    • sclpsolve('set_print_sol', lp_handle, print_sol)
    • No special considerations.
  • set_rh
    • return = sclpsolve('set_rh', lp_handle, row, value)
    • return = sclpsolve('set_rh', lp_handle, [values])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = sclpsolve('set_rh_range', lp_handle, row, deltavalue)
    • return = sclpsolve('set_rh_range', lp_handle, [deltavalues])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • sclpsolve('set_rh_vec', lp_handle, [rh])
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = sclpsolve('set_row', lp_handle, row_no, [row])
    • return = sclpsolve('set_rowex', lp_handle, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • set_row_name
    • return = sclpsolve('set_row_name', lp_handle, row, name)
    • return = sclpsolve('set_row_name', lp_handle, [names])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • sclpsolve('set_scalelimit', lp_handle, scalelimit)
    • No special considerations.
  • set_scaling
    • sclpsolve('set_scaling', lp_handle, scalemode)
    • No special considerations.
  • set_semicont
    • return = sclpsolve('set_semicont', lp_handle, column, must_be_sc)
    • return = sclpsolve('set_semicont', lp_handle, [must_be_sc])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • sclpsolve('set_sense', lp_handle, maximize)
    • No special considerations.
  • set_simplextype
    • sclpsolve('set_simplextype', lp_handle, simplextype)
    • No special considerations.
  • set_solutionlimit
    • sclpsolve('set_solutionlimit', lp_handle, simplextype)
    • No special considerations.
  • set_timeout
    • sclpsolve('set_timeout', lp_handle, sectimeout)
    • No special considerations.
  • set_trace
    • sclpsolve('set_trace', lp_handle, trace)
    • No special considerations.
  • set_upbo
    • return = sclpsolve('set_upbo', lp_handle, column, value)
    • return = sclpsolve('set_upbo', lp_handle, [values])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_branch
    • return = sclpsolve('set_var_branch', lp_handle, column, branch_mode)
    • return = sclpsolve('set_var_branch', lp_handle, [branch_mode])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = sclpsolve('set_var_weights', lp_handle, [weights])
    • No special considerations.
  • set_verbose
    • sclpsolve('set_verbose', lp_handle, verbose)
    • No special considerations.
  • set_XLI
    • return = sclpsolve('set_XLI', lp_handle, filename)
    • No special considerations.
  • solve
    • result = sclpsolve('solve', lp_handle)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = sclpsolve('time_elapsed', lp_handle)
    • No special considerations.
  • unscale
    • sclpsolve('unscale', lp_handle)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = sclpsolve('write_freemps', lp_handle, filename)
    • return = sclpsolve('write_freeMPS', lp_handle, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In Scilab it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = sclpsolve('write_lp', lp_handle, filename)
    • return = sclpsolve('write_LP', lp_handle, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In Scilab it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = sclpsolve('write_mps', lp_handle, filename)
    • return = sclpsolve('write_MPS', lp_handle, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In Scilab it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = sclpsolve('write_XLI', lp_handle, filename {, options {, results}})
    • No special considerations.

Extra Scilab routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = sclpsolve('get_col_names', lp_handle)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = sclpsolve('get_constr_types', lp_handle)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = sclpsolve('get_int', lp_handle)
    • The same as is_int. Implemented for backwards compatibility.
  • return = sclpsolve('get_no_cols', lp_handle)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = sclpsolve('get_no_rows', lp_handle)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = sclpsolve('get_objective_name', lp_handle)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = sclpsolve('get_obj_fn', lp_handle)
    [row_vec, return] = sclpsolve('get_obj_fun', lp_handle)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = sclpsolve('get_problem_name', lp_handle)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = sclpsolve('get_reduced_costs', lp_handle)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = sclpsolve('get_row_names', lp_handle)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = sclpsolve('get_solution', lp_handle)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = sclpsolve('mat_elm', lp_handle)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = sclpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = sclpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.

Compile the sclpsolve driver

Windows, Unix/Linux

Under Windows, the sclpsolve Scilab driver is a dll: sclpsolve.dll
Under Unix/Linux, the sclpsolve Scilab driver is a static library sclpsolve.a
The library is an interface to the lpsolve51 library that contains the implementation of lp_solve. Under windows this is a dll lpsolve51.dll and under Unix/Linux it is a shared library liblpsolve51.so
They are distributed with the lp_solve package. See at the beginning of this article where these files must be installed. The sclpsolve Scilab driver is just a wrapper between Scilab and lp_solve to translate the input/output to/from Scilab and the lp_solve library.

The sclpsolve Scilab driver is written in C. To compile this code, under Windows the Microsoft C compiler is needed and under Unix the standard compiler is used.
This compiler must be called from Scilab. To make the compilation process easier, a script can be used: builder.sce
Before the compilation is started, it may be necessary to edit the file Path.incl. In this file it is specified where scilab is installed and were lp_solve is installed. Change the paths as needed.
To make everything, just enter exec builder.sce and everything is build.
This compiles the source files to the needed libraries, compiles the sci scripts and makes the manuals. It also generates a new loader.sce file to load the driver into the Scilab workspace.

This build process is the same under Windows and Unix/Linux. Note that builder.sce generates Makefiles that are then used to build the code. Don't edit the Makefiles since your changes will be lost when build.sce is executed again.

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix


Changes compared to version 4

Main features and changes to v5 compared to v4

Overall, the v5 code is faster and more robust than v4. This robustness is for example proven by the fact that many more models can now be solved even without scaling. However, scaling should still be considered. The API has also routine to do a crash of basis (determine a starting point so that solving goes faster). The lp_solve program has been extended with options to handle the new functionality. It now also has options to write the model in the different file formats.
  • The modularization started in v4 has been significantly enhanced.
  • Internal logic and naming is much more in compliance with conventional usage.
  • Advanced pricing using Devex and Steepest Edge for both primal and dual simplexes.
  • Scaling behavior is made more consistent and many more options are available.
  • Presolve has been radically expanded.
  • A crash basis routine has been added to determine a starting point. This can improve solving time.
  • It is now possible to select desired combinations of primal and dual phases 1 and 2.
  • The native etaPFI/inverse has been improved with optimization of column ordering.
  • Alternative (and faster) inverse/re-factorization libraries are provided for. See Basis Factorization Packages
  • Alternative model readers and writers possible via the XLI implementation. See External Language Interfaces
  • B&B code has been made non-recursive (no more stack overflows!).
  • MIP contains many more variable selection and branching strategies, including pseudo-costs.
  • SOS and SC handling is faster (more branches avoided).
  • LP file support is expanded and now also includes full CPLEX LP format support.
  • Building the model via the API interface row by row can be improved spectacular by calling the new API call set_add_rowmode.

Changes in lp_solve program

The lp_solve program has many new options to make use of as many as possible possibilities of lpsolve. There are several extra options, some are extended and some are removed because they are obsolete. See lp_solve for a list of all possible options. Note that on this link there is also a reference to the API call(s) that are used for this option. There you can find more information on the option. See the list above for some of the new features.

What happened with lp2mps, mps2lp ?

These programs are removed. But don't panic, there is another way to convert from one format to another. This via the lp_solve program. This is done because of the support of a new format: The CPLEX-format. Because there are now 3 formats supported, it would have required 6 programs to convert from one format to another. Instead of doing this, lp_solve has new parameters to be able to write the model to a file, and that in all formats. So, lp_solve can read the model in any format and write it back in any format. In that case, it is most likely not whished to also calculate the model and therefore the parameter -parse_only can be used. Here some examples how to convert from one format to another:

lp to mps: lp_solve -parse_only -lp lpfile -wmps mpsfile
mps to lp: lp_solve -parse_only -mps mpsfile -wlp lpfile

It is even possible to generate several formats at the same time:
lp to all formats: lp_solve -parse_only -lp lpfile -wlp lpfile -wmps mpsfile

Changes in API calls

The API is not that much changed, but has been expanded to handle new functionality. Some simplification has taken place, for example in scaling, and a call to auto_scale is not necessary any more.
However the changes in some routines is big enough to break compatibility with version 4. Be aware of this. You must review your source code for the mentioned functions. Especially those with a (!) behind are very important to check. That is also the reason why the Windows dll will be called lpsolve51.dll compared to lpsolve.dll for version 4. Don't just rename this dll and expect that your program will work then.

Changed API calls

  • add_column, str_add_column
    • Return value is now unsigned char instead of int

  • add_constraint, str_add_constraint (!)
    • Return value is now unsigned char instead of int
    • Variable constr_type is now int instead of short
    • The constant LE has now value 1 instead of 0
      The constant EQ has now value 3 instead of 1

  • add_lag_con, str_add_lag_con (!)
    • Return value is now unsigned char instead of int
    • Variable constr_type is now int instead of short
    • The constant LE has now value 1 instead of 0
      The constant EQ has now value 3 instead of 1

  • add_sos (!)
    • Variable sostype is now int instead of short

  • column_in_lp (!)
    • Return value is now int instead of unsigned char

  • del_column
    • Return value is now unsigned char instead of int

  • del_constraint
    • Return value is now unsigned char instead of int

  • get_basis (!)
    • An extra variable is added to the argument list: nonbasic

  • get_bb_floorfirst (!)
    • This function is renamed. Before it was called get_floor_first
    • Return value is now int instead of short

  • get_bb_rule (!)
    • Return value is now int instead of short
    • The function returns different constants for different rules.

  • get_bounds_tighter
    • Return value is now unsigned char instead of int

  • get_col_name
    • When no name is set, the function now returns Cx instead of v_x

  • get_column
    • Return value is now unsigned char instead of int

  • get_constr_type (!)
    • The constant LE has now value 1 instead of 0
      The constant EQ has now value 3 instead of 1

  • get_constraints, get_ptr_constraints
    • Return value is now unsigned char instead of int

  • get_improve (!)
    • Return value is now int instead of short
    • Constant IMPROVE_FULL is renamed to IMPROVE_SOLVE
    • New constant IMPROVE_INVERSE

  • get_infinite (!)
    • The new default infinite value is 1e30 instead of 1e24

  • get_lambda, get_ptr_lambda
    • Return value is now unsigned char instead of int

  • get_maxpivot
    • This function is renamed. Before it was called get_max_num_inv

  • get_mip_gap (!)
    • An extra variable is added to the argument list: absolute

  • get_pivoting (!)
    • This function is renamed. Before it was called get_piv_rule
    • Return value is now int instead of short
    • The function returns different constants for different rules.

  • get_presolve (!)
    • This function is renamed. Before it was called is_do_presolve
    • Return value is now int instead of short
    • The function now returns constants instead of FALSE or TRUE.

  • get_primal_solution, get_ptr_primal_solution
    • Return value is now unsigned char instead of int

  • get_print_sol (!)
    • This function is renamed. Before it was called is_print_sol
    • Return value is now int instead of short
    • The function now also returns the constant AUTOMATIC.

  • get_rh_range (!)
    • The new default range value is 1e30 instead of 1e24

  • get_row
    • Return value is now unsigned char instead of int

  • get_row_name
    • When no name is set, the function now returns Rx instead of r_x

  • get_scaling (!)
    • This function is renamed. Before it was called get_scalemode
    • Return value is now int instead of short
    • The function returns different constants.

  • get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex (!)
    • Return value is now unsigned char instead of int
    • If there are integer variables, then these functions only work if set_presolve is called with parameter PRESOLVE_SENSDUALS before solve.

  • get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution (!)
    • Return value is now unsigned char instead of int
    • If there are integer variables, then these functions only work if set_presolve is called with parameter PRESOLVE_SENSDUALS before solve.
    • get_dual_solution is renamed. Before it was called get_reduced_costs
    • get_ptr_dual_solution is renamed. Before it was called get_ptr_reduced_costs

  • get_upbo (!)
    • The new default upper bound is 1e30 instead of 1e24

  • get_var_branch
    • Return value is now int instead of short

  • get_var_priority (!)
    • This function is renamed. Before it was called get_varpriority

  • get_variables, get_ptr_variables
    • Return value is now unsigned char instead of int

  • get_verbose (!)
    • Return value is now int instead of short
    • Return value can now also be NEUTRAL

  • is_anti_degen (!)
    • Return value is now unsigned char instead of short
    • An extra variable is added to the argument list: testmask

  • is_break_at_first
    • Return value is now unsigned char instead of short

  • is_debug
    • Return value is now unsigned char instead of short

  • is_feasible (!)
    • Return value is now unsigned char instead of int
    • An extra variable is added to the argument list: threshold

  • is_int
    • Return value is now unsigned char instead of int

  • is_lag_trace
    • Return value is now unsigned char instead of short

  • is_presolve (!)
    • This function is renamed. Before it was called is_do_presolve
    • Return value is now unsigned char instead of short
    • An extra variable is added to the argument list: testmask

  • is_SOS_var
    • Return value is now unsigned char instead of int

  • is_trace
    • Return value is now unsigned char instead of short

  • print_constraints (!)
    • An extra variable is added to the argument list: columns

  • print_solution (!)
    • An extra variable is added to the argument list: columns

  • read_lp, read_LP
    • Variable verbose is now int instead of short

  • read_mps, read_MPS
    • Variable verbose is now int instead of short

  • set_anti_degen (!)
    • Variable anti_degen is now int instead of short. Instead of FALSE/TRUE it takes new constants.

  • set_basis (!)
    • An extra variable is added to the argument list: nonbasic

  • set_bb_floorfirst (!)
    • This function is renamed. Before it was called set_floor_first
    • Variable branch_mode is now int instead of short

  • set_bb_rule (!)
    • Variable bb_rule is now int instead of short
    • Variable bb_rule now takes other constants.

  • set_bounds
    • Return value is now unsigned char instead of int

  • set_bounds_tighter
    • Variable tighten is now unsigned char instead of int

  • set_break_at_first
    • Variable break_at_first is now unsigned char instead of short

  • set_col_name
    • Return value is now unsigned char instead of int

  • set_constr_type (!)
    • Return value is now unsigned char instead of int
    • Variable constr_type is now int instead of short
    • The constant LE has now value 1 instead of 0
      The constant EQ has now value 3 instead of 1

  • set_debug
    • Variable debug is now unsigned char instead of short

  • set_epsint (!)
    • This function is renamed. Before it was called set_epsilon

  • set_improve (!)
    • Variable improve is now int instead of short
    • Constant IMPROVE_FULL is renamed to IMPROVE_SOLVE
    • New constant IMPROVE_INVERSE

  • set_int
    • Return value is now unsigned char instead of int
    • Variable must_be_int is now unsigned char instead of short

  • set_lag_trace
    • Variable lag_trace is now unsigned char instead of short

  • set_lowbo
    • Return value is now unsigned char instead of int

  • set_lp_name
    • Return value is now unsigned char instead of int

  • set_mat
    • Return value is now unsigned char instead of int

  • set_maxpivot
    • This function is renamed. Before it was called set_max_num_inv

  • set_mip_gap (!)
    • An extra variable is added to the argument list: absolute

  • set_obj_fn, str_set_obj_fn
    • Return value is now unsigned char instead of int

  • set_outputstream, set_outputfile (!)
    • The function set_outputfile is renamed. Before it was called print_file
    • Variable lp is added. Output is now set per lp.
    • The function set_outputstream is new

  • set_pivoting (!)
    • This function is renamed. Before it was called set_piv_rule
    • Variable pivot_rule is now int instead of short
    • The function uses different constants for different rules.

  • set_presolve (!)
    • This function is renamed. Before it was called set_do_presolve
    • Variable do_presolve is now int instead of short
    • The function uses different constants for different rules.

  • set_print_sol (!)
    • Variable print_sol is now int instead of short
    • Variable print_sol now also takes the value AUTOMATIC.

  • set_rh
    • Return value is now unsigned char instead of int

  • set_rh_range
    • Return value is now unsigned char instead of int

  • str_set_rh_vec
    • Return value is now unsigned char instead of int

  • set_row_name
    • Return value is now unsigned char instead of int

  • set_scaling (!)
    • This function is renamed. Before it was called set_scalemode
    • Variable scalemode is now int instead of short
    • The function uses different constants for different rules

  • set_semicont
    • Return value is now unsigned char instead of int
    • Variable must_be_sc is now unsigned char instead of short

  • set_trace (!)
    • Variable trace is now unsigned char instead of short

  • set_upbo
    • Return value is now unsigned char instead of int

  • set_var_branch
    • Return value is now unsigned char instead of int
    • Variable branch_mode is now int instead of short

  • set_var_weights (!)
    • This function is renamed. Before it was called set_varweights
    • Return value is now unsigned char instead of int

  • set_verbose (!)
    • Variable verbose is now int instead of short
    • Variable verbose can now also be NEUTRAL.

  • solve (!)
    • The return values of this function have changed.

  • write_lp, write_LP
    • Return value is now unsigned char instead of int

  • write_mps, write_MPS
    • Return value is now unsigned char instead of int

New API calls

  • add_columnex

  • add_constraintex

  • default_basis

  • free_lp

  • get_anti_degen

  • get_basiscrash

  • get_bb_depthlimit

  • get_bb_floorfirst
    • This function is renamed. Before it was called get_floor_first

  • get_origcol_name

  • get_dual_solution, get_ptr_dual_solution
    • These functions are renamed. Before they were called get_reduced_costs, get_ptr_reduced_costs

  • get_maxpivot
    • This function is renamed. Before it was called get_max_num_inv

  • get_nameindex

  • get_nonzeros

  • get_pivoting
    • This function is renamed. Before it was called get_piv_rule

  • get_presolve
    • This function is renamed. Before it was called is_do_presolve

  • get_var_primalresult

  • get_print_sol
    • This function is renamed. Before it was called is_print_sol

  • get_origrow_name

  • get_simplextype

  • get_scalelimit

  • get_scaling
    • The function get_scaling is renamed. Before it was called get_scalemode

  • get_scaling
    • The function get_scaling is renamed. Before it was called get_scalemode

  • get_var_dualresult

  • get_solutioncount

  • get_solutionlimit

  • get_status

  • get_statustext

  • get_var_priority
    • This function is renamed. Before it was called get_varpriority

  • get_working_objective

  • has_BFP

  • has_XLI

  • is_add_rowmode

  • is_binary

  • is_constr_type

  • is_free

  • is_infinite

  • is_integerscaling

  • is_maxim

  • is_native_BFP

  • is_native_XLI

  • is_negative

  • is_piv_rule

  • is_piv_mode
    • This function is renamed. Before it was called is_piv_strategy

  • is_presolve
    • This function is renamed. Before it was called is_do_presolve

  • is_scalemode

  • is_scaletype

  • is_semicont

  • print_str

  • print_tableau

  • put_msgfunc

  • read_freemps, read_freeMPS

  • read_XLI

  • set_add_rowmode

  • set_basiscrash

  • set_bb_depthlimit

  • set_bb_floorfirst
    • This function is renamed. Before it was called set_floor_first

  • set_BFP

  • set_column, set_columnex

  • set_XLI

  • set_binary

  • set_free

  • set_epsint
    • The function set_epsint is renamed. Before it was called set_epsilon

  • set_maxpivot
    • This function is renamed. Before it was called set_max_num_inv

  • set_obj

  • set_obj_fnex

  • set_outputstream, set_outputfile
    • The function set_outputfile is renamed. Before it was called print_file
    • The function set_outputstream is new

  • set_pivoting
    • This function is renamed. Before it was called set_piv_rule

  • set_preferdual

  • set_presolve
    • This function is renamed. Before it was called set_do_presolve

  • set_row, set_rowex

  • set_scalelimit

  • set_scaling
    • The function set_scaling is renamed. Before it was called set_scalemode

  • set_sense

  • set_simplextype

  • set_solutionlimit

  • set_var_weights
    • This function is renamed. Before it was called set_varweights

  • time_elapsed

  • print_debugdump

  • write_freemps, write_freeMPS

  • write_XLI

Removed API calls

  • auto_scale
    • This function is no longer required to be called. lpsolve calls it automatically when set_scaling was called to specify a scaling mode. Therefore, this function is no longer exported from the lpsolve library.

  • copy_lp

  • get_floor_first
    • Use get_bb_floorfirst instead

  • get_max_num_inv
    • Use get_maxpivot instead

  • get_pivot_rule
    • Use get_pivoting instead

  • get_ptr_work_solution

  • get_splitnegvars

  • get_reduced_costs, get_ptr_reduced_costs
    • Use get_dual_solution, get_ptr_dual_solution instead

  • get_varpriority
    • Use get_var_priority instead

  • get_work_solution

  • is_do_presolve
    • Use get_presolve instead

  • is_print_at_invert

  • is_print_sol
    • Use get_print_sol instead

  • is_do_presolve
    • Use is_presolve instead

  • is_piv_strategy
    • Use is_piv_mode instead

  • read_lp_file
    • Use read_lp instead

  • mat_elm
    • Use get_mat instead

  • print_file
    • Use set_outputfile instead

  • set_do_presolve
    • Use set_presolve instead

  • set_floor_first
    • Use set_bb_floorfirst instead

  • set_lowrange
    • Use set_rh_range instead

  • set_max_num_inv
    • Use set_maxpivot instead

  • set_pivot_rule
    • Use set_pivoting instead

  • set_print_at_invert

  • set_scalemode
    • Use set_scaling instead

  • set_splitnegvars

  • set_uprange
    • Use set_rh_range instead

  • set_varweights
    • Use set_var_weights instead


lp_solve Frequently Asked Questions

- Where can I find the latest version of lp_solve?
There is a yahoo group (http://groups.yahoo.com/group/lp_solve/) that bundles all activities of the lp_solve community. You have to register but this is for free. You will find there the latest sources, examples and manuals.

- Can I use lp_solve in commercial code?
Yes you can. However read the GNU LESSER GENERAL PUBLIC LICENSE which you can find in LGPL.txt

- How should lp_solve be cited when I use it?

lpsolve citation data
----------------------
Description     : Open source (Mixed-Integer) Linear Programming system
Language        : Multi-platform, pure ANSI C / POSIX source code, Lex/Yacc based parsing
Official name   : lp_solve (alternatively lpsolve)
Release data    : Version 5.1.0.0 dated 1 May 2004
Co-developers   : Michel Berkelaar, Kjell Eikland, Peter Notebaert
Licence terms   : GNU LGPL (Lesser General Public Licence)
Citation policy : General references as per LGPL
                  Module specific references as specified therein
This text is also in citations.txt

- What are the default bounds on variables?
As all (at least, simplex) lp solvers, the default lower bound on a variable is 0 and the default upper bound is unlimited.

- Is it possible to set negative bounds on variables?
Yes, this is perfectly possible.

- Is it possible to set a minus infinite lower bound on a variable?
Yes, this is possible. In the lp format, use as lower bound -Inf. In the mps format, in the BOUNDS section use FR
If you use the API interface, use get_infinite(lp)
Note that lp_solve splits this variable in 2 if there is a positive or no upper bound. This is done automatically by lp_solve. Because of this, the model becomes larger and thus can take some more time to solve, so only put a minus infinity lower bound on a variable when it is needed.

- What is the layout of the lp/mps/CPLEX format?
See the help file

- lp_solve fails to solve my model. What can I do?
lp_solve has a lot of options. See lp_solve -h
Especially consider to use scaling via the -s options

- Can lp_solve handle non-linear equations?
No, lp_solve can only handle linear constraints. However it also supports integer and semi-continuous variables and special ordered sets. This can be a help to simulate non-linearity.

- Can lp_solve handle ratios?
Ratios can be converted to linear equations. See the help file.

- lp_solve prints the output on screen. Can I have the output also in a file?
Yes, you can use standard redirection for that. Use the > before the filename to do that.
For example:
lp_solve input.lp >output.txt

- I have a constraint saying that x < 2, but lp_solve comes with a solution of 2, how comes?
< is the same as as <=
also > is the same as >=
This makes more than sense. Mathematically, 1.99999999999999999999999999999999999999999999999999 is smaller than 2, but what is the practical difference with 2? You always have to consider rounding errors also... If the variable is defined as integer then just say x <= 1

- When I solve my model, I get a stack overflow error/core dump/protection error. What is wrong?
If your model has integer/binary/semi-cont/SOS variables then version 5 can solve your problem. In version 4, the implemented branch-and-bound algorithm puts its branches on the stack and that can result in a stack overflow when it is a tough model. Version 5 doesn't put the branches on the stack anymore and because of that, this error is solved.

- Version 4 solves my models slower than version 3 did. What can I do?
Some models are indeed slower with version 4. Version 5 has several enhancements and is faster and more stable. Also version 4 always calculates the sensitivity information while older versions did not have this feature. This also takes some time. Version 5 only calculates the sensitivity when this information is specifically asked that makes it again faster.

- It takes a long time to build the model via the API interface. Especially add_constraint, add_constraintex, str_add_constraint seems to be slow. How can it be made faster?
Version 5 has a new API call set_add_rowmode that makes add_constraint, str_add_constraint spectacular faster.
If the model is build column by column, then it is strongly suggested to use add_columnex instead of add_column because add_columnex gives the possibility to only supply the non-zero elements and that speeds up building the model considerably, especially if the matrix is sparse (a lot of zero elements).
If the model is build row by row, then it is strongly suggested to use add_constraintex instead of add_constraint because add_constraintex gives the possibility to only supply the non-zero elements and that speeds up building the model considerably, especially if the matrix is sparse (a lot of zero elements).

- Can lp_solve give me the 'simplex tableau' of the model?
Version 5 has a new routine (print_tableau) to give you this information.

- Is there documentation about the API interface?
Yes, there are html (help) files. See the Files section.

- What is the maximum number of rows/columns that lp_solve can handle?
There is no fixed limit. Only available memory is a limit.

- Can lp_solve be called from .NET?
Yes it can. There is a VB.NET and a C# example in the Files section.

- Can lp_solve be called from Delphi?
Yes it can. There is a Delphi library the Files section. Thanks to Butch Dulaney for providing this module.

- Can lp_solve be called from Java?
Yes it can. There is a Java wrapper library called lpsolve4j in the files section that enables calls to lp_solve via the Java Native Interface (JNI) mechanism. Thanks to Juergen Ebert for providing this library.

- Can lp_solve be called from AMPL?
Yes it can. AMPL allows to call any solver if there is a driver program available. There is now also one for version 5.1. The driver program is called lpsolve. The driver program has a lot of new options such that the full potential of lp_solve can be used. Also see AMPL.

- Can lp_solve be called from MATLAB?
Yes it can. MATLAB allows to call any solver if there is a driver program available. There is now also one for version 5.1. The driver program is called mxlpsolve. The driver program has a lot of new options such that the full potential of lp_solve can be used. Also see MATLAB.

- Can lp_solve be called from O-Matrix?
Yes it can. O-Matrix allows to call any solver if there is a driver program available. There is now also one for version 5.1. The driver program is called omlpsolve. The driver program has a lot of options such that the full potential of lp_solve can be used. Also see O-Matrix.

- Can lp_solve be called from Scilab?
Yes it can. Scilab allows to call any solver if there is a driver program available. There is now also one for version 5.1. The driver program is called sclpsolve. The driver program has a lot of options such that the full potential of lp_solve can be used. Also see Scilab.

- I use a programming language that is not listed as supported or for which there are no examples. Can lp_solve be called from this language?
If this language allows calling functions from a C-dll, then it is possible. It is not because there is no example provided (yet) that it is not possible. The lp_solve community is always interested in your interface to call the lp_solve library. It doesn't have to be perfect.

- The Windows examples don't work. I get an error running them. Some dll cannot be found.
The examples call a dll that contains the lp_solve routines. This dll is called lpsolve*.dll and must be on the system either in the directory of the application or somewhere in the path.
This dll is contained in the windows binaries archive in the files section.

- Does lp_solve supports the mps free format?
This is possible from version 5.0.10.0. Before it was not possible. See read_freeMPS or the -fmps and -wfmps options to the lp_solve program. There is also a utility LPx2D that allows to convert this format. See the Files section.

- Does the lp_solve lp format support comments?
Yes it does. Put the comments between /* */
It can be anywhere in the text, even over multiple lines. Just like in C
lp_solve 4.0.1.11 and newer also supports the C++ line comment //

- I want to compile lp_solve myself, but I get link errors. Also what should I do with lp.y, lex.l, lp_rlp.y, lp_rlp.l?
The .y files are yacc files. They can be translated to C via the bison or yacc commands.
The .l files are lex files. They can be translated to C via the flex or lex commands.
lp.y/lex.l were used in version 4. Version 5 use the names lp_rlp.y/lp_rlp.l All unix environments have these commands. There are also windows versions available.
For example at http://unxutils.sourceforge.net/
Also only include lp.c in your compile project, not lex.c. lex.c is automatically #included by lp.c
Version 5 doesn't use the .c extension for the translated lex file. Instead it uses the .h extension. That way there is no confusion. So you don't have to (and may not) include it yourself again in the project.
To compile lp_solve, you must use make or gmake and a Makefile. There are several example makefiles in the source included like Makefile.linux, Makefile.msc. Enter make or gmake -f makefile. Note that for WINDOWS, you must use gnu make because MS make hasn't enough functionality. You can find gmake at http://unxutils.sourceforge.net/

- I compile lp_solve myself, but I get link errors saying that main (or _main) is already defined.
demo.c, mps2lp.c, lp2mps.c, lp_solve.c may never be in the same project. You must use one of these with the other C source files (except lex.c, see above) to make either demo.exe, mps2lp.exe, lp2mps.exe, lp_solve.exe

- I want to use the lpsolve dll, but when I compile my C/C++ program, I get link errors. He doesn't find any of the lpsolve API routines. What am I doing wrong?
Each function that you use in a C/C++ application must be defined. The compiler gives a warning if he doesn't find a definition of a function and the linker gives an error if he doesn't find an implementation for each used function. The implementation of a function can be in your source code, in another source file or in a library. If the function is in the same source code and defined before it is called, then you get no compiler warning because it is declared implicitly. If the function is after you call it, in another source file or in a library, then your source code must have a definition of this function or the compiler will give a warning. This is because the compiler wants to check if the function is correctly called (correct number of arguments, correct return code, should there be done some implicit conversion, ...). It is common to define these declarations in a header (.h) file. That is the reason why you include stdio.h, stdlib.h, string.h, windows.h and so on. For lpsolve, this library is lp_lib.h (lpkit.h in version 4 and before). Because lp_lib.h and lpkit.h also include other header files, you need these also. Including these source files do not guarantee that the linker will not give an error. This because the linker not only wants the definition of the functions, it also needs the implementation of it. So all routine calls that you do must be found somewhere by the linker. These can be in one of your source files and if they are not static defined then it is ok for the linker, or they are in a library. For example the function printf is a function from a library. This library can be linked statically or dynamically with your program. In Visual C, for the standard libraries this is defined via one of the compiler options /MT, /MD, /ML (in .NET via project, properties, C/C++, Code generation, Runtime Library. In VC6 via Project, settings, C/C++, category code generation, use runtime library). This results in using one of the libraries LIBC*.lib or MSVCRT*.lib. If you use static linking, then these routines are linked at link time with your program so that this program runs without the need of any other file. So these routines are then in LIBC.lib (the static libraries). If you use dynamic linking (MSVCRT.lib), then this library contains minimal code (not the implementation of this function) to call a library (a dll) at runtime. For example MSVCRT.DLL. So this dll must be on the system when you *run* the application. You will see that the resulting exe is smaller when dynamically linked compared to statically linked. This is logical because the implementation of the routine is in the DLL. The advantage of a DLL is that you can have a new implementation of it and use it in your application without having to rebuild your application. This because the DLL is linked at runtime with your program. Off course, the interface should stay the same for that. Also see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_c_run.2d.time_libraries.asp for an explanation on the VC runtime libraries.
Now besides the standard libraries there are also additional libraries. For example odbc32.lib is one that provides an API to access ODBC, or ws2_32.lib that contains the winsock/TCP/IP API calls and so on. These are all dynamic linked libraries, so the implementation is in a DLL. You must specify the library to the linker so that he knows how to call the implemented DLL (how it is called, ...).

Now if you want to use the lpsolve dll, you must also specify the lpsolve library to the linker so that you don't get the link errors. For version 5, this library is called lpsolve51.lib. You must specify it via Project, Properties, Linker, Input, Additional Dependencies (.NET) or Project, Settings, Link, Category General, Object Library Modules (VC6). There you add lpsolve51.lib (if there are already other libraries, just add at the end, separated via a space). You can specify the path where this file is located or you can specify via Project, Properies, Linker, General, Additional Library Directories (.NET) or Project, Settings, Link, Category Input, Additional library path, the paths where libraries can be found (separated by ,). Basically that is it. Also see Calling the lpsolve API from your application for more information.

- lp.c and lex.c that are generated on my system are different from the versions that can be found in the support folder in the files section. Are the latest versions of these files on your site?
Depending on the platform, the command used and the version of the command, these files are indeed different. That is not a problem. You can compare this with a compiler. The same source code generates totally different binaries, depending on the compiler used and its version, but the programs react the same (at least, they should ...).

- When I start the lp_solve program, nothing happens. I just get a blinking cursor. If I enter a command like lp1 = make_lp(0,4), I get a parse error. What is wrong here? How do I use the program?
lp_solve is a library with a set of routines with purpose to solve a MIP model. These routines are sometimes refered as the API (Application Programming Interface). These routines can be used in a C-program to solve MIP models. This is for example demonstrated in the demo program. Under Windows there is also a dll available that can be used by other programming languages to call the API functions. There are demos in VB and .NET available, but the principle is the same. The lp_solve program is basically another 'demo' program of this api. This program reads the MIP model from standard input or from a file and outputs the result back to the console or to a file. There are two possible input formats: the 'lp' format and the 'mps' format. This has nothing to do with the API. So lp1 = make_lp(0,4) is a totally wrong input for the lp_solve program. The lp-format is a 'readable' format of a MIP model.
For example:

max: -x1 + 2 x2;
C1: 2x1 + x2 <= 5;
-4 x1 + 4 x2 <= 5;

int x2,x1;

This lp-format is the default format of the lp_solve program.

The other format is mps format. This is a totally different format and used by many MIP solvers. This format is not very readable for us humans. The same example as above in mps format looks like this:

ROWS
 N  r_0
 L  C1
 L  r_2
COLUMNS
    MARK0000  'MARKER'                 'INTORG'
    x1        r_0                  1   C1                   2
    x1        r_2                 -4
    x2        r_0                 -2   C1                   1
    x2        r_2                  4
    MARK0001  'MARKER'                 'INTEND'
RHS
    RHS       C1                   5   r_2                  5
ENDATA

To enable this input format in the lp_solve program, use the -mps option.

The lp_solve program has many other options to control many other things like the amount of data to output, if scaling must be used and so on.

There are two other 'demo' programs: lp2mps and mps2lp. They convert model files from one format to the other.

The lp_solve, lp2mps and mps2lp programs all use API calls of the lp_solve library to perform their actions.

If lp_solve is started without an input file, then it gives a blinking cursor and waits for input. It is now possible to enter the model in the specified format (lp by default). But this is not very handy. You must enter the whole model each time you want to solve it and must be careful that you don't type any errors. To stop input mode, press Ctrl Z.
However it is much better to write your model in a disk file with your favourite editor (make sure it is in text format) and then provide this file to lp_solve. For example:

lp_solve input.lp

It is also possible to use input redirection:

lp_solve <input.lp

Or more sophisticated constructs like:

gen_model | lp_solve

gen_model is here a user written program that outputs the model to standard output and via the pipe character (|) this output is redirected to lp_solve. So no intermediate file is needed in this case.

- Is there no more user-friendly interface than the lp_solve command line program?
Yes there is, thanks to Henri Gourvest. For version 5 there is now the LPSolve IDE, a Windows interface to the lpsolve library. See LPSolve IDE for more information.


Linear Programming FAQ

Linear Programming
Frequently Asked Questions

Optimization Technology Center of
Northwestern University and Argonne National Laboratory

Posted at http://www-unix.mcs.anl.gov/otc/Guide/faq/LinearProgrammingFAQ.htm
Changes posted to Usenet newsgroup sci.op-research

Date of this version: April 1, 2004

  • Q1. "What is Linear Programming?"
  • Q2. "Where is there good software to solve LP problems?"
    • "Free" codes
    • Commercial codes and modeling systems
    • Free demos of commercial codes
  • Q3. "Oh, and we also want to solve it as an integer program."
  • Q4. "I wrote an optimization code. Where are some test models?"
  • Q5. "What is MPS format?"
  • Q6. Topics briefly covered:
    • Q6.1: "What is a modeling language?"
    • Q6.2: "How do I diagnose an infeasible LP model?"
    • Q6.3: "I want to know the specific constraints that contradict each other."
    • Q6.4: "I just want to know whether or not a feasible solution exists."
    • Q6.5: "I have an LP, except it's got several objective functions."
    • Q6.6: "I have an LP that has large almost-independent matrix blocks that are linked by a few constraints. Can I take advantage of this?"
    • Q6.7: "I am looking for an algorithm to compute the convex hull of a finite number of points in n-dimensional space."
    • Q6.8: "Are there any parallel LP codes?"
    • Q6.9: "What software is there for Network models?"
    • Q6.10: "What software is there for the Traveling Salesman Problem (TSP)?"
    • Q6.11: "What software is there for cutting or packing problems?"
    • Q6.12: "What software is there for linear programming under uncertainty?"
    • Q6.13: "I need to do post-optimal analysis."
    • Q6.14: "Do LP codes require a starting vertex?"
    • Q6.15: "How can I combat cycling in the Simplex algorithm?"
  • Q7. "What references are there in this field?"
    • General reference
    • Textbooks
    • Presentations of LP modeling systems
    • Books containing source code
    • Additional books
    • Periodicals
    • Articles of interest
  • Q8. "What's available online in this field?"
    • Online sources of optimization services
    • Online sources of optimization software
    • Online sources of optimization information
  • Q9. "Who maintains this FAQ list?"
See also the following pages
pertaining to mathematical programming and optimization modeling:
  • The related Nonlinear Programming FAQ.
  • Harvey Greenberg's Mathematical Programming Glossary.
  • The Optimization Online repository of reports and papers.
  • The e-Optimization.community website.

  • The NEOS Guide to optimization models and software.
  • The Decision Tree for Optimization Software by H.D. Mittelmann and P. Spellucci.
  • Software for Optimization: A Buyer's Guide by Robert Fourer.
  • The OR/MS Today 2001 Linear Programming Software Survey.

  • The NEOS Server for access to optimization solvers through the internet
  • Hans Mittelmann's Benchmarks for Optimization Software.
  • The Computational Optimization and Applications Software Forum
. . . and don't forget the Web search engines! Services such as google, go/infoseek, lycos, excite, and altavista can be surprisingly helpful in finding pages on particular problem types or application areas.

Q1. "What is Linear Programming?"

A: (For rigorous definitions and theory, which are beyond the scope of this document, the interested reader is referred to the many LP textbooks in print, a few of which are listed in the references section.)

A Linear Program (LP) is a problem that can be expressed as follows (the so-called Standard Form):

    minimize   cx
    subject to Ax  = b
                x >= 0
where x is the vector of variables to be solved for, A is a matrix of known coefficients, and c and b are vectors of known coefficients. The expression "cx" is called the objective function, and the equations "Ax=b" are called the constraints. All these entities must have consistent dimensions, of course, and you can add "transpose" symbols to taste. The matrix A is generally not square, hence you don't solve an LP by just inverting A. Usually A has more columns than rows, and Ax=b is therefore quite likely to be under-determined, leaving great latitude in the choice of x with which to minimize cx.

The word "Programming" is used here in the sense of "planning"; the necessary relationship to computer programming was incidental to the choice of name. Hence the phrase "LP program" to refer to a piece of software is not a redundancy, although I tend to use the term "code" instead of "program" to avoid the possible ambiguity.

Although all linear programs can be put into the Standard Form, in practice it may not be necessary to do so. For example, although the Standard Form requires all variables to be non-negative, most good LP software allows general bounds l <= x <= u, where l and u are vectors of known lower and upper bounds. Individual elements of these bounds vectors can even be infinity and/or minus-infinity. This allows a variable to be without an explicit upper or lower bound, although of course the constraints in the A-matrix will need to put implied limits on the variable or else the problem may have no finite solution. Similarly, good software allows b1 <= Ax <= b2 for arbitrary b1, b2; the user need not hide inequality constraints by the inclusion of explicit "slack" variables, nor write Ax >= b1 and Ax <= b2 as two separate constraints. Also, LP software can handle maximization problems just as easily as minimization (in effect, the vector c is just multiplied by -1).

The importance of linear programming derives in part from its many applications (see further below) and in part from the existence of good general-purpose techniques for finding optimal solutions. These techniques take as input only an LP in the above Standard Form, and determine a solution without reference to any information concerning the LP's origins or special structure. They are fast and reliable over a substantial range of problem sizes and applications.

Two families of solution techniques are in wide use today. Both visit a progressively improving series of trial solutions, until a solution is reached that satisfies the conditions for an optimum. Simplex methods, introduced by Dantzig about 50 years ago, visit "basic" solutions computed by fixing enough of the variables at their bounds to reduce the constraints Ax = b to a square system, which can be solved for unique values of the remaining variables. Basic solutions represent extreme boundary points of the feasible region defined by Ax = b, x >= 0, and the simplex method can be viewed as moving from one such point to another along the edges of the boundary. Barrier or interior-point methods, by contrast, visit points within the interior of the feasible region. These methods derive from techniques for nonlinear programming that were developed and popularized in the 1960s by Fiacco and McCormick, but their application to linear programming dates back only to Karmarkar's innovative analysis in 1984.

The related problem of integer programming (or integer linear programming, strictly speaking) requires some or all of the variables to take integer (whole number) values. Integer programs (IPs) often have the advantage of being more realistic than LPs, but the disadvantage of being much harder to solve. The most widely used general-purpose techniques for solving IPs use the solutions to a series of LPs to manage the search for integer solutions and to prove optimality. Thus most IP software is built upon LP software, and this FAQ applies to problems of both kinds.

Linear and integer programming have proved valuable for modeling many and diverse types of problems in planning, routing, scheduling, assignment, and design. Industries that make use of LP and its extensions include transportation, energy, telecommunications, and manufacturing of many kinds. A sampling of applications can be found in many LP textbooks, in books on LP modeling systems, and among the application cases in the journal Interfaces.

Q2. "Where is there good software to solve LP problems?"

A: Thanks to the advances in computing of the past decade, linear programs in a few thousand variables and constraints are nowadays viewed as "small". Problems having tens or hundreds of thousands of continuous variables are regularly solved; tractable integer programs are necessarily smaller, but are still commonly in the hundreds or thousands of variables and constraints. The computers of choice for linear and integer programming applications are Pentium-based PCs and the several varieties of Unix workstations.

There is more to linear programming than optimal solutions and number-crunching, however. This can be appreciated by observing that modern LP software comes in two related but very different kinds of packages:

  • Algorithmic codes are devoted to finding optimal solutions to specific linear programs. A code takes as input a compact listing of the LP constraint coefficients (the A, b, c and related values in the standard form) and produces as output a similarly compact listing of optimal solution values and related information.

  • Modeling systems are designed to help people formulate LPs and analyze their solutions. An LP modeling system takes as input a description of a linear program in a form that people find reasonably natural and convenient, and allows the solution output to be viewed in similar terms; conversion to the forms requried by algorithmic codes is done automatically. The collection of statement forms for the input is often called a modeling language.

Most modeling systems support a variety of algorithmic codes, while the more popular codes can be used with many different modeling systems. Because packages of the two kinds are often bundled for convenience of marketing or operation, the distinction between them is sometimes obscured, but it is important to keep in mind when attempting to sort through the many alternatives available.

Large-scale LP algorithmic codes rely on general-structure sparse matrix techniques and numerous other refinements developed through years of experience. The fastest and most reliable codes thus represent considerable development effort, and tend to be expensive except in very limited demonstration or "student" versions. Those codes that are free -- to all, or at least for research and teaching -- tend to be somewhat less robust, though they are still useful for many problems. The ability of a code to solve any particular class of problems cannot easily be predicted from problem size alone; some experimentation is usually necessary to establish difficulty.

Large-scale LP modeling systems are commercial products virtually without exception, and tend to be as expensive as the commercial algorithmic codes (again with the exception of small demo versions). They vary so greatly in design and capability that a description in words is adequate only to make a preliminary decision among them; your ultimate choice is best guided by using each candidate to formulate a model of interest.

Listed below are summary descriptions of available free codes, and a tabulation of many commercial codes and modeling systems for linear (and integer) programming. A list of free demos of commercial software appears at the end of this section.

Another useful source of information is the Optimization Software Guide by Jorge More' and Stephen Wright. It contains references to about 75 available software packages (not all of them just LP), and goes into more detail than is possible in this FAQ; see in particular the sections on "linear programming" and on "modeling languages and optimization systems." An updated Web version of this book is available on the NEOS Guide. Another good soruce of feature summaries and contact information is the Linear Programming Software Survey compiled by OR/MS Today (which also has the largest selection of advertisements for optimization software). Much information can also be obtained through the websites of optimization software developers, many of which are identified in the writeup and tables below.

To provide some idea of the relative performance of LP codes, a collection of benchmark results for optimization software is being compiled by Hans Mittelmann of Arizona State University. It includes tests of numerous simplex and interior-point codes for linear programming as well as branch-and-bound codes for linear integer programming; both commercial packages and downloadable free implementations are included. (Many nonlinear programming benchmarks are also available at this site.)

When evaluating any performance comparison, whether performed by a customer, vendor, or disinterested third party, keep in mind that all high-quality codes provide options that offer superior performance on certain difficult kinds of LP or IP problems. Benchmark studies of the "default settings" of codes will fail to reflect the power of any optional settings that are applicable.

"Free" codes

Some of these programs require registration or payment for some (especially commercial) uses. Conditions of use are also subject to change. It is a good practice to check a code's "readme" file or introductory documentation for restrictions before committing to use it.

These codes are not as fast or robust on average as the commercial products, but they're a a reasonable first try if you're not sure what level of power you need.

Based on the simplex method:

lp_solve is a downloadable code for linear and mixed-integer programming, currently maintained by Peter Notebaert (peno@mailme.org). Version 4.0 is now available, under the Lesser GNU Public License, along with converters between MPS format and lp_solve's own input format.

GLPK (GNU Linear Programming Kit) is a C package that includes simplex (and also primal-dual interior point) methods for linear programming, a branch-and-bound implementation for integer programming, and a translator for the GNU MathProg language (a subset of AMPL). It is made available as open source under the GNU General Program License; Andrew Makhorin (mao@mai2.rcnet.ru) is the developer and maintainter.

LP-Optimizer is a simplex-based code for linear and integer programs, written by Markus Weidenauer (weidenauer@netcologne.de). Free Borland Pascal 7.0 and Borland Delphi 4 source is available for downloading, as are executables for DOS and for Windows (95 or later).

SoPlex is an object-oriented implementation of the primal and dual simplex algorithms, developed by Roland Wunderling. Source code is available free for research uses at noncommercial and academic institutions.

Among the SLATEC library routines is a Fortran sparse implementation of the simplex method, SPLP. Its documentation states that it can solve LP models of "at most a few thousand constraints and variables".

Based on interior-point methods:

The Optimization Technology Center at Argonne National Laboratory and Northwestern University has developed PCx, an interior-point code that is freely available for downloading. PCx is available in Fortran or C source or a variety of Windows and Unix executables, with an optional Java-based GUI interface. Input can be specified in MPS form or by use of the AMPL modeling language.

Csaba Meszaros (meszaros@sztaki.hu) has written BPMPD, an interior-point code for linear and convex quadratic programs. A demonstration version, which solves problems of any size but does not report optimal values of the variables for problems larger than about 500 x 500, is available as a Windows95/NT executable or DLL. Separately, a large variety of Unix binaries for Linux and four workstation platforms are available for downloading.

Jacek Gondzio (gondzio@maths.ed.ac.uk) has developed the interior-point LP (and convex QP) solver HOPDM. Several papers (also available at the HOPDM website) detail the features of this solver, which include automatic selection of multiple centrality correctors and factorization method, and a "warm start" feature for taking advantage of known solutions. A public-domain Fortran version (2.13, LP only) can be downloaded, and a newer C version (2.30) is available on request to the developer.

If you want to solve an LP without downloading a code to your own machine, you can execute many of these interior-point codes (as well as varied commercial LP codes) through the NEOS Server.

Modeling systems:

LPL is a mathematical modeling language for formulating and maintaining linear and mixed-integer programs. It is particularly notable for its ability to also handle a variety of logical constraints, which are translated symbolically into algebraic constraints using 0-1 variables. You can download the software and documentation free of charge.

The open source "scenario scripting language" IPAT-S includes support for linear programming problems, using the lp_solve library.

Other software of interest:

COIN, a Common Optimization INterface for Operations Research, is an "open source" repository established with support from IBM Corporation. Source code initially available includes a parallel branch-cut-price framework, a cut generation library, an implementation of the Volume Algorithm for fast approximate solutions to combinatorial problems, and an open solver interface layer.

ABACUS is a C++ class library that "provides a framework for the implementation of branch-and-bound algorithms using linear programming relaxations that can be complemented with the dynamic generation of cutting planes or columns" (branch-and-cut and/or branch-and-price). It relies on CPLEX, SoPlex, or Xpress-MP to solve linear programs. Further information is available from Stefan Thienel, thienel@informatik.uni-koeln.de.

Various small-scale implementations are mainly intended for instructional purposes.

  • Robert Vanderbei of Princeton has developed Java-based tools for facilitating simplex pivots and facilitating network simplex pivots, and well as a variety of Java applets that test students on their knowledge of various simplex-based methods.
  • A web-based Linear Program Solver with Simplex, part of the RIOT project at Berkeley, appears to be useful for solving small models that can be entered by hand.
  • The NEOS Guide developed by Northwestern and Argonne National Laboratory offers a Java-based Simplex Tool that demonstrates the workings of the simplex method on small user-entered problems.

The Operations Research Laboratory at Seoul National University, Korea offers C source for large-scale Linear Programming software (both Simplex and Barrier) and for numerous more specialized optimization problems.

Will Naylor has a collection of software he calls WNLIB. Routines of interest include a dense-matrix simplex method for linear programming (with anti-cycling and numerical stability "hacks") and a sparse-matrix transportation/assignment problem routine. (WNLIB also contains routines pertaining to nonlinear optimization.)

A code known as lp is Mike Hohmeyer's C implementation of Raimund Seidel's O(d! n) time linear programming algorithm. It's reputed to be extremely fast in low dimensions (say, d < 10), so that it's appropriate for a variety of geometric problems, especially with very large numbers of constraints.

The next several suggestions are for codes that are severely limited by the dense vector and matrix algebra employed in their implementations; they may be OK for models with (on the order of) 100 variables and constraints, but it's unlikely they will be satisfactory for larger models. In the words of Matt Saltzman (mjs@clemson.edu):

    The main problems with these codes have to do with scaling, use of explicit inverses and lack of reinversion, and handling of degeneracy. Even small problems that are ill-conditioned or degenerate can bring most of these tableau codes to their knees. Other disadvantages for larger problems relate to sparsity, pricing, and maintaining the complete nonbasic portion of the tableau. But for small, dense problems these difficulties may not be serious enough to prevent such codes from being useful, or even preferable to more "sophisticated" sparse codes. In any event, use them with care.
  • For DOS/PC users, there is a "friendly Linear Programming and Linear Goal Programming" code called LINSOLVE, developed by Prof. Timo Salmi (ts@uwasa.fi).
  • Also on the garbo server is a LP 2.61, a shareware linear and integer programming code of Cornel Huth, distributed as PC binaries. It accepts text and spreadsheet files as input.
  • There is an ACM TOMS routine for LP, #552. This routine was designed for fitting data to linear constraints using an L1 norm, but it uses a modification of the Simplex Method and could presumably be modified to satisfy LP purposes.
  • There are books that contain source code for the Simplex Method. See the section on references. You should not expect such code to be robust. In particular, you can check whether it uses a 2-dimensional array for the A-matrix; if so, it is surely using the tableau Simplex Method rather than sparse methods, and Saltzman's comments will apply.
  • OR-Objects is a Java class library that includes objects for dense linear programming (and other methods common in operations research).
  • Pysimplex contains an implementation of the simplex method in the object-oriented language Python, together with modules that allow construction of models in a straightforward symbolic manner.

For Macintosh users there is relatively little available, but here are a few possibilities:

  • Mac OS X binaries for the student version of AMPL and three solvers are available from netlib.
  • LinPro is a freely available but strictly small-scale linear programming package. It has its own input format and does not support MPS format.
  • The 2nd edition of Wayne L. Winston's Introduction to Mathematical Programing: Applications and Algorithms is listed by Duxbury Press as being available with the Macintosh LINDO LP solver.

Stephen F. Gale (sfgale@calcna.ab.ca) writes:

  • Available at my website is a fairly simple Simplex Solver written for Turbo Pascal 3.0. The original algorithm is from the book "Some Common BASIC Programs" by Lon Poole and Mary Borchers (ISBN 0-931988-06-3). However, I revised it considerably when I converted it to Pascal. I then added Sensitivity Analysis based on the book "The Operations Research Problem Solver" (ISBN 0-87891-548-6). I have tested the program on over 30 textbook problems, but never used it for real life applications. If someone finds a problem with the program, I would be pleased to correct it. I would also appreciate knowing how the program was used.

The following suggestions may represent low-cost ways of solving LPs if you already have certain software available to you.

  • All of the most popular spreadsheet programs come with a limited linear/integer programming solver as a feature or add-in. A much broader range of more powerful solvers are available for separate purchase from LINDO Systems and Frontline Systems. Some of these solvers give special attention to common spreadsheet functions such as MIN, IF, and LOOKUP that can be handled by linear or integer programming approaches.
  • QSB for Windows by Yih-Long Chang, published by Wiley, has an LPf module among its routines.
  • If you have access to a commercial math library, such as SAS, IMSL or NAG, you may be able to use an LP routine from there.
  • If you have MATLAB, you can run a number of useful optimization packages that provide some linear programming features:
    • The MATLAB Optimization Toolbox.
    • The TOMLAB Optimization Environment provides MATLAB connections to MINOS for large-scale linear programming and Xpress-MP and CPLEX for large-scale linear and integer programming, as well as to these and other codes for a variety of nonlinear programming problems. (See listing under modeling systems below.)
    • milp.m, a routine that uses the Optimization Toolbox to solve mixed-integer linear programs.
    • LPMEX, an interface to let you run lp_solve from MATLAB.
    • MATLAB interfaces to the LOQO and LIPSOL, and MOSEK solvers.
    The MAPLE and Mathematica packages for mathematical computation also provide some linear programming routines; you can get more information by searching at their websites.

Commercial codes and modeling systems

If your models prove to be too difficult for free or add-on software to handle, then you may have to consider acquiring a commercial LP code. Dozens of such codes are on the market. There are many considerations in selecting an LP code. Speed is important, but LP is complex enough that different codes go faster on different models; you won't find a "Consumer Reports" article to say with certainty which code is THE fastest. I usually suggest getting benchmark results for your particular type of model if speed is paramount to you. Benchmarking can also help determine whether a given code has sufficient numerical stability for your kind of models.

Other questions you should answer: Can you use a stand-alone code, or do you need a code that can be used as a callable library, or do you require source code? Do you want the flexibility of a code that runs on many platforms and/or operating systems, or do you want code that's tuned to your particular hardware architecture (in which case your hardware vendor may have suggestions)? Is the choice of algorithm (Simplex, Interior-Point) important to you? Do you need an interface to a spreadsheet code? Is the purchase price an overriding concern? If you are at a university, is the software offered at an academic discount? How much hotline support do you think you'll need? There is usually a large difference in LP codes, in performance (speed, numerical stability, adaptability to computer architectures) and in features, as you climb the price scale.

Information on commercial systems is provided in two tables below. The first lists packages that are primarily algorithmic codes, and the second lists modeling systems. For a more extensive summary, take a look at the Linear Programming Software Survey in the August 1999 issue of OR/MS Today.

In the tables below, product names are linked to product or developer websites where known. Under "Platform" is an indication of common environments in which the code runs, with the choices being Microsoft Windows (PC), Macintosh OS (M), and Unix/Linux (U). The codes under "Features" are as follows:

                  S=Simplex        Q=Quadratic
                  B=Barrier        G=General Nonlinear
                  N=Network
                  I=Integer/Combinatorial
All product information is subject to change, and some delay may occur before changes are reflected in this table. Consult the products' developers or vendors for definitive information.

Solver Product | Features | Platform | Phone (+1) | E-mail address
C-WHIZ | SI | PC U | 703-412-3201 | info@ketronms.com
CPLEX | SBINQ | PC U | 800-367-4564 775-831-7744 | info@ilog.com
FortMP | SBIQ | PC U | +44 18-9525-6484 | optirisk@optirisk-systems.com
HI-PLEX | S | PC U | +44 20-7594-8334 | i.maros@ic.ac.uk
HS/LP | SI | PC | 201-627-1424 | info@haverly.com
ILOG Opt Suite | SBINQ | PC U | 800-367-4564 775-831-7744 | info@ilog.com
LAMPS | SI | PC U | +44 20-8877-3030 | info@amsoft.demon.co.uk
LINDO API | SBI | PC U | 312-988-7422 | info@lindo.com
LOQO | IQG | PC U | 609-258-0876 | rvdb@princeton.edu
LPS-867 | SI | PC U | 609-737-6800 | info@main.aae.com
MINOS | SG | PC | 650-856-1695 | info@sbsi-sol-optimize.com
MINTO | I | U | 404-894-6287 | martin.savelsbergh@isye.gatech.edu
MOSEK | SBQG | PC U | +45 3917-9907 | info@mosek.com
MPSIII | SIN | PC U | 703-412-3201 +352 5313-2455 | info@ketronms.com rudy@arbed-rech-isdn1.restena.lu
OSL | SBINQ | PC U | 914-435-6685 | osl@us.ibm.com
SAS/OR | SINQG | PC M U | 919-677-8000 |
SCICONIC | SI | PC U | +44 19-0828-4188 | msukwt03.gztltm@eds.com
Solver DLL Platform | SIQG | PC | 888-831-0333 775-831-0300 | info@frontsys.com
SOPT | SBIQG | PC U | 732-264-4700 +81 3-5966-1220 | sales@saitech-inc.com
XA | SI | PC M U | 626-441-1565 | jim@sunsetsoft.com
Xpress-MP | SBIQ | PC U | 201-567-9445 +44 1604-858993 | info@dashoptimization.com

Modeling Product | Platform | Phone (+1) | E-mail address
AIMMS | PC | +31 23-5511512 | info@paragon.nl
AMPL | PC U | see list | info@ampl.com
ANALYZE | PC | 303-796-7830 | hgreenbe@carbon.cudenver.edu
DecisionPRO | PC | 919-859-4101 | vsinfo@vanguardsw.com
DATAFORM | PC U | 703-412-3201 | info@ketronms.com
EZMod | PC | 866-811-4541 418-653-0853 | info@modellium.com
GAMS | PC U | 202-342-0180 | sales@gams.com
LINGO | PC U | 800-441-2378 | info@lindo.com
LP-TOOLKIT | PC U | +33 1-39071240 | info@eurodecision.fr
MathPro | PC U | 301-951-9006 | mathpro@erols.com
MIMI | PC U | 908-464-8300 | supplychain@aspentech.com
MINOPT | PC U | 609-258-3097 | jean@princeton.edu
MODLER | PC U | 303-796-7830 | hgreenbe@carbon.cudenver.edu
MPL | PC | 703-522-7900 | info@maximal-usa.com
OML | PC U | 703-412-3201 | info@ketronms.com
OMNI | PC U | 973-627-1424 | info@haverly.com
OPL Studio | PC U | 800-367-4564 775-831-7744 | info@ilog.com
Premium Solver Platform | PC | 888-831-0333 775-831-0300 | info@frontsys.com
TOMLAB | PC U M | +46 21-804760 530-629-1110 | sales@tomlab.biz us@tomlab.biz
What's Best! | PC U M | 800-441-2378 | info@lindo.com
Xpress-Mosel | PC U | 201-567-9445 +44 1604-858993 | info@dashoptimization.com

Free demos of commercial codes

The following commercial LP software developers make demo or academic versions available for downloading through their websites:
  • AIMMS
  • AMPL with CPLEX and MINOS
  • ANALYZE, MODLER and RANDMOD
  • C-WHIZ and OML
  • LINDO, LINGO and What's Best!
  • LOQO with a built-in AMPL interface
  • MOSEK API and MATLAB toolbox
  • MPL with CPLEX
  • OPL Studio with the ILOG Optimization Suite (including CPLEX)
  • TOMLAB with MINOS, CPLEX, Xpress-MP, and other solvers running from Matlab.
  • Xpress-IVE with the Xpress-MP Optimizer and Xpress-Mosel
Typically these versions are limited in the size of problem they accept, or are made available only for "academic use" (mainly research or teaching at universities). Nevertheless, they have most or all of the features of the full versions. All run under recent versions of Microsoft Windows, and some under Linux, Solaris, or other Unix variants; check the relevant web pages for details.

In a number of cases, the developers have also written books about these modeling systems. Demo software with a corresponding book can provide a convenient and inexpensive package for use in teaching or self-study.

Many developers are also willing to arrange for you to "borrow" copies of their full-featured versions for purposes of evaluation. Details vary, however, so you'll have to check with each vendor whose product you're interested in.

Q3. "Oh, and we also want to solve it as an integer program."

A: Integer LP models are ones whose variables are constrained to take integer or whole number (as opposed to fractional) values. It may not be obvious that integer programming is a very much harder problem than ordinary linear programming, but that is nonetheless the case, in both theory and practice.

Integer models are known by a variety of names and abbreviations, according to the generality of the restrictions on their variables. Mixed integer (MILP or MIP) problems require only some of the variables to take integer values, whereas pure integer (ILP or IP) problems require all variables to be integer. Zero-one (or 0-1 or binary) MIPs or IPs restrict their integer variables to the values zero and one. (The latter are more common than you might expect, because many kinds of combinatorial and logical restrictions can be modeled through the use of zero-one variables.)

For the sake of generality, the following disucssion uses the term MIP to refer to any kind of integer LP problem; the other kinds can be viewed as special cases. MIP, in turn, is a particular member of the class of combinatorial or discrete optimization problems. In fact the problem of determining whether a MIP has an objective value less than a given target is a member of the class of "NP-complete" problems, all of which are very hard to solve (at least as far as anyone has been able to tell). Since any NP-complete problem is reducible to any other, virtually any combinatorial problem of interest can be attacked in principle by solving some equivalent MIP. This approach sometimes works well in practice, though it is by no means infallible.

People are sometimes surprised to learn that MIP problems are solved using floating point arithmetic. Most available general-purpose large-scale MIP codes use a procedure called "branch-and-bound" to search for an optimal integer solution by solving a sequence of related LP "relaxations" that allow some fractional values. Good codes for MIP distinguish themselves primarily by solving shorter sequences of LPs, and secondarily by solving the individual LPs faster. (The similarities between successive LPs in the "search tree" can be exploited to speed things up considerably.) Even more so than with regular LP, a costly commercial code may prove its value if your MIP model is difficult.

Another solution approach known generally as constraint logic programming or constraint programming (CP) has drawn increasing interest of late. Having their roots in studies of logical inference in artificial intelligence, CP codes typically do not proceed by solving any LPs. As a result, compared to branch-and-bound they search "harder" but faster through the tree of potential solutions. Their greatest advantage, however, lies in their ability to tailor the search to many constraint forms that can be converted only with difficulty to the form of an integer program; their greatest success tends to be with "highly combinatorial" optimization problems such as scheduling, sequencing, and assignment, where the construction of an equivalent IP would require the definition of large numbers of zero-one variables. Notable constraint programming codes include CHIP, ECLiPSe, GNU Prolog, IF/Prolog, ILOG Solver, Koalog Constraint Solver, MOzart, and SICStus Prolog. Much more information can be found in the Constraints Archive, which contains the the comp.constraints newsgroup FAQ, pages of constraint-related pointers, source code for various systems, benchmarks, a directory of people interested in constraints, constraint bibliographies, and a collection of on-line papers.

The IP and CP approaches are not so far apart as they may seem, particularly now that each is being adapted to incorporate some of the strengths of the other. Some fundamental connections are described in [Chandru and Hooker] and [Hooker].

Whatever your solution technique, you should be prepared to devote far more computer time and memory to solving a MIP problem than to solving the corresponding LP relaxation. (Or equivalently, you should be prepared to solve much smaller MIP problems than LP problems using a given amount of computer resources.) To further complicate matters, the difficulty of any particular MIP problem is hard to predict (in advance, at least!). Problems in no more than a hundred variables can be challenging, while others in tens of thousands of variables solve readily. The best explanations of why a particular MIP is difficult often rely on some insight into the system you are modeling, and even then tend to appear only after a lot of computational tests have been run. A related observation is that the way you formulate your model can be as important as the actual choice of solver.

Thus a MIP problem with hundreds of variables (or more) should be approached with a certain degree of caution and patience. A willingness to experiment with alternative formulations and with a MIP code's many search options often pays off in greatly improved performance. In the hardest cases, you may wish to abandon the goal of a provable optimum; by terminating a MIP code prematurely, you can often obtain a high-quality solution along with a provable upper bound on its distance from optimality. A solution whole objective value is within some fraction of 1% of optimal may be all that is required for your purposes. (Indeed, it may be an optimal solution. In contrast to methods for ordinary LP, procedures for MIP may not be able to prove a solution to be optimal until long after they have found it.)

Once one accepts that large MIP models are not typically solved to a proved optimal solution, that opens up a broad area of approximate methods, probabilistic methods and heuristics, as well as modifications to B&B. See [Balas] which contains a useful heuristic for 0-1 MIP models. See also the brief discussion of Genetic Algorithms and Simulated Annealing in the Nonlinear Programming FAQ.

A major exception to this somewhat gloomy outlook is that there are certain models whose LP solution always turns out to be integer, assuming the input data is integer to start with. In general these models have a "unimodular" constraint matrix of some sort, but by far the best-known and most widely used models of this kind are the so-called pure network flow models. It turns out that such problems are best solved by specialized routines, usually based on the simplex method, that are much faster than any general-purpose LP methods. See the section on Network models for further information.

Commercial MIP codes are listed with the commercial LP codes and modeling systems above. The following are notes on some publicly available codes for MIP problems.

  • The "free" codes lp_solve and GLPK, mentioned earlier, accept MIP models.

  • OPBDP is a C++ implementation by Peter Barth of an implicit enumeration algorithm for solving linear 0-1 optimization problems. The developer states that the algorithm compares well with commercial linear programming-based branch-and-bound on a variety of standard 0-1 integer programming benchmarks; exploiting the logical structure of a problem, using OPBDP, is said to yield good performance on problems where exploiting the polyhedral structure seems to be inefficient and vice versa.

  • I have seen mention made of algorithm 333 in the Collected Algorithms from CACM, though I'd be surprised if it was robust enough to solve large models. I am not aware of this algorithm being available online anywhere.

  • In [Syslo] is code for 28 algorithms, most of which pertain to some aspect of Discrete Optimization.

  • Omega analyzes systems of linear equations in integer variables. It does not solve optimization problems, except in the case that a model reduces completely, but its features could be useful in analyzing and reducing MIP models.

Q4. "I wrote an optimization code. Where are some test models?"

A: If you want to try out your code on some real-world linear programs, there is a very nice collection of small-to-medium-size ones, with a few that are rather large, popularly known as the Netlib collection (although Netlib consists of much more than just LP). Also on netlib is a collection of infeasible LP models. See the readme file for a listing and further information. The test problem files (after you uncompress them) are in a format called MPS, which is described in another section of this document. Note that, when you receive a model, it may be compressed both with the Unix compression utility (use uncompress if the file name ends in .Z) and with an LP-specific program (grab either emps.f or emps.c at the same time you download the model, then compile/run the program to undo the compression).

There is a collection of mixed integer (linear) programming (or MIP) models, called MIPLIB, housed at Rice University.

TSPLIB is a library of traveling salesman and related problems, including vehicle routing problems.

For network flow problems, there are some generators and instances collected at DIMACS. The NETGEN and GNETGEN generator can be downloaded from netlib. Generators and instances for multicommodity network flow problems are maintained by the Operations Research group in the Department of Computer Science at the University of Pisa.

The commercial modeling language GAMS comes with about 160 test models, which you might be able to test your code with. There are also pages containing pointers to numerous examples in AMPL, MPL, and OPL.

There is a collection called MP-TESTDATA available at Konrad-Zuse-Zentrum fuer Informations-technik Berlin (ZIB). This directory contains various subdirectories, each of which has a file named "index" containing further information. Indexed at this writing are: assign, cluster, lp, ip, matching, maxflow, mincost, set-parti, steiner-tree, tsp, vehicle-rout, and generators.

John Beasley of the Imperial College Management School maintains the OR-Library, which lists linear programming and over 3 dozen other categories of optimization test problems.

Finally, Martin Chlond's pages on Integer Programming in Recreational Mathematics provide a variety of challenges for both modelers and software.

Q5. "What is MPS format?"

A: MPS format was named after an early IBM LP product and has emerged as a de facto standard ASCII medium among most of the commercial LP codes. Essentially all commercial LP codes accept this format, but if you are using public domain software and have MPS files, you may need to write your own reader routine for this. It's not too hard. See also the comment regarding the lp_solve code, in another section of this document, for the availability of an MPS reader.

The main things to know about MPS format are that it is column oriented (as opposed to entering the model as equations), and everything (variables, rows, etc.) gets a name. The MIPLIB site provides a concise summary of MPS format, and a more detailed description is given in [Murtagh].

MPS is a very old format, so it is set up as though you were using punch cards, and is not free format. Fields start in column 1, 5, 15, 25, 40 and 50. Sections of an MPS file are marked by so-called header cards, which are distinguished by their starting in column 1. Although it is typical to use upper-case throughout the file (like I said, MPS has long historical roots), many MPS-readers will accept mixed-case for anything except the header cards, and some allow mixed-case anywhere. The names that you choose for the individual entities (constraints or variables) are not important to the solver; you should pick names that are meaningful to you, or will be easy for a post-processing code to read.

Here is a little sample model written in MPS format (explained in more detail below):

NAME          TESTPROB
ROWS
 N  COST
 L  LIM1
 G  LIM2
 E  MYEQN
COLUMNS
    XONE      COST                 1   LIM1                 1
    XONE      LIM2                 1
    YTWO      COST                 4   LIM1                 1
    YTWO      MYEQN               -1
    ZTHREE    COST                 9   LIM2                 1
    ZTHREE    MYEQN                1
RHS
    RHS1      LIM1                 5   LIM2                10
    RHS1      MYEQN                7
BOUNDS
 UP BND1      XONE                 4
 LO BND1      YTWO                -1
 UP BND1      YTWO                 1
ENDATA

For comparison, here is the same model written out in an equation-oriented format:

Optimize
 COST:    XONE + 4 YTWO + 9 ZTHREE
Subject To
 LIM1:    XONE + YTWO < = 5
 LIM2:    XONE + ZTHREE > = 10
 MYEQN:   - YTWO + ZTHREE  = 7
Bounds
 0 < = XONE < = 4
-1 < = YTWO < = 1
End

Strangely, there is nothing in MPS format that specifies the direction of optimization. And there really is no standard "default" direction; some LP codes will maximize if you don't specify otherwise, others will minimize, and still others put safety first and have no default and require you to specify it somewhere in a control program or by a calling parameter. If you have a model formulated for minimization and the code you are using insists on maximization (or vice versa), it may be easy to convert: just multiply all the coefficients in your objective function by (-1). The optimal value of the objective function will then be the negative of the true value, but the values of the variables themselves will be correct.

The NAME card can have anything you want, starting in column 15. The ROWS section defines the names of all the constraints; entries in column 2 or 3 are E for equality rows, L for less-than ( <= ) rows, G for greater-than ( >= ) rows, and N for non-constraining rows (the first of which would be interpreted as the objective function). The order of the rows named in this section is unimportant.

The largest part of the file is in the COLUMNS section, which is the place where the entries of the A-matrix are put. All entries for a given column must be placed consecutively, although within a column the order of the entries (rows) is irrelevant. Rows not mentioned for a column are implied to have a coefficient of zero.

The RHS section allows one or more right-hand-side vectors to be defined; most people don't bother having more than one. In the above example, the name of the RHS vector is RHS1, and has non-zero values in all 3 of the constraint rows of the problem. Rows not mentioned in an RHS vector would be assumed to have a right-hand-side of zero.

The optional BOUNDS section lets you put lower and upper bounds on individual variables (no * wild cards, unfortunately), instead of having to define extra rows in the matrix. All the bounds that have a given name in column 5 are taken together as a set. Variables not mentioned in a given BOUNDS set are taken to be non-negative (lower bound zero, no upper bound). A bound of type UP means an upper bound is applied to the variable. A bound of type LO means a lower bound is applied. A bound type of FX ("fixed") means that the variable has upper and lower bounds equal to a single value. A bound type of FR ("free") means the variable has neither lower nor upper bounds.

There is another optional section called RANGES that I won't go into here. The final card must be ENDATA, and yes, it is spelled funny.

Q6. Topics briefly covered:

Q6.1: "What is a modeling language?"

A: There is more to linear programming (or integer programming) than optimal solutions and number-crunching. This can be appreciated by observing that modern LP software comes in two related but very different kinds of packages:
  • Algorithmic codes are devoted to finding optimal solutions to specific linear programs. A code takes as input a compact listing of the LP constraint coefficients (the A, b, c and related values in the standard form) and produces as output a similarly compact listing of optimal solution values and related information.

  • Modeling systems are designed to help people formulate LPs and analyze their solutions. An LP modeling system takes as input a description of a linear program in a form that people find reasonably natural and convenient, and allows the solution output to be viewed in similar terms; conversion to the forms requried by algorithmic codes is done automatically. The collection of statement forms for the input is often called a modeling language.

Most modeling systems support a variety of algorithmic codes, while the more popular codes can be used with many different modeling systems. Because packages of the two kinds are often bundled for convenience of marketing or operation, the distinction between them is sometimes obscured, but it is important to keep in mind when sorting through the many possibilities. See under Commercial Codes and Modeling Systems elsewhere in this FAQ for a list of modeling systems available. There are no free ones of note, but many do offer free demo versions.

Common alternatives to modeling languages and systems include spreadsheet front ends to optimization, and custom optimization applications written in general-purpose programming languages. You can find a discussion of the pros and cons of these approaches in What Modeling Tool Should I Use? on the Frontline Systems website.

Q6.2: "How do I diagnose an infeasible LP model?"

A: A linear program is infeasible if there exists no solution that satisfies all of the constraints -- in other words, if no feasible solution can be constructed. Since any real operation that you are modeling must remain within the constraints of reality, infeasibility most often indicates an error of some kind. Simplex-based LP software efficiently detects when no feasible solution is possible; some early interior-point codes could not detect an infeasible situation as reliably, but remedies for this flaw have been introduced.

The source of infeasibility is often difficult to track down. It may stem from an error in specifying some of the constraints in your model, or from some wrong numbers in your data. It can be the result of a combination of factors, such as the demands at some customers being too high relative to the supplies at some warehouses.

Upon detecting infeasibility, LP codes typically show you the most recent infeasible solution that they have encountered. Sometimes this solution provides a good clue as to the source of infeasibility. If it fails to satisfy certain capacity constraints, for example, then you would do well to check whether the capacity is sufficient to meet the demand; perhaps a demand number has been mistyped, or an incorrect expression for the capacity has been used in the capacity constraint, or or the model simply lacks any provision for coping with increasing demands. More often, unfortunately, LP codes respond to an infeasible problem by returning a meaninglessly infeasible solution, such as one that violates material balances.

A more useful approach is to forestall meaningless infeasibilities by explicitly modeling those sources of infeasibility that you view as realistic. As a simple example, you could add a new "slack" variable on each capacity constraint, having a very high penalty cost. Then infeasibilities in your capacities would be signalled by positive values for these slacks at the optimal solution, rather than by a mysterious lack of feasibility in the linear program as a whole. Many modelers recommend the use of "soft constraints" of this kind in all models, since in reality many so-called constraints can be violated for a sufficiently high price. Modeling approaches that use such constraints have a number of names, most notably "goal programming" and "elastic programming".

Q6.3: "I want to know the specific constraints that contradict each other."

A: There can be many ways to answer this question, some of them potentially harder than solving the underlying LP would be (if it were feasible). One useful appoach is to apply auxiliary algorithms that look for small groups of constraints that can be considered to "cause" the infeasibility of the LP.

Several codes include methods for finding an "irreducible infeasible subset" (IIS) of constraints that has no feasible solution, but that becomes feasible if any one constraint is removed. John Chinneck has developed MINOS(IIS), an extended version of the MINOS package that finds an IIS when the constraints have no feasible solution; a demonstration copy is available for downloading. There are also IIS finders in CPLEX, LINDO, OSL, and Xpress-MP, as well as Premium Solver Platform for Excel.

Methods also exist for finding an "IIS cover" that has at least one constraint in every IIS. A minimal IIS cover is the smallest subset of constraints whose removal makes the linear program feasible. Further details and references for a variety of IIS topics are available in papers by John Chinneck.

The software system ANALYZE carries out various other analyses to detect structures typically associated with infeasibility. (A bibliography on optimization modeling systems collected by Harvey Greenberg of the University of Colorado at Denver contains cross-references to over 100 papers on the subject of model analysis.)

Q6.4: "I just want to know whether or not a feasible solution exists."

A: From the standpoint of computational complexity, finding out if an LP model has a feasible solution is essentially as hard as actually finding the optimal LP solution, within a factor of 2 on average, in terms of effort in the Simplex Method; plug your problem into a normal LP solver with any objective function you like, such as c=0. For MIP models, it's also difficult - if there exists no feasible solution, then you must go through the entire Branch and Bound procedure (or whatever algorithm you use) to prove this. There are no shortcuts in general, unless you know something useful about your model's structure (e.g., if you are solving some form of a transportation problem, you may be able to assure feasibility by checking that the sources add up to at least as great a number as the sum of the destinations).

Q6.5: "I have an LP, except it's got several objective functions."

A: If you have several objectives, then you may find that they cannot all be optimized by any one solution. Instead, you will need to look for a solution or solutions that achieve an acceptable tradeoff between objectives. Deciding what tradeoffs are "acceptable" is a topic of investigation in its own right. You may want to consult MCDM WorldScan, the newsletter of the International Society on Multiple Criteria Decision Making.

There are a few free software packages specifically for multiple objective linear programming, including:

  • ADBASE computes all efficient (i.e., nondominated) extreme points of a multiple objective linear program. It is available without charge for research and instructional purposes. If someone has a genuine need for such a code, they should send a request to: Ralph E. Steuer, Faculty of Management Science, Brooks Hall, University of Georgia, Athens, GA 30602-6255.
  • PROTASS, developed by Rafal Cytrycki (rcytrycki@computerland.pl) and Andrzej Dzik (andrzej.dzik@ekspert.szczecin.pl), provides two methods for multicriteria optimization: STEM and HSJ.
  • NIMBUS is an interactive multiobjective optimization system that has a Web interface.
Other approaches that have worked are:
  • Goal Programming (treat the objectives as constraints with costed slacks), or, almost equivalently, form a composite function from the given objective functions;
  • Pareto preference analysis (essentially brute force examination of all vertices);
  • Put your objective functions in priority order, optimize on one objective, then change it to a constraint fixed at the optimal value (perhaps subject to a small tolerance), and repeat with the next function.
There is a section on this whole topic in [Nemhauser]. [Schrage] has a chapter devoted to the subject. [Hwang] has also been recommended by a reader on Usenet. As a final piece of advice, if you can cast your model in terms of physical realities, or dollars and cents, sometimes the multiple objectives disappear! 8v)

Q6.6: "I have an LP that has large almost-independent matrix blocks that are linked by a few constraints. Can I take advantage of this?"

A: Possibly you could solve your LP faster by using some form of decomposition scheme; see for example section 6.2 in [Nemhauser] or chapter 26 of [Chvatal]. The commercial code OSL has features to assist in decomposing so-called Dantzig-Wolfe and staircase structures. With any other code, you'll have to create your own decomposition framework and then call an LP solver to handle the subproblems.

The folklore is that generally decomposition schemes take a long time to converge, so that they're slower than just solving the model as a whole -- although research continues. For now my advice, unless you are using OSL or your model is so huge that you can't buy enough memory to hold it, is to not bother decomposing it. It's probably more cost effective to upgrade your solver than to invest more time in programming (a good piece of advice in many situations).

Q6.7: "I am looking for an algorithm to compute the convex hull of a finite number of points in n-dimensional space."

A: A good place to start is the directory of Codes for Polytope and Polyhedron Algorithms at the Konrad-Zuse-Zentrum für Informationstechnik Berlin. It includes codes for convex hull computation, as well as for the opposite problem of generating all extreme points and extreme rays of a general convex polyhedron given by a system of linear inequalities. Here are further comments on some of these codes:

Ken Clarkson has written Hull, an ANSI C program that computes the convex hull of a point set in general dimension. The input is a list of points, and the output is a list of facets of the convex hull of the points, each facet presented as a list of its vertices.

Qhull computes convex hulls as well as Delaunay triangulations, halfspace intersections about a point, Voronoi diagrams, and related objects. It uses the "Beneath Beyond" method, described in [Edelsbrunner].

Komei Fukuda's cdd solves both the convex hull and vertex enumeration problems, using the Double Description Method of Motzkin et al. There are also a C++ version (cdd+) and a C-library version (cddlib) that can be compiled to run with both floating-point and GMP exact rational arithmetics.

David Avis's lrslib is a self-contained ANSI C implementation of the reverse search algorithm for vertex enumeration/convex hull problems, implemented as a callable library with a choice of three arithmetic packages. VE041, another implementation of this approach by Fukuda and Mizukoshi, is available in a Mathematica implementation.

See also the directory of computational geometry software compiled by Nina Amenta; and the archive of the former University of Minnesota Geometry Center website, which includes links to downloadable software.

Other algorithms for such problems are described in [Swart], [Seidel], and [Avis]. Such topics are said to be discussed in [Schrijver] (page 224), [Chvatal] (chapter 18), [Balinski], and [Mattheis] as well.

Q6.8: "Are there any parallel LP codes?"

A: Options for parallel computation of various kinds have become a common feature of software for linear and mixed-integer programming. Here are some examples:
  • IBM's OSL Parallel Extensions implement interior-point methods for linear programming and branch-and-bound methods for mixed-integer programming on homogeneous networks under Windows NT, AIX 4.x (on IBM RS/6000 and SP systems), HP-UX, Sun Solaris, and SGI IRIX, using the Parallel Virtual Machine (PVM) System version 3.4 for communication.
  • The CPLEX Parallel Solvers include simplex, barrier, and branch-and-bound solvers for linear and mixed-integer programming on a number of multiple-CPU systems.
  • Dash's Xpress-Parallel includes a branch-and-bound mixed-integer programming code designed to exploit both multi-processor computers and networks of workstations.
  • OOPS is an object-oriented parallel implementation of the interior point algorithm, developed by Jacek Gondzio (gondzio@maths.ed.ac.uk), Andreas Grothey and Robert Sarkissian. The code can exploit any special structure of the problem. It runs on all parallel computing platforms that support MPI.
Two parallel branch-cut-price frameworks are available to those who want to program specialized solvers for hard combinatorial problems that can be approached via integer programming:
  • Symphony requires the user to supply model-specific preprocessing and separation functions, while other components including search tree, cut pool, and communication management are handled internally. Source code is included for basic applications to traveling salesman and vehicle routing problems. The distributed version runs in any environment supported by the PVM message passing protocol, and can also be compiled for shared-memory architectures using any OpenMP compliant compiler.
  • BCP is a component of the COIN open source initiative.
Performance evaluations of parallel solvers must be interpreted with care. One common measurement is the "speedup" defined as the time for solution using a single processor divided by the time using multiple processors. A speedup close to the number of processors is ideal in some sense, but it is only a relative measure. The greatest speedups tend to be achieved by the least efficient codes, and especially by those that fail to take advantage of the sparsity (predominance of zero coefficients) in the constraints. For problems having thousands of constraints, a sparse single-processor code will tend to be faster than a non-sparse multiprocessor code running on current-day hardware.

Q6.9: "What software is there for Network models?"

A: In the context of linear programming, the term "network" is most often associated with the minimum-cost network flow problem. A network for this problem is viewed as a collection of nodes (or circles or locations) and arcs (or lines or routes) connecting selected pairs of nodes. Arcs carry a physical or conceptual flow of some kind, and may be directed (one-way) or undirected (two-way). Some nodes may be sources (permitting flow to enter the network) or sinks (permitting flow to leave).

The network linear programming problem is to minimize the (linear) total cost of flows along all arcs of a network, subject to conservation of flow at each node, and upper and/or lower bounds on the flow along each arc. This is a special case of the general linear programming problem. The transportation problem is an even more special case in which the network is bipartite: all arcs run from nodes in one subset to the nodes in a disjoint subset. A variety of other well-known network problems, including shortest path problems, maximum flow problems, and certain assignment problems, can also be modeled and solved as network linear programs. Details are presented in many books on linear programming and operations research.

Network linear programs can be solved 10 to 100 times faster than general linear programs of the same size, by use of specialized optimization algorithms. Some commercial LP solvers include a version of the network simplex method for this purpose. That method has the nice property that, if it is given integer flow data, it will return optimal flows that are integral. Integer network LPs can thus be solved efficiently without resort to complex integer programming software.

Unfortunately, many different network problems of practical interest do not have a formulation as a network LP. These include network LPs with additional linear "side constraints" (such as multicommodity flow problems) as well as problems of network routing and design that have completely different kinds of constraints. In principle, nearly all of these network problems can be modeled as integer programs. Some "easy" cases can be solved much more efficiently by specialized network algorithms, however, while other "hard" ones are so difficult that they require specialized methods that may or may not involve some integer programming. Contrary to many people's intuition, the statement of a hard problem may be only marginally more complicated than the statement of some easy problem.

A canonical example of a hard network problem is the "traveling salesman" problem of finding a shortest tour through a network that visits each node once. A canonical easy problem not obviously equivalent to a linear program is the "minimum spanning tree" problem to find a least-cost collection of arcs that connect all the nodes. But if instead you want to connect only some given subset of nodes (the "Steiner tree" problem) then you are faced with a hard problem. These and many other network problems are described in some of the references below.

Software for network optimization is thus in a much more fragmented state than is general-purpose software for linear programming. The following are some of the implementations that are available for downloading. Most are freely available for many purposes, but check their web pages or "readme" files for details.

  • ASSCT, an implementation of the Hungarian Method for the Assignment problem (#548 from Collected Algorithms of the ACM).

  • GIDEN, an interactive graphical environment for a variety of network problems and algorithms, available as a Java application or as an applet that can be executed through any Java-enabled Web browser. Further information is available by writing to giden@iems.nwu.edu.

  • MCF, a C implementation of primal and dual network simplex methods (from Andreas Loebel, loebel@zib.de), supported for Unix/Linux environments and Windows 95/98/NT (MS Visual C++ 6.0), and available for academic use free of charge.

  • Netflo, the Fortran network simplex code from [Kennington], and several codes for maximum matching and maximum flow problems (from DIMACS, help@dimacs.rutgers.edu)

  • PPRN, for single or multicommodity network flow problems having a linear or nonlinear objective function, optionally with linear side constraints, by Jordi Castro (jcastro@eio.upc.es)

  • RELAX-IV for minimum-cost network flows (by Dimitri Bertsekas, bertsekas@lids.mit.edu and Paul Tseng, tseng@math.washington.edu); also a C++ version of the RELAX-IV algorithm (at the Department of Computer Science, University of Pisa, frangio@di.unipi.it)
The following indexes may also be useful:
  • Network optimization codes in Fortran 77 and in C, compiled by Ernesto Martins (eqvm@mat.uc.pt)

  • The network optimization library, including codes for assignment, shortest path, minimum-cost flow, and maximum flow/minimum cut, by Andrew Goldberg (avg@research.nj.nec.com).

  • Optimization routines for networks and graphs in the listing of public-domain optimization codes maintained by Jiefeng Xu (Jiefeng.Xu@Colorado.edu).

  • Network optimization listings from the NEOS Guide.

Fortran code for the Assignment Problem and others can also be copied from[Burkard] and from [Martello].

Q6.10: "What software is there for the Traveling Salesman Problem?"

A: This famously hard problem -- known more briefly as the TSP -- is to find the shortest tour that visits a given collection of cities or locations of some kind. It is a hard (NP-complete) problem just like integer programming, but the obvious integer programming formulations of it are not especially useful in getting good solutions within a reasonable amount of time.

The TSP has attracted many of the best minds in the optimization field, and serves as a kind of test-bed for methods subsequently applied to more complex and practical problems. Methods have been explored both to give proved optimal solutions, and to give approximate but "good" solutions, with a number of codes being developed as a result:

  • Concorde has solved a number of the largest TSPs for which proved optimal solutions are known. It employs a polyhedral approach, which is to say that it relies on a range of exceedingly sophisticated linear programming constraints, in a framework that resembles integer programming branch-and-bound methods. The constraints are selectively generated as the solution process proceeds. The full C code is available without cost for research purposes.
  • Public domain code for the Asymmetric TSP (with travel between two cities significantly cheaper in one of the two directions) is available in TOMS routine #750, documented in [Carpaneto].
  • Code for a solver can be obtained via instructions in [Volgenant].
  • Chad Hurwitz (churritz@cts.com), offers a code called tsp_solve for heuristic and optimal solution, to those who email him.
  • [Syslo] contains some algorithms and Pascal code.
  • Numerical Recipes [Press] contains code that uses simulated annealing.
  • Stephan Mertens's TSP Algorithms in Action uses Java applets to illustrate some simple heursitics and compare them to optimal solutions, on 10-25 node problems.
  • Onno Waalewijn has constructed Java TSP applets exhibiting the behavior of different methods for heuristic and exhaustive search on various test problems.
For a bibliography, check the Integer Programming section of [Nemhauser], particularly the references with the names Groetschel and/or Padberg in them. Other good references are [Lawler] and [Reinelt]. Sophisticated and widely used heuristics for getting a "good" solution are described in the article by Lin and Kernighan in Operations Research 21 (1973) 498-516.

For practical purposes, the traveling salesman problem is only the simplest case of what are generally known as vehicle-routing problems. Thus commercial software packages for vehicle routing -- or more generally for "supply chain management" or "logistics" -- may have TSP routines buried somewhere within them. OR/MS Today published a detailed vehicle routing software survey in their August 2000 issue.

Q6.11: "What software is there for cutting or packing problems?"

A: The cutting (or "cutting stock") problem involves cutting large pieces of something into specified numbers of smaller pieces in the most economical way. In the one-dimensional version, cutting only reduces a single measurement, usually referred to as the length or width of the pieces; examples include cutting wide rolls of paper or sheet steel into specified numbers of smaller widths (also called the "roll trim" problem), and cutting long pieces of wood or pipe into specified specified numbers of shorter pieces. In the two-dimensional version, both a length and width may be specified for both the large pieces you start with and the smaller ones to be cut, or the shapes to be cut may be more general. The material may again be wood or metal, or paper or fabric, or even cookie dough.

The packing problem can be regarded as a kind of cutting in reverse, where the goal is to fill large spaces with specified smaller pieces in the most economical (or profitable) way. As with cutting, there are one-dimensional problems (also called knapsack problems) and two-dimensional problems, but there are also many three-dimensional cases such as arise in filling trucks or shipping containers. The size measure is not always length or width; it may be weight, for example.

Except for some very special cases, cutting and packing problems are hard (NP-complete) like integer programming or the TSP. The simpler one-dimensional instances are often not hard to solve in practice, however:

  • For knapsack problems, a good MIP solver applied to a straightforward integer-programming formulation can often be used. Specialized algorithms are said to be available in [Syslo] and [Martello].

  • For roll-trim problems, it is not hard to implement the Gilmore-Gomory procedure using a linear programming subroutine library or modeling language. The NEOS Guide's cutting stock case study introduces this procedure and lets you try small examples, while a good detailed presentation can be found in chapter 13 of [Chvatal]). This approach is based on a linear programming problem that decides how many rolls should be cut in each of several patterns, which means that fractional numbers of patterns may show up in the results. As long as most widths are needed in substantial quantities -- say, 10 or more -- an acceptable result can usually be found by rounding the fractions, or by solving one integer program at the end of the procedure.
One-dimensional problems that are subject to additional special requirements can be much harder, though; see [Haessler] for some examples in the roll-trim context. Higher-dimensional problems tend to be much harder still. As a result, there are a great variety of approximating heuristics and exact methods for solving various classes of cutting and packing problems. To find a useful solver for your particular problem may take some searching, and the best ones may be costly.

There has been a great deal written on cutting and packing topics, but it tends to be scattered. You might want to start by looking at the web page of the Special Interest Group on Cutting and Packing and the "application-oriented research bibliography" in [Sweeney]. A search through some of the INFORMS databases will also turn up a lot of references. In fact, even an ordinary web search engine can find you a lot on this topic; try searching on "cutting stock".

Among the commercial systems are CutRite, act/cut and act/square of Alma, Cutting Optimizer of Ardis, Cutter of Escape, Cube-IQ and PlanIQ of MagicLogic, PLUS1D and PLUS2D of Nirvana Technologies, Cut Planner of Pattern Systems, and SmartTRIM of Strategic Systems. Particular application areas, from paper to carpeting, have also given rise to their own specialized cutting-stock tools, which can often be found by a web search on the area of interest.

Q6.12: "What software is there for linear programming under uncertainty?"

A: See the Stochastic Programming Community Home Page for listings of software as well as conferences, tutorial materials, and publications. Instructions for joining a stochastic programming mailing list can also be found at this site.

[Thanks to Derek Holmes for the following text.] Your success solving a stochastic program depends greatly on the characteristics of your problem. The two broad classes of stochastic programming problems are recourse problems and chance-constrained (or probabilistically constrained) problems.

Recourse Problems are staged problems wherein one alteranates decisions with realizations of stochastic data. The objective is to minimize total expected costs of all decisions. The main sources of code (not necessarily public domain) depend on how the data is distributed and how many stages (decision points) are in the problem.

  • For discretely distributed multistage problems, a good package called MSLiP has been developed by Gus Gassmann (Horand.Gassmann@dal.ca). Also, for not huge discretely distributed problems, a deterministic equivalent can be formed which can be solved with a standard solver.
  • The most recent program for continuously distributed data is BRAIN, by K. Frauendorfer (frauendorfer@sgcl1.unisg.ch), written up in detail in the author's monograph ``Stochastic Two-Stage Programming'', Lecture Notes in Economics & Math. Systems #392 (Springer-Verlag).
  • IBM's Stochastic Solutions and Optimization Library Stochastic Extensions build on the OSL library to solve multistage stochastic programs.
  • POSTS is a small test set of recourse problems designed to highlight different qualities; it is meant as a common test bed for reporting the computational characteristics of state-of-the-art SLP algorithms and their implementations. Some test problems from a financial application have been posted by the Centre for Financial Research.

Chance-Constrained Programming (CCP) problems are not usually staged, and have a constraint of the form Pr( Ax <= b ) >= alpha. The solvability of CCP problems depends on the distribution of the data (A &/v b). I don't know of any public domain codes for CCP probs., but you can get an idea of how to approach the problem by reading Chapter 5 by Prof. A. Prekopa (prekopa@cancer.rutgers.edu) Y. Ermoliev, and R. J-B. Wets, eds., Numerical Techniques for Stochastic Optimization (Series in Comp. Math. 10, Springer-Verlag, 1988).

Both Springer Verlag texts mentioned above are good introductory references to Stochastic Programming. The Stochastic Programming E-Print Series collects many recent papers in the field.

Q6.13: "I need to do post-optimal analysis."

A: Many commercial LP codes have features to do this. Also called Ranging or Sensitivity Analysis, it gives information about how the coefficients in the problem could change without affecting the nature of the solution. Most LP textbooks, such as [Nemhauser], describe this. Unfortunately, all this theory applies only to LP.

For a MIP model with both integer and continuous variables, you could get a limited amount of information by fixing the integer variables at their optimal values, re-solving the model as an LP, and doing standard post-optimal analyses on the remaining continuous variables; but this tells you nothing about the integer variables, which presumably are the ones of interest. Another MIP approach would be to choose the coefficients of your model that are of the most interest, and generate "scenarios" using values within a stated range created by a random number generator. Perhaps five or ten scenarios would be sufficient; you would solve each of them, and by some means compare, contrast, or average the answers that are obtained. Noting patterns in the solutions, for instance, may give you an idea of what solutions might be most stable. A third approach would be to consider a goal-programming formulation; perhaps your desire to see post-optimal analysis is an indication that some important aspect is missing from your model.

Q6.14: "Do LP codes require a starting vertex?"

A: No. Any reasonable simplex-based LP code can construct a starting vertex (or "basic solution") for you, given the constraints and the objective function. Most codes go through a so-called two-phase procedure, wherein they first look for a feasible solution, and then work on getting an optimal solution. (The two phases are often grandly titled phase I and phase II.) The first phase, if properly written, can begin at any infeasible basic solution, and commercial codes typically have a so-called crash routine to pick a reasonable start. It is generally not worth going to a lot of trouble to look for a better starting basic solution, unless you have already solved a similar problem. The optimal basis (the list of basic variables) from a similar problem often does help the simplex solver to get good start that substantially reduces the number of iterations to optimality. Commercial codes generally provide for saving an optimal basis and reusing it in this way, but free codes may not.

Interior-point methods for LP have entirely different requirements for a good starting point. Any reasonable interior-point-based LP code has its own routines for picking a starting point that is "well-centered" away from the constraints, in an appropriate sense. There is not much advantage to supplying your own starting point of any kind -- at least, not at the current state of the art -- and some codes do not even provide an option for giving a starting point.

Q6.15: "How can I combat cycling in the Simplex algorithm?"

A: Cycling is the condition that occurs when the Simplex method gets "stuck" and finds itself repeating the same vertices over and over. While this specific behavior is rather rare in practice, it is quite common for the algorithm to reach a point where it temporarily stops making forward progress in terms of improvement in the objective function; this is termed "stalling", or more loosely known as "degeneracy" since it is caused by one or more basic variables taking on the value of a lower or upper bound. In most cases, the algorithm will work through this nest of coincident vertices, then resume making tangible progress. However, in extreme cases the degeneracy is so bad that to all intents and purposes it can be considered cycling.

The simplest answer to the problem of degeneracy/cycling is often to "get a better optimizer", i.e. one with stronger pricing algorithms, and a better selection of features. However, obviously that is not always an option (money!), and even the best LP codes can run into degeneracy on certain models. Besides, they say it's a poor workman who blames his tools.

So, when one cannot change the optimizer, it's expedient to change the model. Not drastically, of course, but a little "noise" can usually help to break the ties that occur during the Simplex method. A procedure that can work nicely is to add, to the values in the RHS, random values roughly six orders of magnitude smaller. Depending on your model's formulation, such a perturbation may not even seriously affect the quality of the solution values. However, if you want to switch back to the original formulation, the final solution basis for the perturbed model should be a useful starting point for a "cleanup" optimization phase. (Depending on the code you are using, this may take some ingenuity to do, however.)

Another helpful tactic: if your optimization code has more than one solution algorithm, you can alternate among them. When one algorithm gets stuck, begin again with another algorithm, using the most recent basis as a starting point. For instance, alternating between a primal and a dual method can move the solution away from a nasty point of degeneracy. Using partial pricing can be a useful tactic against true cycling, as it tends to reorder the columns. And of course Interior Point algorithms are much less affected by (though not totally immune to) degeneracy. Unfortunately, the optimizers richest in alternate algorithms and features also tend to be least prone to problems with degeneracy in the first place.

Q7. "What references are there in this field?"

A: What follows is an idiosyncratic list, based on my own preferences, various people's recommendations on the net, and recent announcements of new publications. It is divided into the following categories:

    • General reference
    • Textbooks
    • Presentations of LP modeling systems
    • Books containing source code
    • Additional books
    • Periodicals
    • Articles of interest

    • See also the listings of online sources of information following.
I have not reviewed everything listed.

General reference

  • Nemhauser, Rinnooy Kan, & Todd, eds, Optimization: Handbooks in Operations Research and Management Science, Volume 1, North-Holland, 1989. (Very broad-reaching, with large bibliography; a good reference, and worth checking first. Expensive, though, and tough reading for beginners.)

Textbooks

Regarding the common question of the choice of textbook for a college LP course, it's difficult to give a blanket answer because of the variety of topics that can be emphasized: brief overview of algorithms, deeper study of algorithms, theorems and proofs, complexity theory, efficient linear algebra, modeling techniques, solution analysis, and so on. A small and unscientific poll of ORCS-L mailing list readers in 1993 uncovered a consensus that [Chvatal] was in most ways pretty good, at least for an algorithmically oriented class; of course, some new candidate texts have been published in the meantime. For a class in modeling, a book about a commercial code would be useful (LINDO, AMPL, GAMS were suggested), especially if the students are going to use such a code; and many are fond of [Williams], which presents a considerable variety of modeling examples.

  • Bazaraa, Jarvis and Sherali. Linear Programming and Network Flows. Grad level.
  • Bertsimas, Dimitris and Tsitsiklis, John, Introduction to Linear Optimization. Athena Scientific, 1997 (ISBN 1-886529-19-1). Graduate-level text on linear programming, network flows, and discrete optimization.
  • Chvatal, Linear Programming, Freeman, 1983. Undergrad or grad.
  • Cook, W.J., Cunningham, W.H., Pulleyblank, W.R. and Schrijver, A. Combinatorial Optimization, Wiley Interscience, 1997.
  • Daellenbach, Hans G., A User's Guide to Linear Programming. Good for engineers. Currently out of print.
  • Fang, S.-C. & Puthenpura, S., Linear Optimization and Extensions: Theory and Algorithms. Prentice Hall, 1993.
  • Dantzig, George B., Linear Programming and Extensions, Princeton University Press, 1963.. The most widely cited early textbook in the field.
  • Dantzig, George B. and Thapa, Mukund N., Linear Programming 1: Introduction, Springer Verlag, 1997..
  • Gass, Saul I., Linear Programming: Methods and Applications, 5th edition. International Thomson Publishing, 1985.. The author received the 1997 INFORMS Expository Writing Award.
  • Ignizio, J.P. & Cavalier, T.M., Linear Programming, Prentice Hall, 1994. Covers usual LP topics, plus interior point, multi-objective and heuristic techniques.
  • Luenberger, Introduction to Linear and Nonlinear Programming, Addison Wesley, 1984. Updated version of an old standby. The author received the 1999 INFORMS Expository Writing Award.
  • Murtagh, B., Advanced Linear Programming: Computation and Practice. McGraw-Hill, 1981. Good one after you've read an introductory text. Currently out of print.
  • Murty, K., Linear and Combinatorial Programming.
  • Nash, S., and Sofer, A., Linear and Nonlinear Programming, McGraw-Hill, 1996.
  • Nazareth, J.L., Computer Solution of Linear Programs, Oxford University Press, New York and Oxford, 1987.
  • Nemhauser, G.L. and Wolsey, L.A., Integer and Combinatorial Optimization, Wiley Interscience, 1988. An advanced text that covers many theortical and computational topics.
  • Nering, E.D. & Tucker, A.W., Linear Programs and Related Problems, Academic Press, 1993.
  • Roos, Terlaky and Vial, Theory and Algorithms for Linear Optimization: An Interior Point Approach. John Wiley, Chichester, 1997
  • Saigal, R., Linear Programming: A Modern Integrated Analysis, Kluwer Academic Publishers, 1995.
  • Schrijver, A., Theory of Linear and Integer Programming, Wiley, 1986. Advanced.
  • Taha, H., Operations Research: An Introduction, 1987.
  • Thie, P.R., An Introduction to Linear Programming and Game Theory, Wiley, 1988.
  • Vanderbei, Robert J., Linear Programming: Foundations and Extensions. Kluwer Academic Publishers, 1996. Balanced coverage of simplex and interior-point methods. Source code available on-line for all algorithms presented.
  • Williams, H.P., Model Building in Mathematical Programming, Wiley 1993, 3rd edition. Little on algorithms, but excellent for learning what makes a good model.
  • Wright, Stephen J., Primal-Dual Interior-Point Methods. SIAM Publications, 1997. Covers theoretical, practical and computational aspects of the most important and useful class of interior-point algorithms. The web page for this book contains current information on interior-point codes for linear programming, including links to their websites.
  • Ye, Yinyu, Interior Point Algorithms: Theory and Analysis. Wiley, 1997.

Presentations of LP modeling systems (usable as texts for some classes)

Free software for problems of limited size is available to accompany most of these books. See the associated software websites for details.
  • Bisschop and Roelofs, AIMMS Optimization Modeling and AIMMS User's Guide, Paragon Decision Technology, 1999.
  • Brooke, Kendrick & Meeraus, GAMS: A Users' Guide, The Scientific Press/Duxbury Press, 1988.
  • Fourer, Gay & Kernighan, AMPL: A Modeling Language for Mathematical Programming (2nd edition), Duxbury Press, 2002.
  • Greenberg, H.J., Modeling by Object-Driven Linear Elemental Relations: A User's Guide for MODLER, Kluwer Academic Publishers, 1993.
  • Guéret, C., Prins, C. and Sevaux, M., Applications of Optimization with Xpress-MP (translated and revised by Susanne Heipcke), Dash Optimization, 2002.
  • Schrage, L., Optimization Modeling with LINDO, 5th edition, and Optimization Modeling with LINGO, 5th edition, LINDO Systems.

Books containing source code

  • Best and Ritter, Linear Programming: active set analysis and computer programs, Prentice-Hall, 1985.
  • Bertsekas, D.P., Linear Network Optimization: Algorithms and Codes, MIT Press, 1991.
  • Bunday and Garside, Linear Programming in Pascal, Edward Arnold Publishers, 1987.
  • Bunday, Linear Programming in Basic (presumably the same publisher).
  • Burkard and Derigs, Springer Verlag Lecture Notes in Math Systems #184 (the Assignment Problem and others).
  • Kennington & Helgason, Algorithms for Network Programming, Wiley, 1980. (A special case of LP; contains Fortran source code.)
  • Lau, H.T., A Numerical Library in C for Scientists and Engineers, 1994, CRC Press. (Contains a section on optimization.)
  • Martello and Toth, Knapsack Problems: Algorithms and Computer Implementations, Wiley, 1990. (Contains Fortran code, comes with a disk - also covers Assignment Problem.)
  • Press, Flannery, Teukolsky & Vetterling, Numerical Recipes, Cambridge, 1986. (Comment: use their LP code with care.)
  • Syslo, Deo & Kowalik, Discrete Optimization Algorithms with Pascal Programs, Prentice-Hall (1983). (Contains code for 28 algorithms such as Revised Simplex, MIP, networks.)

Additional books

  • Ahuja, Magnanti and Orlin, Network Flows, Prentice Hall, 1993.
  • Beasley, ed., Advances in Linear and Integer Programming. Oxford University Press, 1996. Each chapter is a self-contained essay on one aspect of the subject.
  • Bertsekas, Network Optimization: Continuous and Discrete Models, Athena Scientific, 1998.
  • Chandru and Hooker, Optimization Methods for Logical Inference, Wiley-Interscience, 1999.
  • Edelsbrunner, Algorithms in Combinatorial Geometry, Springer Verlag, 1987.
  • Forsythe, Malcolm & Moler, Computer Methods for Mathematical Computations, Prentice-Hall.
  • Gill, Murray and Wright, Numerical Linear Algebra and Optimization, Addison-Wesley, 1991.
  • Greenberg, A Computer-Assisted Analysis System for Mathematical Programming Models and Solutions: A User's Guide for ANALYZE, Kluwer Academic Publishers, 1993.
  • Hooker, Logic-Based Methods for Optimization, Wiley-Interscience, 2000.
  • Hwang and Yoon, Multiple Attribute Decision Making: An Introduction, Sage, 1995.
  • Lawler, Lenstra, Rinnooy Kan and Shmoys, The Traveling Salesman Problem: A Guided Tour of Combinatorial Optimization, Wiley, 1985.
  • Moré and Wright, Optimization Software Guide, SIAM Publications, 1993. See also the NEOS Guide to Optimization Software.
  • Murty, Network Programming, Prentice Hall, 1992.
  • Papadimitriou and Steiglitz, Combinatorial Optimization: Algorithms and Complexity, Dover, 1998. Also contains a discussion of complexity of simplex method.
  • Reeves, ed., Modern Heuristic Techniques for Combinatorial Problems, Halsted Press (Wiley), 1993. Contains chapters on tabu search, simulated annealing, genetic algorithms, neural nets, and Lagrangian relaxation.
  • Reinelt, The Traveling Salesman: Computational Solutions for TSP Applications, Springer-Verlag, 1994.
  • Rockafellar, Network Flows and Monotropic Optimization, Athena Scientific, 1984, reprinted 1998.

Periodicals

  • Publications of INFORMS, the principal operations research and management science society in the United States:
    • OR/MS Today, the bimonthly newsletter of INFORMS, includes case studies, software reviews, and software surveys relevant to linear programming. It also has the most extensive collection of advertisements for commercial linear programming (and other optimization) software packages.
    • Interfaces frequently publishes interesting accounts of applications that make use of linear programming.
    • INFORMS Journal on Computing includes some articles on the computational aspects of linear programming algorithms.
    • Interactive Transactions of OR/MS contains a number of useful surveys and bibliographies relevant to linear programming.
  • Publications of the Mathematical Programming Society:
    • Mathematical Programming contains technical articles on theory and computation.
    • Optima, the Society's newsletter, incorporates survey articles and book reviews.
  • Publications of SIAM, the principal applied mathematics society in the United States:
    • SIAM Journal on Optimization contains technical articles, mainly of a mathematical nature.
    • SIAG/OPT Newsletter, from the SIAM Activity Group on Optimization.
  • Publisher-sponsored technical journals focusing on optimization topics:
    • Computational Optimization and Applications (and allied Software Forum)
    • Constraints
    • Journal of Optimization Theory and Applications
    • Optimization Methods and Software

Articles of interest

  • Avis & Fukuda, "A Pivoting Algorithm for Convex Hulls and Vertex Enumeration of Arrangements and Polyhedra", Discrete and Computational Geometry, 8 (1992), 295--313.
  • Balas, E. and Martin, C., "Pivot And Complement: A Heuristic For 0-1 Programming Problems", Management Science, 1980, Vol 26, pp 86-96.
  • Balinski, M.L., "An Algorithm for Finding all Vertices of Convex Polyhedral Sets", SIAM J. 9, 1, 1961.
  • Carpaneto, Dell'amico & Toth, "A Branch-and-bound Algorithm for Large Scale Asymmetric Travelling Salesman Problems," ACM Transactions on Mathematical Software 21 (1995) 410-415.
  • Haessler, "Selection and Design of Heuristic Procedures for Solving Roll Trim Problems," Management Science 12 (1988) 1460-1471.
  • Lustig, Marsten and Shanno, "Interior Point Methods for Linear Programming: Computational State of the Art", ORSA Journal on Computing, Vol. 6, No. 1, Winter 1994, pp. 1-14. Followed by commentary articles, and a rejoinder by the authors.
  • Marsten, Subramanian, Shanno, Saltzman and Lustig, "Interior point methods for linear programming: Just call Newton, Lagrange, and Fiacco and McCormick!" Interfaces, Vol. 20, No. 4 (1990) pp. 105-116.
  • Mattheis and Rubin, "A Survey and Comparison of Methods for Finding All Vertices of Convex Polyhedral Sets", Mathematics of Operations Research, vol. 5 no. 2 1980, pp. 167-185.
  • Seidel, "Constructing Higher-Dimensional Convex Hulls at Logarithmic Cost per Face", 1986, 18th ACM STOC, 404--413.
  • Smale, Stephen, "On the Average Number of Steps in the Simplex Method of Linear Programming", Math Programming 27 (1983), 241-262.
  • Swart, "Finding the Convex Hull Facet by Facet", Journal of Algorithms, 6 (1985), 17--48.
  • P.E. Sweeney and E.R. Paternoster, "Cutting and Packing Problems: A Categorized, Application-Oriented Research Bibliography," Journal of the Operational Research Society 43 (1992) 691-706.
  • Volgenant, A., Symmetric TSPs, European Journal of Operations Research, 49 (1990) 153-154.

  • A special issue of Optimization Methods and Software (volumes 11-12, December 1999) is devoted to interior-point methods and includes a supplementary CD with related sofware.

Q8. "What's available online in this field?"

A: Though traditional publications may remain the best places to learn about optimization theory and algorithms, the Web is the place to go for optimization software. In addition to numerous sources of optimization codes and optimization-related home pages, the Web is increasingly a source of optimization services that let you try out solvers without having to install them on your own equipment.

On-line sources of optimization services

The following websites offer, in some sense, to run your linear or integer programming problem and return a result. Check their home pages for details, which vary considerably. (See also the analogous listing in the NLP FAQ.)
  • AMPL. A convenient interface supports experimentation with the AMPL modeling language on test problems up to 300 variables and 300 constraints + objectives. Users can request any example from the AMPL book, or provide their own model and data files. There is a choice among 8 solvers for linear and integer programming (as well as nonlinear optimization and complementarity problems).

  • DecisionNet. Provides access to "a distributed collection of decision technologies," including linear programming, "that are made available for execution over the World Wide Web. These technologies are developed and maintained locally by their providers. DecisionNet contains technology metainformation necessary to guide consumers in search, selection, and execution of these technologies." Facilities for submitting problems in popular modeling language formats are currently being tested.

  • GIDEN. An interactive graphical environment for a variety of network optimization problems and algorithms. It is written in Java, so you can try it out through any Java-enabled Web browser.

  • Kestrel. This interface permits varied linear, integer, and nonlinear optimization problems to be sent directly from the AMPL and GAMS modeling systems to the NEOS Server. Results are sent back to AMPL or GAMS, where they may be displayed and analyzed just as if the solving had been done locally.

  • LPL. Small problems modeled in the LPL language can be submitted by typing or pasting into a web form. Results are returned on a subsequent web page.

  • MILP by Dmitry V. Golovashkin. Small-scale mixed-integer programs in a simple algebraic format are solved through a web form interface.

  • Network-Enabled Optimization System (NEOS) Server. Offers access to several dozen solvers for linear and integer programming as well as various nonlinear optimization problems.
    • Linear and integer programs are accepted in MPS format or in modeling languages such as AMPL and GAMS.
    • Submissions may be made by sending e-mail, by submitting names of local files through a Web form, or via a socket-based submission tool available in Java and Unix tcl/tk versions.

  • Numerische Mathematik Interaktiv includes teaching tools for various linear and nonlinear optimization methods (in German).

  • Optimisation Service Provision (OSP) is a prototype for a web-based service that offers varied modeling tools, solvers, and data management facilities. It presents a sophisticated interface and currently offers the only web access to the CPLEX and OSL solvers.

  • RIOT. The Remote Interactive Optimization Testbed at Berkeley's Industrial Engineering and Operations Research Department, offering online demonstrations of numerous optimization tools and applications.
A more extensive survey appears in Optimization as an Internet Resource by R. Fourer and J.-P. Goux, in the INFORMS journal Interfaces, volume 31, number 2 (2001).

Online sources of optimization software

The Netlib Repository contains a huge collection of mathematical software, papers, and databases, maintained at the University of Tennessee, Knoxville and Oak Ridge National Laboratory. There are also mirror sites in the United States, Norway, the United Kingdom, and other locations. Once you know what you want from Netlib, you may may prefer to make requests by anonymous ftp or e-mail; alternative access methods and many other relevant matters are explained in the Netlib FAQ.

Many optimization packages are distributed from their own Web sites. Numerous links to these sites are provided elsewhere in this FAQ, especially under the Where is there good software? question.

Online sources of optimization information

Varied general sources on optimization include information on linear and integer programming. They include:
  • The Optimization Online repository of papers and reports on optimization. Contributions are accepted from anyone working in the field, and are moderated by a team of volunteer coordinators; you can subscribe to a monthly digest that summarizes reports recently received.

  • The e-Optimization.community, a web meeting place for optimization users and developers, featuring a who's who of people in optimization as well as listings of optimization resources, applications, vendors, case studies, and news.

  • The NEOS Guide of the Argonne/Northwestern Optimization Technology Center.

  • The Decision Tree for Optimization Software by Hans Mittelmann and P. Spellucci, and the related Benchmarks for Optimization Software.

  • Harvey Greenberg's Mathematical Programming Glossary and Bibliography for the Development of An Intelligent Mathematical Programming System.

  • Listings of optimization software and related information at the Center for Advanced Modeling and Optimization.
More specialized sources include:
  • Interior-Point Methods Online, containing most new reports in the area of interior-point methods that have appeared since December 1994. Abstracts for all reports are available, as are links to postscript source for most reports; a mailing list carries announcements of new papers, conferences, software, and special journal issues relevant to interior-point methods.

  • A bibliography of books and papers on Interior-Point methods (including many older ones) compiled by Eberhard Kranich.

  • A resource website in semidefinite programming maintained by Christoph Helmberg, and a semidefinite programming bibliography by Henry Wolkowicz.

  • An extensive bibliography for stochastic programming and a specialized one for stochastic integer programming, compiled by Maarten van der Vlerk.
The following sites cover operations research and management science more generally, but have a large amount of content relevant to linear programming and other optimization problems:
  • INFORMS Online, the website of the Institute for Operations Research and the Management Sciences, including:

    • Searchable databases of INFORMS conference presentations going back to 1990, and publications in operations research back to 1982.
    • The INFORMS OR/MS Resource Collection (formerly "Michael Trick's Operations Research Page").

  • WORMS (World-Wide-Web for Operations Research and Management Science) at the Department of Mathematics and Statistics, University of Melbourne, Australia.

Q9. "Who maintains this FAQ list?"

A: This list is maintained by Robert Fourer (4er@iems.nwu.edu) and the Optimization Technology Center of Northwestern University and Argonne National Laboratory.

This article is Copyright © 2000 by Robert Fourer. It may be freely redistributed in its entirety provided that this copyright notice is not removed. It may not be sold for profit or incorporated in commercial documents without the written permission of the copyright holder. Permission is expressly granted for this document to be made available for file transfer from installations offering unrestricted anonymous file transfer on the Internet.

The material in this document does not reflect any official position taken by any organization. While all information in this article is believed to be correct at the time of writing, it is provided "as is" with no warranty implied.

If you wish to cite this FAQ formally -- this may seem strange, but it does come up -- you may use:

Robert Fourer (4er@iems.nwu.edu), "Linear Programming Frequently Asked Questions," Optimization Technology Center of Northwestern University and Argonne National Laboratory, http://www-unix.mcs.anl.gov/otc/Guide/faq/ LinearProgrammingFAQ.htm (2000).
Suggestions, corrections, topics you'd like to see covered, and additional material are all solicited. Send them to 4er@iems.nwu.edu.

END linear-programming-faq


GNU LESSER GENERAL PUBLIC LICENSE

               Version 2.1, February 1999

 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]

                Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

  This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.

  When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

  To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

  To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

  Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

  Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

  When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

  We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

  For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard.  To achieve this, non-free programs must be
allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

  In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

  Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

          GNU LESSER GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.

  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.

  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

  6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Use a suitable shared library mechanism for linking with the
    Library.  A suitable mechanism is one that (1) uses at run time a
    copy of the library already present on the user's computer system,
    rather than copying library functions into the executable, and (2)
    will operate properly with a modified version of the library, if
    the user installs one, as long as the modified version is
    interface-compatible with the version that the work was made with.

    c) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    d) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    e) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.

  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

                NO WARRANTY

  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

             END OF TERMS AND CONDITIONS

           How to Apply These Terms to Your New Libraries

  If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change.  You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).

  To apply these terms, attach the following notices to the library.  It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.

    <one line to give the library's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  library `Frob' (a library for tweaking knobs) written by James Random Hacker.

  <signature of Ty Coon>, 1 April 1990
  Ty Coon, President of Vice

That's all there is to it!