Commits (6)
pyscipopt: Python interface and modeling environment for SCIP
=============================================================
Description
-----------
Python interface and modeling environment for SCIP
License
-------
MIT
Upstream Contact
----------------
https://pypi.org/project/PySCIPOpt/
Dependencies
------------
scipoptsuite
tarball=PySCIPOpt-VERSION.tar.gz
sha1=e18b1d110082d6be9ebafbdc380d791e5eb3f1d9
md5=9624b3b49c122af500aa160e5786b0ec
cksum=1962617065
upstream_url=https://pypi.io/packages/source/p/pyscipopt/PySCIPOpt-VERSION.tar.gz
$(PYTHON) scipoptsuite | $(PYTHON_TOOLCHAIN)
----------
All lines of this file are ignored except the first.
cd src
export SCIPOPTDIR="$SAGE_LOCAL"
sdh_pip_install .
......@@ -20,20 +20,14 @@ this license without charge for research purposes as a member of a
non-commercial and academic institution, e.g., a university. The
software is available with its source code.
http://scip.zib.de/academic.txt
SPKG Maintainers
----------------
- Martin Albrecht (original spkg)
- Matthias Koeppe (updates for new spkg style)
https://www.scipopt.org/academic.txt
Upstream Contact
----------------
http://scip.zib.de/doc/html/AUTHORS.shtml
https://scipopt.org/#scipoptsuite
Dependencies
------------
......@@ -41,10 +35,15 @@ Dependencies
cmake
scipoptsuite brings its own patched version of the bliss library.
This will conflict with the optional package bliss.
Special Update/Build Instructions
---------------------------------
We do not have permission to redistribute SCIP or SoPlex. Hence, you
must download it yourself from http://scip.zib.de and put the tarball
``scipoptsuite-VERSION.tgz`` in ``$SAGE_ROOT/upstream``, renaming
it to ``scipoptsuite-VERSION-do-not-distribute.tgz``.
We do not have permission to redistribute the SCIP Optimization Suite.
Hence, you must download it yourself from http://scip.zib.de and
put the tarball ``scipoptsuite-VERSION.tgz`` in ``$SAGE_ROOT/upstream``,
renaming it to ``scipoptsuite-VERSION-do-not-distribute.tgz``.
tarball=scipoptsuite-VERSION-do-not-distribute.tgz
sha1=6f7f1b6fb09f7fcd289a260bfdc81b2918086514
md5=56071392f5cc2a85cd995758cd90af25
cksum=11618526
sha1=711bb29ee3ca26dd6ae08a26637dac5da2405605
md5=4d85624679644db1d2a8c2cb843942dc
cksum=1761242752
$(MP_LIBRARY) bliss readline | cmake
$(MP_LIBRARY) readline | cmake
----------
All lines of this file are ignored except the first.
......
From 0b79dea019a9b258014454ac527f04f7d76763fd Mon Sep 17 00:00:00 2001
From f9ac9ece39f487de3115a653d5d626514385ef8e Mon Sep 17 00:00:00 2001
From: Matthias Koeppe <mkoeppe@math.ucdavis.edu>
Date: Thu, 5 Apr 2018 12:01:25 -0500
Subject: [PATCH 1/3] Use libhistory
Subject: [PATCH 1/2] Use libhistory
---
scip/cmake/Modules/FindReadline.cmake | 11 ++++++++---
......@@ -36,10 +36,10 @@ index 051a1e7..9f14b5f 100644
mark_as_advanced(
Readline_ROOT_DIR
diff --git a/scip/src/CMakeLists.txt b/scip/src/CMakeLists.txt
index bbe9c72..ef55fe7 100644
index c3bec60..01e2fc8 100644
--- a/scip/src/CMakeLists.txt
+++ b/scip/src/CMakeLists.txt
@@ -803,6 +803,7 @@ setLibProperties(libscip "scip")
@@ -963,6 +963,7 @@ endif()
target_link_libraries(libscip PRIVATE
${ZLIB_LIBRARIES}
${Readline_LIBRARY}
......@@ -47,15 +47,15 @@ index bbe9c72..ef55fe7 100644
${GMP_LIBRARIES}
${THREAD_LIBRARIES}
${NLPI_LIBRARIES}
@@ -824,7 +825,7 @@ endif()
target_compile_definitions(scip PRIVATE EXTERN=extern)
@@ -991,7 +992,7 @@ if(CMAKE_BUILD_TYPE EQUAL "Debug")
add_sanitizers(scip)
endif()
-target_link_libraries(scip ${ZLIB_LIBRARIES} ${Readline_LIBRARY} ${GMP_LIBRARIES}
+target_link_libraries(scip ${ZLIB_LIBRARIES} ${Readline_LIBRARY} ${History_LIBRARY} ${GMP_LIBRARIES}
${ZIMPL_LIBRARIES} ${LPS_LIBRARIES} ${SYM_LIBRARIES} ${THREAD_LIBRARIES} ${NLPI_LIBRARIES})
${ZIMPL_LIBRARIES} ${LPS_LIBRARIES} ${SYM_LIBRARIES} ${THREAD_LIBRARIES} ${NLPI_LIBRARIES} ${PAPILO_IMPORTED_TARGETS})
add_dependencies(libscip scip_update_githash)
--
2.11.0
2.28.0
From 983b0b8630c41d2ce966877709184564432436cf Mon Sep 17 00:00:00 2001
From: Moritz Firsching <moritz@math.fu-berlin.de>
Date: Tue, 17 Apr 2018 11:09:35 +0200
Subject: [PATCH] added cmake ipopt patch
---
scip/cmake/Modules/FindIPOPT.cmake | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/scip/cmake/Modules/FindIPOPT.cmake b/scip/cmake/Modules/FindIPOPT.cmake
index 4d65120..00f4c34 100644
--- a/scip/cmake/Modules/FindIPOPT.cmake
+++ b/scip/cmake/Modules/FindIPOPT.cmake
@@ -35,6 +35,7 @@
# (To distribute this file outside of YCM, substitute the full
# License text for the above reference.)
+SET(IPOPT_FOUND FALSE)
if(NOT WIN32)
# On non Windows systems we use PkgConfig to find IPOPT
@@ -62,6 +63,7 @@ if(NOT WIN32)
PATHS ${_PC_IPOPT_LIBRARY_DIRS})
list(APPEND IPOPT_LIBRARIES ${${_LIBRARY}_PATH})
endforeach()
+ set(IPOPT_FOUND TRUE)
else()
set(IPOPT_DEFINITIONS "")
endif()
@@ -114,6 +116,7 @@ if(NOT WIN32)
endif()
mark_as_advanced(IPOPT_SEARCH_FOR_${LIB})
endforeach()
+ set(IPOPT_FOUND TRUE)
endif()
endif()
@@ -180,6 +183,7 @@ else()
endif()
mark_as_advanced(IPOPT_SEARCH_FOR_${LIB})
endforeach()
+ set(IPOPT_FOUND TRUE)
endif()
endif()
@@ -188,16 +192,18 @@ else()
endif()
# parse the version number
-if(EXISTS ${IPOPT_INCLUDE_DIRS} )
- file(STRINGS ${IPOPT_INCLUDE_DIRS}/IpoptConfig.h CONFIGFILE)
-
- foreach(STR ${CONFIGFILE})
- if("${STR}" MATCHES "^#define IPOPT_VERSION ")
- string(REGEX REPLACE "#define IPOPT_VERSION " "" IPOPT_VERSION ${STR})
- string(REGEX REPLACE "\"" "" IPOPT_VERSION ${IPOPT_VERSION})
- endif()
- endforeach()
- # MESSAGE("found Ipopt ${IPOPT_VERSION}")
+if(IPOPT_FOUND)
+ if(EXISTS ${IPOPT_INCLUDE_DIRS} )
+ file(STRINGS ${IPOPT_INCLUDE_DIRS}/IpoptConfig.h CONFIGFILE)
+
+ foreach(STR ${CONFIGFILE})
+ if("${STR}" MATCHES "^#define IPOPT_VERSION ")
+ string(REGEX REPLACE "#define IPOPT_VERSION " "" IPOPT_VERSION ${STR})
+ string(REGEX REPLACE "\"" "" IPOPT_VERSION ${IPOPT_VERSION})
+ endif()
+ endforeach()
+ # MESSAGE("found Ipopt ${IPOPT_VERSION}")
+ endif()
endif()
mark_as_advanced(IPOPT_INCLUDE_DIRS
--
2.17.0
From 656f9c88d52639af5109ca18c329bce6e0cea4da Mon Sep 17 00:00:00 2001
From 78286c79696405cb19b6da5c82fc78837ff41ffc Mon Sep 17 00:00:00 2001
From: Matthias Koeppe <mkoeppe@math.ucdavis.edu>
Date: Thu, 5 Apr 2018 17:53:39 -0500
Subject: [PATCH 2/3] ZIMPL cmake scripts: Put ZIMPL includes first to avoid
Subject: [PATCH 2/2] ZIMPL cmake scripts: Put ZIMPL includes first to avoid
clash of idxset.h with install soplex idxset.h
---
......@@ -9,10 +9,10 @@ Subject: [PATCH 2/3] ZIMPL cmake scripts: Put ZIMPL includes first to avoid
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/zimpl/src/CMakeLists.txt b/zimpl/src/CMakeLists.txt
index ee4dbca..a2d0865 100644
index 5395d60..f378d68 100644
--- a/zimpl/src/CMakeLists.txt
+++ b/zimpl/src/CMakeLists.txt
@@ -5,7 +5,7 @@ flex_target(MMLSCAN zimpl/mmlscan.l ${CMAKE_CURRENT_BINARY_DIR}/mmlscan.c)
@@ -7,7 +7,7 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/zimpl)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# for zimpl headers
......@@ -22,5 +22,5 @@ index ee4dbca..a2d0865 100644
set(libsources
zimpl/blkmem.c
--
2.11.0
2.28.0
From a6ff146209ed3dfab985870aa529889625492196 Mon Sep 17 00:00:00 2001
From: Matthias Koeppe <mkoeppe@math.ucdavis.edu>
Date: Mon, 16 Apr 2018 12:17:08 +0200
Subject: [PATCH 3/3] use INSTALL_NAME_DIR fix for libscip
---
scip/src/CMakeLists.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/scip/src/CMakeLists.txt b/scip/src/CMakeLists.txt
index ef55fe7..838ef15 100644
--- a/scip/src/CMakeLists.txt
+++ b/scip/src/CMakeLists.txt
@@ -834,6 +834,7 @@ add_dependencies(scip scip_update_githash)
set_target_properties(libscip PROPERTIES
VERSION ${SCIP_VERSION_MAJOR}.${SCIP_VERSION_MINOR}.${SCIP_VERSION_PATCH}.${SCIP_VERSION_SUB}
SOVERSION ${SCIP_VERSION_MAJOR}.${SCIP_VERSION_MINOR}
+ INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib"
INSTALL_RPATH_USE_LINK_PATH TRUE)
# set the install rpath to the installed destination
--
2.11.0
echo "Building scipoptsuite with cmake"
cd src
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX="${SAGE_LOCAL}"/ -DCMAKE_VERBOSE_MAKEFILE=ON -DGMP_DIR="${SAGE_LOCAL}" -DZLIB_ROOT="${SAGE_LOCAL}" -DReadline_ROOT_DIR="${SAGE_LOCAL}" -DBLISS_DIR="${SAGE_LOCAL}" -DIPOPT=FALSE
make
make install
$SAGE_LOCAL/bin/scip -s /dev/null -c quit
if [ $? -ne 0 ]; then
echo "SCIP build completed but the scip executable does not work."
exit 1
fi
echo "Finished building scipoptsuite"
cmake .. -DCMAKE_INSTALL_PREFIX="${SAGE_LOCAL}"/ \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE \
-DGMP_DIR="${SAGE_GMP_PREFIX}" \
-DReadline_ROOT_DIR=$(pkg-config --variable=prefix readline) \
-DHistory_ROOT_DIR=$(pkg-config --variable=prefix readline) \
-DIPOPT=FALSE \
|| sdh_die "Error configuring $PKG_NAME with cmake"
sdh_make
sdh_make_install
......@@ -509,7 +509,7 @@ cdef class GenericBackend:
for i, c in coefficients:
coefficients_d.append((i, c[d]))
lower_bound_d = None if lower_bound is None else lower_bound[d]
upper_bound_d = None if upper_bound is None else upper_bound[d]
upper_bound_d = None if upper_bound is None else upper_bound[d]
self.add_linear_constraint(coefficients_d, lower_bound_d, upper_bound_d, name=name)
@classmethod
......@@ -872,7 +872,7 @@ cdef class GenericBackend:
tester = self._tester(**options)
p = self
tester.assertGreaterEqual(self.ncols(), 0)
cpdef int nrows(self):
"""
Return the number of rows/constraints.
......@@ -1251,7 +1251,7 @@ cdef class GenericBackend:
"{}({}) does not match".format(method, i))
for method in ("row_bounds", "row", "row_name"):
assert_equal_row_data(method)
def _test_copy(self, **options):
"""
Test whether the backend can be copied
......@@ -1262,16 +1262,19 @@ cdef class GenericBackend:
cp = copy(self)
self._do_test_problem_data(tester, cp)
def _test_copy_does_not_share_data(self, **options):
"""
Test whether copy makes an independent copy of the backend.
"""
tester = self._tester(**options)
cp = copy(self)
cpcp = copy(cp)
del cp
self._do_test_problem_data(tester, cpcp)
# TODO: We should have a more systematic way of generating MIPs for testing.
@classmethod
def _test_copy_some_mips(cls, tester=None, **options):
......@@ -1288,6 +1291,7 @@ cdef class GenericBackend:
pass
# From doctest of GenericBackend.problem_name:
p.problem_name("There once was a french fry")
p._test_copy(**options)
p._test_copy_does_not_share_data(**options)
......@@ -1577,7 +1581,7 @@ def default_mip_solver(solver=None):
return default_solver
else:
for s in ["Cplex", "Gurobi", "Coin", "Glpk"]:
for s in ["Cplex", "Gurobi", "Coin", "Glpk", "SCIP"]:
try:
default_mip_solver(s)
return s
......@@ -1631,8 +1635,16 @@ def default_mip_solver(solver=None):
elif solver == "Interactivelp":
default_solver = solver
elif solver == "SCIP" or solver == "Scip":
try:
from sage.libs.scip.scip import SCIP
from pyscipopt import Model
default_solver = solver
except ImportError:
raise ValueError("SCIP is not available. Please refer to the documentation to install it.")
else:
raise ValueError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'CVXOPT', 'Gurobi', 'PPL', 'InteractiveLP', a callable, or None.")
raise ValueError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'CVXOPT', 'Gurobi', 'PPL', 'SCIP', 'InteractiveLP', a callable, or None.")
cpdef GenericBackend get_solver(constraint_generation = False, solver = None, base_ring = None):
"""
......@@ -1664,7 +1676,7 @@ cpdef GenericBackend get_solver(constraint_generation = False, solver = None, ba
- When set to ``True``, after solving the ``MixedIntegerLinearProgram``,
it is possible to add a constraint, and then solve it again.
The effect is that solvers that do not support this feature will not be
used.
used. (Coin and SCIP are such solvers.)
- Defaults to ``False``.
......@@ -1744,7 +1756,7 @@ cpdef GenericBackend get_solver(constraint_generation = False, solver = None, ba
# We do not want to use Coin for constraint_generation. It just does not
# work
if solver == "Coin" and constraint_generation:
if solver in ("Coin", "SCIP") and constraint_generation:
solver = "Glpk"
if callable(solver):
......@@ -1788,5 +1800,10 @@ cpdef GenericBackend get_solver(constraint_generation = False, solver = None, ba
from sage.numerical.backends.interactivelp_backend import InteractiveLPBackend
return InteractiveLPBackend(base_ring=base_ring)
elif solver == "Scip":
from sage.numerical.backends.scip_backend import SCIPBackend
return SCIPBackend()
else:
raise ValueError("'solver' should be set to 'GLPK', 'GLPK/exact', 'Coin', 'CPLEX', 'CVXOPT', 'Gurobi', 'PPL', 'InteractiveLP', None (in which case the default one is used), or a callable.")
raise ValueError("'solver' should be set to 'GLPK', 'GLPK/exact', 'Coin', 'CPLEX', 'CVXOPT', 'Gurobi', 'PPL', 'SCIP', 'InteractiveLP', None (in which case the default one is used), or a callable.")
#*****************************************************************************
# Copyright (C) 2017 Matthias Koeppe <mkoeppe@math.ucdavis.edu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# http://www.gnu.org/licenses/
#*****************************************************************************
from generic_backend cimport GenericBackend
cdef class SCIPBackend(GenericBackend):
cdef model
cpdef _get_model(self)
cpdef get_row_prim(self, int i)
cpdef write_cip(self, char * filename)
This diff is collapsed.
......@@ -796,7 +796,7 @@ cdef class MixedIntegerLinearProgram(SageObject):
shorthand for generating new variables with default settings::
sage: mip.<x, y, z> = MixedIntegerLinearProgram(solver='GLPK')
sage: mip.add_constraint(x[0] + y[1] + z[2] <= 10)
sage: mip.add_constraint(x[0] + y[1] + z[2] <= 10)
sage: mip.show()
Maximization:
<BLANKLINE>
......@@ -1309,7 +1309,7 @@ cdef class MixedIntegerLinearProgram(SageObject):
name = varid_explainer[i]
lb, ub = b.col_bounds(i)
print(' {0} is {1} variable (min={2}, max={3})'.format(
name, var_type,
name, var_type,
lb if lb is not None else "-oo",
ub if ub is not None else "+oo"))
......@@ -1636,7 +1636,7 @@ cdef class MixedIntegerLinearProgram(SageObject):
sage: p.add_constraint(x[5] + 3*x[7] == x[6] + 3)
sage: p.add_constraint(x[5] + 3*x[7] <= x[6] + 3 <= x[8] + 27)
Using this notation, the previous program can be written as::
sage: p = MixedIntegerLinearProgram(maximization=True, solver='GLPK')
......@@ -1751,7 +1751,7 @@ cdef class MixedIntegerLinearProgram(SageObject):
<BLANKLINE>
Constraints:
1.0 <= x_0 - x_1
-2.0 <= -2.0 x_0 + 2.0 x_1
-2.0 <= -2.0 x_0 + 2.0 x_1
Variables:
x_0 is a continuous variable (min=-oo, max=+oo)
x_1 is a continuous variable (min=-oo, max=+oo)
......@@ -1819,8 +1819,8 @@ cdef class MixedIntegerLinearProgram(SageObject):
raise ValueError('min and max must not be specified for (in)equalities')
relation = linear_function
M = relation.parent().linear_tensors().free_module()
self.add_constraint(relation.lhs() - relation.rhs(),
min=M(0) if relation.is_equation() else None,
self.add_constraint(relation.lhs() - relation.rhs(),
min=M(0) if relation.is_equation() else None,
max=M(0), name=name)
else:
raise ValueError('argument must be a linear function or constraint, got '+str(linear_function))
......@@ -2409,7 +2409,7 @@ cdef class MixedIntegerLinearProgram(SageObject):
sage: p.solver_parameter("timelimit", 60)
Sets the solver to stop its computations after 60 seconds, and works
with GLPK, CPLEX and Gurobi.
with GLPK, CPLEX , SCIP, and Gurobi.
- ``"timelimit"`` -- defines the maximum time spent on a
computation. Measured in seconds.
......@@ -2452,6 +2452,9 @@ cdef class MixedIntegerLinearProgram(SageObject):
method. Their list is available on Gurobi's website
`<http://www.gurobi.com/documentation/5.5/reference-manual/node798>`_.
SCIP's parameter can be found here:
`<http://scip.zib.de/doc-5.0.1/html/PARAMETERS.php>`_.
INPUT:
- ``name`` (string) -- the parameter
......@@ -2712,7 +2715,7 @@ cdef class MixedIntegerLinearProgram(SageObject):
if back_end.variable_lower_bound(i) != 0:
raise ValueError('Problem variables must have 0 as lower bound')
if back_end.variable_upper_bound(i) is not None:
raise ValueError('Problem variables must not have upper bound')
raise ValueError('Problem variables must not have upper bound')
# Construct 'A'
coef_matrix = []
......@@ -2992,14 +2995,14 @@ cdef class MIPVariable(SageObject):
j = self._p._backend.add_variable(
lower_bound=self._lower_bound,
upper_bound=self._upper_bound,
binary=False,
continuous=True,
integer=False,
binary=self._vtype==0,
continuous=self._vtype==-1,
integer=self._vtype==1,
obj=zero,
name=name)
v = self._p.linear_functions_parent()({j : 1})
self._p._variables[v] = j
self._p._backend.set_variable_type(j, self._vtype)
#self._p._backend.set_variable_type(j, self._vtype)
self._dict[i] = v
return v
......