-
General Information
- About
- License
- Questions and Answers
-
Building
- Building Cbc for ScaiIlp
- Optional: Building pthreads-win32 with VS 2022
- Building HiGHS with VS 2022
- Building SCIP with VS 2022
- Building ScaiIlp with VS 2022
-
Code Structure
- Projects in Visual Studio
- Usage
- Class Hierarchy
- Adding a New Solver
ScaiIlp can provide an interface to different ILP solvers.
Currently supported solvers are:
- Cbc
- HiGHS
- SCIP
- Gurobi
ScaiIlp is licensed under the terms of the Eclipse Public License (EPL), version 1.0
See https://opensource.org/licenses/EPL-1.0 or license.txt
A: There are two.
- Provide a unified and simplified interface for different ILP solvers.
- Allow dynamic linking without having to modify the sources/makefiles of solvers that do not support this natively.
A: On the one hand, Osi is quite a complex interface. As it spreads over several files with several classes, it is difficult to use as the interface of a DLL. On the other hand, some functions that we needed are missing in Osi.
A: IlpSolverStub is a wrapper for IlpSolverCbc. It insulates it from your program. If the solver crashes, your program can survive this. On any crashes we know of, IlpSolverStub does silently the same as if the solver just found no solution. On unknown crashes and unknown problems, IlpSolverStub throws an exception, which can be caught in your code.
A: If you don't experience solver crashes, you can avoid some overhead by using IlpSolverCbc directly.
-
Download the coinbrew script from https://coin-or.github.io/coinbrew/
-
Follow the instructions described in https://coin-or.github.io/user_introduction#windows-1 to compile it to your specifications.
-
We require the configuration options
- --enable-shared
- ADD_CXXFLAGS=-D_ITERATOR_DEBUG_LEVEL=0
-
If Cbc should support multi-threading via pthreads (see section 2.2), you also need to provide the configuration options
- --enable-cbc-parallel
- --with-pthreadsw32-lib=path_to_pthreads_lib
- --with-pthreadsw32-incdir=path_to_pthreads_include
-
Download pthreads-win32 from the Pthreads-Win32 project
- Download: ftp://sourceware.org/pub/pthreads-win32/
-
Open pthread.dsw with VS 2022 and let it upgrade the project.
-
When you want to compile for 64 bit platforms:
- Choose "Build" -> "Configuration Manager".
- In the "Active solution platform" dropdown menu, select "New" and choose "x64" as new platform.
- Make sure that "Copy settings from: x86" is chosen and "Create new project platforms" is checked.
-
Choose "Build" -> "Configuration Manager". Choose the "Active solution platform" depending on your needs:
- Choose "x86" when compiling for 32 bit platforms
- Choose "x64" when compiling for 64 bit platforms
-
Right-click onto the project "pthread" in the Solution Explorer and choose
-
"Properties" -> "Configuration Properties".
-
Select "All Configurations" and "All Platforms" and use the following settings:
- General / Output Directory:
$(SolutionDir)$(PlatformTarget)-$(PlatformToolset)-$(Configuration)\
- General / Intermediate Directory:
$(PlatformTarget)-$(PlatformToolset)-$(Configuration)\
- General / Windows SDK Version: Your current SDK
- General / Platform Toolset:
Visual Studio 2022 (v143)
- C/C++ / General / Debug Information Format:
Program Database (/Zi)
- C/C++ / Preprocessor / Preprocessor Definitions: prepend
_ITERATOR_DEBUG_LEVEL=0;_TIMESPEC_DEFINED;
- C/C++ / Precompiled Headers / Precompiled Header Output File:
$(IntDir)pthread.pch
- C/C++ / Output Files / ASM List Location:
$(IntDir)
- C/C++ / Output Files / Object File Name:
$(IntDir)
- C/C++ / Output Files / Program Database File Name:
$(IntDir)
- Linker / General / Output File:
$(OutDir)$(TargetName)$(TargetExt)
- Linker / Debugging / Generate Debug Info:
Generate Debug Information (/DEBUG)
- Linker / Advanced / Import Library:
$(OutDir)$(TargetName).lib
- General / Output Directory:
-
For faster compilation, you can additionally use the following settings (set none or both):
- C/C++ / General / Multi-processor Compilation:
Yes (/MP)
- C/C++ / Code Generation / Enable Minimal Rebuild:
No (/Gm-)
- C/C++ / General / Multi-processor Compilation:
-
-
In the Solution Explorer
- Find the filter "Resource Files"
- Right-click onto "version.rc"
- Choose "Properties".
- Select "All Configurations"
- Resources / General / Preprocessor Definitions:
- prepend
PTW32_ARCHx86;
when compiling for 32 bit platforms - or
PTW32_ARCHx64;
(without double quotes) otherwise.
- prepend
-
Find the file pthreads.h in project "pthread" -> "Header Files"
- At the top of the file, insert the line
#define _TIMESPEC_DEFINED
- At the top of the file, insert the line
-
Download the HiGHS source code from https://github.com/ERGO-Code/HiGHS.
-
Uncomment the line
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
in CMakeLists.txt. -
Open CMakeLists.txt (the file in the root folder) in VS2022 with File -> Open -> CMake.
-
Build and install all desired configurations.
-
To obtain SCIP, visit https://scip.zib.de/index.php#download and download the SCIP Optimization Suite.
-
Open CMakeLists.txt (the file in the root folder) in VS2022 with File -> Open -> CMake.
-
You may need to overwrite some compiler flags to compile the Release builds. In the files ./scip/CMakeLists.txt and ./soplex/CMakeLists.txt in lines 3 and 4 respectively,
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_RELEASE}") -> set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_DEBUG} ${CMAKE_C_FLAGS_RELEASE}") -> set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE}")
-
You may want to set different build/install directories.
-
Compile the needed configurations [32|64] bit in [Release | Debug] mode.
-
This version of SCIP will run only single-threaded. To use SCIP multithreaded you will need to compile it with the Ubiquity Generator (UG) framework. The UG-framework does only provide makefiles, so doing this on Windows is not easy and we can not provide a guideline for it.
-
Ensure that you have built Cbc as described above.
-
Ensure that you have built Boost. When building Boost, you need to set the parameters
define=_ITERATOR_DEBUG_LEVEL=0
define=BOOST_TEST_NO_MAIN
-
Specify the location of Cbc by opening the properties.props file and setting the User Macros
WITH_OSI
andWITH_CBC
to 'true', andCOIN_DIR
to the correct path (if your paths follow our examples). If your paths do not follow our examples, you may want to manually edit the include and linker directories or the properties.props outside of VS. -
[OPTIONAL] If you want to support multithreading, specify the root-location of pthread with the User Macro
PTHREAD_DIR
in the properties.props file. Then setPTHREAD_LIB_PATH
, such that it points to the folder containing the appropriate version of pthread.dll. Usually this will be$(PTHREAD_DIR)\$(PlatformTarget)-v$(PlatformToolsetVersion)-$(Configuration)
. If your structure does not follow this, you may want to manually edit the corresponding CustomBuild setting in ScaiIlpDll.vcxproj. -
[OPTIONAL] If you want to support HiGHS, specify the location of HiGHS by opening the properties.props file and setting the User Macro
WITH_HIGHS
to 'true' andHIGHS_DIR
to the correct path (if your paths follow our examples). If your paths do not follow our examples, you may want to manually edit the include and linker directories or the properties.props outside of VS. -
[OPTIONAL] If you want to support SCIP, specify the location of SCIP by opening the properties.props file and setting the User Macro
WITH_SCIP
to 'true' andSCIP_DIR
to the correct path (if your paths follow our examples). If your paths do not follow our examples, you may want to manually edit the include and linker directories or the properties.props outside of VS. -
[OPTIONAL] If you want to support Gurobi, specify the location of Gurobi by opening the properties.props file and setting the User Macro
WITH_GUROBI
to 'true' andGUROBI_DIR
to the root directory of your Gurobi Installation. Note that current versions of Gurobi only support 64-bit compilation, and that you need a valid Gurobi license to run ScaiILP with Gurobi. -
Specify the location of Boost by opening the properties.props file and setting the User Macros
BOOST_VERSION
andBOOST_DIR
(if your paths follow our examples) or by setting theBOOST_INCLUDE_PATH
andBOOST_LIB_PATH
manually to the correct paths on your system outside of VS. -
Build ScaiIlpDll, ScaiIlpExe, and UnitTest.
The Visual Studio Solution (.sln) contains three projects:
-
ScaiIlpDll creates ScaiIlpDll.dll
- ScaiIlpDll.dll contains the Cbc solver and a stub to communicate with ScaiIlpExe.exe. Optionally, it links dynamically to the SCIP solver and the Gurobi solver.
- It can be linked dynamically into other programs (which may require the dynamic libraries of other included solvers, too).
- The required dynamic libraries are automatically copied to the output folder when building ScaiIlpDll.
-
ScaiIlpExe creates ScaiIlpExe.exe
- ScaiIlpExe.exe links ScaiIlpDll.dll dynamically to provide the Cbc solver.
- ScaiIlpExe.exe can be started in a separate process and communicates via shared memory.
-
UnitTest demonstrates usage for both of above projects.
The published solver interface is ILPSolverInterface. Include ilp_solver_interface.hpp.
The recommended way to use ScaiIlp is to use it as a DLL (dynamic linking)
- Link against ScaiIlpDll.dll.
- Include ilp_solver_factory.hpp.
- Create your objects via create_solver_xxx() from ilp_solver_factory.hpp.
- To destroy the solver later, you MUST call destroy_solver() instead of deleting the pointer yourself.
Alternatively, you may include ilp_solver_xxx.cpp and all its dependencies in your project. This way, your code gets statically linked with a part of ScaiIlp.
To use ScaiIlpExe.exe, there is a class ILPSolverStub. IlpSolverStub can be used like IlpSolverCbc either as described in 3.2.1 or as described in 3.2.2. The constructor of IlpSolverStub and create_solver_stub() expect the base name of a solver executable (in the same directory, should be ScaiIlpExe.exe, unless you rename it).
ILPSolverInterface: Published interface
|
|-> ILPSolverImpl: Auxiliary base class to simplify implementation of any specific solver.
| Implements some methods of ILPSolverInterface
| by calling a smaller number of newly introduced private virtual methods.
|
|-> ILPSolverOsiModel: Base class for solvers whose modeling functionality is exposed via
| | the OsiSolverInterface, i.e. have a partial Osi interface.
| | Implements all methods they share.
| |
| |-> ILPSolverCbc: Final. To use CBC.
| | Implements the remaining, solver specific methods for the CBC solver.
| |
| |-> ILPSolverOsi: Final. Class for solvers who have a complete Osi interface.
| Implements the remaining, solver specific methods.
| Currently, some parameter-setting functions have empty implementations
| because the OsiSolverInterface does not provide this functionality.
|
|-> ILPSolverCollect: Implements all input related methods by storing the data in ILPData.
| | Base class for all solvers where that is useful.
| |
| |-> ILPSolverStub: Final. Solve in a separate process.
| solve_impl() writes the ILPData to shared memory and calls an external solver.
| The external solver writes the result (in form of ILPSolutionData)
| back to the shared memory.
| The solution getter methods of ILPSolverStub simply query ILPSolutionData.
|
|-> ILPSolverHighs: Final. To use HiGHS.
| Implements the solver specific methods for the HiGHS solver.
|
|-> ILPSolverSCIP: Final. To use SCIP.
| Implements the solver specific methods for the SCIP solver.
|
|-> ILPSolverGurobi: Final. To use Gurobi.
Implements the solver specific methods for the Gurobi solver.
When you want to support a new solver, you must ask yourself at which level you want to hook into the class hierarchy.
-
If you want to communicate with the solver via the OsiSolverInterface, can use the ILPSolverOsi class. The constructor takes any valid OsiSolverInterface*.
Note, however, that the OsiSolverInterface does not provide all the functionality that is exposed by ILPSolverInterface. If your solver provides a non-Osi interface, you might prefer the latter. If your solver has ways to partially bypass Osi and add the missing functionality, you should derive from IlpSolverOsi and override the corresponding functions.
-
If your solver is based on an LP-Solver it communicates with via the OsiSolverInterface and if your solver obtains its model via this LP-solver, then you should derive from ILPSolverOsiModel like Cbc does.
-
If you don't use Osi at all, you should derive from ILPSolverImpl.
Most likely you don't want to derive from IlpSolverInterface directly.
If you want your solver to be accessible via the DLL, then you must declare a function
extern "C" __declspec (dllexport) ILPSolverInterface* __stdcall create_solver_xyz(parameters);
in ilp_solver_factory.hpp and define it in ilp_solver_factory.cpp, respectively.