fifr::lpmod  fifr::lpmod C++ modelling library

Introduction

fifr::lpmod is a simple generic C++ interface for creating and solving linear programs. The library provides a simple abstraction to create models with variables and constraints in a solver independent way. The models can than be passed to various solvers like Cplex or Gurobi.

Documentation

The (very sparse) API documentation can found here.

Download

Latest development version: lpmod-trunk.tar.gz

The project lives in a fossil repository. In order to clone the repository, execute the following commands:

fossil clone http://fifr.spdns.de/cpp-lpmod path/to/cpp-lpmod.fossil
mkdir path/to/lpmod-sources
cd path/to/lpmod-sources
fossil open path/to/cpp-lpmod.fossil

Installation

fifr::lpmod comes with a cmake build script. The library can be compiled into a static library using

mkdir path/to/build-directory
cd path/to/build-directory
cmake path/to/lpmod-sources
make

This creates a (static) callable library in path/to/build-directory, usually called libfifrlpmod.a on Linux systems. Note that this library contains only solver independent parts.

The library can be installed on your system using

sudo make install

afterwards (usually you have to run this command as root because it installs the library to a system directory). This command copies the header files and the necessary cmake configuration files to /usr/local (by default). The path can be changed by setting the CMAKE_INSTALL_PREFIX variable when running cmake

cmake -DCMAKE_INSTALL_PREFIX=/installation/path

Note that fifr::lpmod requires C++17.

Cplex

Cplex is looked for in the path set by the environment variable CPLEX_HOME. The variable can also be specified when calling cmake:

env CPLEX_HOME=/path/to/cplex cmake

If Cplex has been found then the CplexSolver class is compiled to its own library libfifrlpmod-cpx.a.

Gurobi

Gurobi is looked for in the path set by the environment variable GUROBI_HOME. (This variable should be set in a proper Gurobi installation). The variable can also be specified when calling cmake:

env GUROBI_HOME=/path/to/gurobi cmake

If Gurobi has been found then the GurobiSolver class is compiled to its own library libfifrlpmod-grb.a.

Using fifr::lpmod in your own project

There are several ways to use fifr::lpmod in your own project depending on whether you use cmake or not. If you are unsure but you use cmake we suggest the cmake subdirectory approach below.

As a cmake package

If you installed fifr::lpmod to a system directory (using the approach described above), you can instruct cmake to look for the library. The following example can be used in your CMakeLists.txt to find fifr::lpmod and link against Cplex or Gurobi if they could be found. If Cplex or Gurobi are mandatory for your project, remove OPTIONAL_COMPONENTS.

find_package(FifrLPmod REQUIRED OPTIONAL_COMPONENTS Cplex Gurobi)
target_link_libraries(${TARGET} Fifr::LPmod)

if (FifrLPmod_Cplex_FOUND)
  target_compile_definitions(${TARGET} PRIVATE -DHAVE_CPLEX=1)
  target_link_libraries(${TARGET} Fifr::LPmod::Cplex)
endif ()

if (FifrLPmod_Gurobi_FOUND)
  target_compile_definitions(${TARGET} PRIVATE -DHAVE_GUROBI=1)
  target_link_libraries(${TARGET} Fifr::LPmod::Gurobi)
endif ()

Note that these script will automatically add the necessary linking parameters for Cplex and Gurobi as well.

As a cmake package installed to a non-standard location

Do the same as above but ensure that the path to your non-standard location is contained in the environment variable CMAKE_PREFIX_PATH before you run cmake on your project:

export CMAKE_PREFIX_PATH=/non-standard/installation/path
cmake
...

Alternatively you can specify the path as cmake define

cmake -DCMAKE_PREFIX_PATH=/non-standard/installation/path
...

As a cmake package without installation

This is similar to the previous approach but instead of installing fifr::lpmod to some non-standard location you can use the build directory directly. So do not execute make install but add the build directory to CMAKE_PREFIX_PATH:

export CMAKE_PREFIX_PATH=path/to/fifrlpmod/build-directory
cmake
...

or

cmake -DCMAKE_PREFIX_PATH=path/to/fifrlpmod/build-directory
...

As a cmake subdirectory

This is probably the easiest way to create a cmake buildable project that can easily be deployed to other systems, because it does not need any fumbling with the installation of fifr::lpmod itself. Simply copy the whole fifr::lpmod source tree to a subdirectory of your project or checkout its fossil repository to a subdirectory:

mkdir -p 3rdparty/lpmod
cd 3rdparty/lpmod
fossil open --nested path/to/lpmod/fossil/repo

Then add the same lines as above to your CMakeLists.txt but replace the find_package command with an add_subdirectory command:

add_subdirectory(3rdparty/lpmod)
target_link_libraries(${TARGET} Fifr::LPmod)

if (FifrLPmod_Cplex_FOUND)
  target_compile_definitions(${TARGET} PRIVATE -DHAVE_CPLEX=1)
  target_link_libraries(${TARGET} Fifr::LPmod::Cplex)
endif ()

if (FifrLPmod_Gurobi_FOUND)
  target_compile_definitions(${TARGET} PRIVATE -DHAVE_GUROBI=1)
  target_link_libraries(${TARGET} Fifr::LPmod::Gurobi)
endif ()

If you configure your project then fifr::lpmod is configured as well.

As part of your own source tree

You can copy the src/fifr/ subdirectory to your own source tree

cp -r /path/to/fifr/lpmod/src/fifr src/

and add that source tree as subdirectory

add_subdirectory(src/fifr/lpmod)
target_link_libraries(${TARGET} Fifr::LPmod)

if (FifrLPmod_Cplex_FOUND)
  target_compile_definitions(${TARGET} PRIVATE -DHAVE_CPLEX=1)
  target_link_libraries(${TARGET} Fifr::LPmod::Cplex)
endif ()

if (FifrLPmod_Gurobi_FOUND)
  target_compile_definitions(${TARGET} PRIVATE -DHAVE_GUROBI=1)
  target_link_libraries(${TARGET} Fifr::LPmod::Gurobi)
endif ()

The difference to the previous approach is that fifr::lpmod's source files are now part of your application's source tree and not contained in its own fossil source directory. So following updates of fifr::lpmod requires manually copying changes source files again.

Link manually

Of course, you can manually link against fifr::lpmod. Simply add the corresponding linker flags to your compiler, but do not forget that you need to links against the solvers, too:

g++ -o myapp myapp.cpp -L/path/to/fifr/lpmod \
    -lfifrlpmod -lfifrlpmod-cpx -lfifrlpmod-grb \
    -Lpath/to/gurobi -lgurobi100 \
    -Lpath/to/cplex -lcplex \
    -ldl -lpthread -lm