Skip to content

Commit

Permalink
Update to Gurobi 9.0.2 and use GUROBI_HOME instead of GUROBI_PATH (Ro…
Browse files Browse the repository at this point in the history
…botLocomotion#13049)

* Update to gurobi9.

* Use gurobi 9.0.2 instead of 9.0.0

* Use GUROBI_HOME instead of GUROBI_PATH environment variable.
  • Loading branch information
hongkai-dai authored May 11, 2020
1 parent 3cae480 commit 29a8e53
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 63 deletions.
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -359,13 +359,13 @@ set(BAZEL_CONFIGS)
option(WITH_GUROBI "Build with support for Gurobi" OFF)

if(WITH_GUROBI)
find_package(Gurobi 8.0.1 EXACT MODULE REQUIRED)
find_package(Gurobi 9.0.2 EXACT MODULE REQUIRED)

list(APPEND BAZEL_CONFIGS --config=gurobi)

if(NOT APPLE)
get_filename_component(GUROBI_PATH "${Gurobi_INCLUDE_DIRS}" DIRECTORY)
list(APPEND BAZEL_ENV "GUROBI_PATH=${GUROBI_PATH}")
get_filename_component(GUROBI_HOME "${Gurobi_INCLUDE_DIRS}" DIRECTORY)
list(APPEND BAZEL_ENV "GUROBI_HOME=${GUROBI_HOME}")
endif()
endif()

Expand Down
16 changes: 8 additions & 8 deletions cmake/modules/FindGurobi.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

find_path(Gurobi_INCLUDE_DIR NAMES gurobi_c.h
PATHS
/Library/gurobi801/mac64
/opt/gurobi801/linux64
/opt/gurobi801/power64
ENV GUROBI_PATH
/Library/gurobi902/mac64
/opt/gurobi902/linux64
/opt/gurobi902/power64
ENV GUROBI_HOME
PATH_SUFFIXES include
)

Expand Down Expand Up @@ -38,10 +38,10 @@ find_library(Gurobi_LIBRARY
NAMES "gurobi${Gurobi_VERSION_MAJOR}${Gurobi_VERSION_MINOR}"
HINTS "${_GUROBI_ROOT}"
PATHS
/Library/gurobi801/mac64
/opt/gurobi801/linux64
/opt/gurobi801/power64
ENV GUROBI_PATH
/Library/gurobi902/mac64
/opt/gurobi902/linux64
/opt/gurobi902/power64
ENV GUROBI_HOME
PATH_SUFFIXES lib
)

Expand Down
12 changes: 6 additions & 6 deletions doc/bazel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ Proprietary Solvers

The Drake Bazel build currently supports the following proprietary solvers:

* Gurobi 8.0.1
* Gurobi 9.0.2
* MOSEK 9.0
* SNOPT 7.4

Expand All @@ -169,24 +169,24 @@ The Drake Bazel build currently supports the following proprietary solvers:
.. _gurobi:

Gurobi 8.0.1
Gurobi 9.0.2
------------

Install on Ubuntu
~~~~~~~~~~~~~~~~~
1. Register for an account on https://www.gurobi.com.
2. Set up your Gurobi license file in accordance with Gurobi documentation.
3. ``export GRB_LICENSE_FILE=/path/to/gurobi.lic``.
4. Download ``gurobi8.0.1_linux64.tar.gz``
5. Unzip it. We suggest that you use ``/opt/gurobi801`` to simplify working with Drake installations.
6. ``export GUROBI_PATH=/opt/gurobi801/linux64``
4. Download ``gurobi9.0.2_linux64.tar.gz``
5. Unzip it. We suggest that you use ``/opt/gurobi902`` to simplify working with Drake installations.
6. If you unzipped into a location other than ``/opt/gurobi902``, then call ``export GUROBI_HOME=GUROBI_UNZIP_PATH/linux64`` to set the path you used, where in ``GUROBI_HOME`` folder you can find ``bin`` folder.

Install on macOS
~~~~~~~~~~~~~~~~
1. Register for an account on http://www.gurobi.com.
2. Set up your Gurobi license file in accordance with Gurobi documentation.
3. ``export GRB_LICENSE_FILE=/path/to/gurobi.lic``
4. Download and install ``gurobi8.0.1_mac64.pkg``.
4. Download and install ``gurobi9.0.2_mac64.pkg``.


To confirm that your setup was successful, run the tests that require Gurobi:
Expand Down
2 changes: 1 addition & 1 deletion doc/python_bindings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ After following the above install steps, check to ensure you can import

If you are using Gurobi, you must either have it installed in the suggested
location under ``/opt/...`` mentioned in :ref:`gurobi`, or you must ensure
that you define the ``${GUROBI_PATH}`` environment variable, or specify
that you define the ``${GUROBI_HOME}`` environment variable, or specify
``${GUROBI_INCLUDE_DIR}`` via CMake.

.. _whats-available-from-python:
Expand Down
4 changes: 2 additions & 2 deletions solvers/gurobi_solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ __attribute__((unused)) bool HasCorrectNumberOfVariables(
* A*x == lb, false otherwise.
* @return error as an integer. The full set of error values are
* described here :
* https://www.gurobi.com/documentation/8.0/refman/error_codes.html
* https://www.gurobi.com/documentation/9.0/refman/error_codes.html
*
* TODO(hongkai.dai): Use a sparse matrix A.
*/
Expand Down Expand Up @@ -355,7 +355,7 @@ int AddSecondOrderConeConstraints(

// Gurobi uses a matrix Q to differentiate Lorentz cone and rotated Lorentz
// cone constraint.
// https://www.gurobi.com/documentation/8.0/refman/c_grbaddqconstr.html
// https://www.gurobi.com/documentation/9.0/refman/c_grbaddqconstr.html
// For Lorentz cone constraint,
// Q = [-1 0 0 ... 0]
// [ 0 1 0 ... 0]
Expand Down
12 changes: 6 additions & 6 deletions solvers/gurobi_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ namespace solvers {
/// details.
struct GurobiSolverDetails {
/// The gurobi optimization time. Please refer to
/// https://www.gurobi.com/documentation/8.0/refman/runtime.html
/// https://www.gurobi.com/documentation/9.0/refman/runtime.html
double optimizer_time{};

/// The error message returned from Gurobi call. Please refer to
/// https://www.gurobi.com/documentation/8.0/refman/error_codes.html
/// https://www.gurobi.com/documentation/9.0/refman/error_codes.html
int error_code{};

/// The status code when the optimize call has returned. Please refer to
/// https://www.gurobi.com/documentation/8.0/refman/optimization_status_codes.html
/// https://www.gurobi.com/documentation/9.0/refman/optimization_status_codes.html
int optimization_status{};

/// The best known bound on the optimal objective. This is used in mixed
/// integer optimization. Please refer to
/// https://www.gurobi.com/documentation/8.0/refman/objbound.html
/// https://www.gurobi.com/documentation/9.0/refman/objbound.html
double objective_bound{NAN};
};

Expand Down Expand Up @@ -66,7 +66,7 @@ class GurobiSolver final : public SolverBase {
/// Users can supply a callback to be called when the Gurobi solver
/// finds an intermediate solution node, which may not be feasible.
/// See Gurobi reference manual for more detail on callbacks:
/// https://www.gurobi.com/documentation/8.0/refman/callback_codes.html.
/// https://www.gurobi.com/documentation/9.0/refman/callback_codes.html.
/// The user may supply a partial solution in the VectorXd and
/// VectorXDecisionVariable arguments that will be passed to Gurobi
/// as a candidate feasible solution.
Expand Down Expand Up @@ -101,7 +101,7 @@ class GurobiSolver final : public SolverBase {
/// Users can supply a callback to be called when the Gurobi solver
/// finds a feasible solution.
/// See Gurobi reference manual for more detail on callbacks:
/// https://www.gurobi.com/documentation/8.0/refman/callback_codes.html.
/// https://www.gurobi.com/documentation/9.0/refman/callback_codes.html.
/// See gurobi_solver_test.cc for an example of using std::bind
/// to create a callback of this signature, while allowing
/// additional data to be passed through.
Expand Down
2 changes: 1 addition & 1 deletion solvers/solver_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace solvers {
*
* "GUROBI" -- Parameter name and values as specified in Gurobi Reference
* Manual, section 10.2 "Parameter Descriptions"
* https://www.gurobi.com/documentation/8.0/refman/parameters.html
* https://www.gurobi.com/documentation/9.0/refman/parameters.html
*
* "SCS" -- Parameter name and values as specified in the struct SCS_SETTINGS in
* SCS header file https://github.com/cvxgrp/scs/blob/master/include/scs.h
Expand Down
10 changes: 5 additions & 5 deletions solvers/test/gurobi_solver_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ TEST_F(UnboundedLinearProgramTest0, TestGurobiUnbounded) {
EXPECT_EQ(result.get_solution_result(),
SolutionResult::kInfeasible_Or_Unbounded);
// This code is defined in
// https://www.gurobi.com/documentation/8.0/refman/optimization_status_codes.html
// https://www.gurobi.com/documentation/9.0/refman/optimization_status_codes.html
const int GRB_INF_OR_UNBD = 4;
EXPECT_EQ(result.get_solver_details<GurobiSolver>().optimization_status,
GRB_INF_OR_UNBD);
Expand All @@ -68,7 +68,7 @@ TEST_F(UnboundedLinearProgramTest0, TestGurobiUnbounded) {
EXPECT_FALSE(result.is_success());
EXPECT_EQ(result.get_solution_result(), SolutionResult::kUnbounded);
// This code is defined in
// https://www.gurobi.com/documentation/8.0/refman/optimization_status_codes.html
// https://www.gurobi.com/documentation/9.0/refman/optimization_status_codes.html
const int GRB_UNBOUNDED = 5;
EXPECT_EQ(result.get_solver_details<GurobiSolver>().optimization_status,
GRB_UNBOUNDED);
Expand Down Expand Up @@ -269,7 +269,7 @@ GTEST_TEST(TestSOCP, MaximizeGeometricMeanTrivialProblem2) {
GurobiSolver solver;
if (solver.available()) {
const auto result = solver.Solve(prob.prog(), {}, {});
// Gurobi 8.0.0 returns a solution that is accurate up to 1.4E-6 for this
// Gurobi 9.0.0 returns a solution that is accurate up to 1.4E-6 for this
// specific problem. Might need to change the tolerance when we upgrade
// Gurobi.
prob.CheckSolution(result, 1.4E-6);
Expand Down Expand Up @@ -359,7 +359,7 @@ GTEST_TEST(GurobiTest, GurobiErrorCode) {
solver_options.SetOption(solver.solver_id(), "Foo", 1);
auto result = solver.Solve(prog, {}, solver_options);
// The error code is listed in
// https://www.gurobi.com/documentation/8.0/refman/error_codes.html
// https://www.gurobi.com/documentation/9.0/refman/error_codes.html
const int UNKNOWN_PARAMETER{10007};
EXPECT_EQ(result.get_solver_details<GurobiSolver>().error_code,
UNKNOWN_PARAMETER);
Expand All @@ -368,7 +368,7 @@ GTEST_TEST(GurobiTest, GurobiErrorCode) {
prog.AddQuadraticCost(x(0) * x(0) - x(1) * x(1));
result = solver.Solve(prog, {}, {});
// The error code is listed in
// https://www.gurobi.com/documentation/8.0/refman/error_codes.html
// https://www.gurobi.com/documentation/9.0/refman/error_codes.html
const int Q_NOT_PSD{10020};
EXPECT_EQ(result.get_solver_details<GurobiSolver>().error_code,
Q_NOT_PSD);
Expand Down
5 changes: 3 additions & 2 deletions tools/bazel.rc
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ test --test_env=MPLBACKEND=Template

### A configuration that enables Gurobi. ###
# -- To use this config, the GRB_LICENSE_FILE environment variable must be set
# -- to the location of the Gurobi license key file. On Ubuntu, the GUROBI_PATH
# -- to the location of the Gurobi license key file. On Ubuntu, the GUROBI_HOME
# -- environment variable must be set to the linux64 directory of the extracted
# -- archive downloaded from gurobi.com.
# -- archive downloaded from gurobi.com when the installation was not at the
# -- default location of /opt/gurobi902/linux64.
#
# -- To run tests where Gurobi is used, ensure that you include
# -- "gurobi_test_tags()" from //tools/skylark:test_tags.bzl.
Expand Down
6 changes: 3 additions & 3 deletions tools/dynamic_analysis/tsan.supp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ called_from_lib:libmosek64.so.9.0
# data race (libglib-2.0.*) in g_static_rec_mutex_lock
race:g_static_rec_mutex_lock

# data race (libgurobi80.*) in bio_asn1.c. Gurobi has not been instrumented
# data race (libgurobi90.*) in bio_asn1.c. Gurobi has not been instrumented
# with TSan.
called_from_lib:libgurobi.so
called_from_lib:libgurobi80.dylib
called_from_lib:libgurobi80.so
called_from_lib:libgurobi90.dylib
called_from_lib:libgurobi90.so

# data race in libtbb.so. libtbb has not been instrumented with TSan.
called_from_lib:libtbb.so
Expand Down
14 changes: 7 additions & 7 deletions tools/workspace/gurobi/package-macos.BUILD.bazel.in
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ licenses(["by_exception_only"]) # Gurobi
genrule(
name = "error-message",
outs = ["error-message.h"],
cmd = "echo 'error: Gurobi 8.0.1 is not installed at {gurobi_path}' && false", # noqa
cmd = "echo 'error: Gurobi 9.0.2 is not installed at {gurobi_home}' && false", # noqa
visibility = ["//visibility:private"],
)

Expand All @@ -29,9 +29,9 @@ cc_library(
hdrs = GUROBI_C_HDRS,
includes = ["gurobi-distro/include"],
linkopts = [
"-L{gurobi_path}/lib",
"-lgurobi80",
"-Wl,-rpath,{gurobi_path}/lib",
"-L{gurobi_home}/lib",
"-lgurobi90",
"-Wl,-rpath,{gurobi_home}/lib",
],
visibility = ["//visibility:public"],
)
Expand All @@ -41,10 +41,10 @@ cc_library(
hdrs = GUROBI_CXX_HDRS,
includes = ["gurobi-distro/include"],
linkopts = [
"-L{gurobi_path}/lib",
"-lgurobi80",
"-L{gurobi_home}/lib",
"-lgurobi90",
"-lgurobi_stdc++",
"-Wl,-rpath,{gurobi_path}/lib",
"-Wl,-rpath,{gurobi_home}/lib",
],
visibility = ["//visibility:public"],
)
Expand Down
14 changes: 7 additions & 7 deletions tools/workspace/gurobi/package-ubuntu.BUILD.bazel.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ licenses(["by_exception_only"]) # Gurobi
genrule(
name = "error-message",
outs = ["error-message.h"],
cmd = "echo 'error: Gurobi 8.0.1 is not installed at {gurobi_path}, export GUROBI_PATH to the correct value' && false", # noqa
cmd = "echo 'error: Gurobi 9.0.2 is not installed at {gurobi_home}, export GUROBI_HOME to the correct value' && false", # noqa
visibility = ["//visibility:private"],
)

Expand All @@ -25,25 +25,25 @@ GUROBI_CXX_HDRS = glob([
"gurobi-distro/include/gurobi_c++.h",
]) or [":error-message.h"]

# In the Gurobi package, libgurobi80.so is a symlink to libgurobi.so.8.0.1.
# However, if we use libgurobi.so.8.0.1 in srcs, executables that link this
# In the Gurobi package, libgurobi90.so is a symlink to libgurobi.so.9.0.0.
# However, if we use libgurobi.so.9.0.0 in srcs, executables that link this
# library will be unable to find it at runtime in the Bazel sandbox,
# because the NEEDED statements in the executable will not square with the
# RPATH statements. I don't really know why this happens, but I suspect it
# might be a Bazel bug.

GUROBI_C_SRCS = glob([
"gurobi-distro/lib/libgurobi80.so",
"gurobi-distro/lib/libgurobi90.so",
]) or [":error-message.h"]

GUROBI_CXX_SRCS = glob([
"gurobi-distro/lib/libgurobi80.so",
"gurobi-distro/lib/libgurobi90.so",
"gurobi-distro/lib/libgurobi_g++5.2.a",
]) or [":error-message.h"]

GUROBI_INSTALL_LIBRARIES = glob([
"gurobi-distro/lib/libgurobi.so.8.0.1",
"gurobi-distro/lib/libgurobi80.so",
"gurobi-distro/lib/libgurobi.so.9.0.2",
"gurobi-distro/lib/libgurobi90.so",
]) or [":error-message.h"]

GUROBI_DOCS = glob([
Expand Down
26 changes: 14 additions & 12 deletions tools/workspace/gurobi/repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,42 @@

load("@drake//tools/workspace:os.bzl", "determine_os")

# Ubuntu only: GUROBI_PATH should be the linux64 directory in the Gurobi 8.0.1
# Ubuntu only: GUROBI_HOME should be the linux64 directory in the Gurobi 9.0.2
# release.
#
# TODO(jwnimmer-tri) The Gurobi docs use /opt/gurobi801/linux64, so we should
# probably look in that location as a reasonable default guess.
def _gurobi_impl(repo_ctx):
os_result = determine_os(repo_ctx)
if os_result.error != None:
fail(os_result.error)

if os_result.is_macos:
# Gurobi must be installed into its standard location.
gurobi_path = "/Library/gurobi801/mac64"
repo_ctx.symlink(gurobi_path, "gurobi-distro")
gurobi_home = "/Library/gurobi902/mac64"
repo_ctx.symlink(gurobi_home, "gurobi-distro")
else:
# Locate Gurobi using an environment variable. If GUROBI_PATH is
# unset, pass the empty string to our template() call, but symlink a
# dummy distro path since we can't symlink to the empty string.
gurobi_path = repo_ctx.os.environ.get("GUROBI_PATH", "")
repo_ctx.symlink(gurobi_path or "/no-gurobi-path", "gurobi-distro")
# The default directory for the downloaded gurobi is
# /opt/gurobi902/linux64. If the user does not use the default
# directory, the he/she should set GUROBI_HOME environment variable to
# the gurobi file location.
gurobi_home = repo_ctx.os.environ.get("GUROBI_HOME", "")
repo_ctx.symlink(
gurobi_home or "/opt/gurobi902/linux64",
"gurobi-distro",
)

# Emit the generated BUILD.bazel file.
repo_ctx.template(
"BUILD.bazel",
Label("@drake//tools/workspace/gurobi:" +
"package-{}.BUILD.bazel.in".format(os_result.distribution)),
substitutions = {
"{gurobi_path}": gurobi_path,
"{gurobi_home}": gurobi_home,
},
executable = False,
)

gurobi_repository = repository_rule(
environ = ["GUROBI_PATH"],
environ = ["GUROBI_HOME"],
local = True,
implementation = _gurobi_impl,
)

0 comments on commit 29a8e53

Please sign in to comment.