Skip to content

Commit

Permalink
[solvers] Deprecate dReal and IBEX for removal (RobotLocomotion#18156)
Browse files Browse the repository at this point in the history
Deprecate the classes DrealSolver and IbexSolver, and their SolverType
enum values.

Deprecate the workspace externals cds, dreal, ibex, and picosat.
  • Loading branch information
jwnimmer-tri authored Nov 1, 2022
1 parent 4bc8764 commit b034166
Show file tree
Hide file tree
Showing 21 changed files with 212 additions and 86 deletions.
3 changes: 2 additions & 1 deletion bindings/pydrake/solvers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ drake_pybind_library(
"//bindings/pydrake:symbolic_types_pybind",
"//bindings/pydrake/common:cpp_param_pybind",
"//bindings/pydrake/common:cpp_template_pybind",
"//bindings/pydrake/common:deprecation_pybind",
"//bindings/pydrake/common:eigen_pybind",
"//bindings/pydrake/common:value_pybind",
],
Expand Down Expand Up @@ -173,7 +174,7 @@ drake_py_unittest(
}),
deps = [
":solvers",
"//bindings/pydrake/common/test_utilities:numpy_compare_py",
"//bindings/pydrake/common/test_utilities",
],
)

Expand Down
36 changes: 25 additions & 11 deletions bindings/pydrake/solvers/solvers_py_dreal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

#include "drake/bindings/pydrake/common/deprecation_pybind.h"
#include "drake/bindings/pydrake/documentation_pybind.h"
#include "drake/bindings/pydrake/pydrake_pybind.h"
#include "drake/bindings/pydrake/solvers/solvers_py.h"
Expand All @@ -11,21 +12,26 @@ namespace drake {
namespace pydrake {
namespace internal {

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void DefineSolversDreal(py::module m) {
// NOLINTNEXTLINE(build/namespaces): Emulate placement in namespace.
using namespace drake::solvers;
constexpr auto& doc = pydrake_doc.drake.solvers;

auto solver = py::class_<DrealSolver, SolverInterface>(
m, "DrealSolver", doc.DrealSolver.doc)
.def_static("id", &DrealSolver::id, doc.DrealSolver.id.doc);
m, "DrealSolver", doc.DrealSolver.doc_deprecated)
.def_static("id",
WrapDeprecated(doc.DrealSolver.id.doc_deprecated,
&DrealSolver::id),
doc.DrealSolver.id.doc_deprecated);

{
using Class = DrealSolver::Interval;
const auto& cls_doc = doc.DrealSolver.Interval;
py::class_<Class>(solver, "Interval", cls_doc.doc)
.def(py::init<double, double>(), py::arg("low"), py::arg("high"),
cls_doc.ctor.doc)
py::class_<Class>(solver, "Interval", cls_doc.doc_deprecated)
.def(py_init_deprecated<Class, double, double>(cls_doc.doc_deprecated),
py::arg("low"), py::arg("high"), cls_doc.doc_deprecated)
.def("diam", &Class::diam, cls_doc.diam.doc)
.def("mid", &Class::mid, cls_doc.mid.doc)
.def("low", &Class::low, cls_doc.low.doc)
Expand All @@ -40,14 +46,22 @@ void DefineSolversDreal(py::module m) {
.value("kNotUse", Class::kNotUse, cls_doc.kNotUse.doc);
}

solver.def(py::init<>(), doc.DrealSolver.ctor.doc)
.def_static("CheckSatisfiability", &DrealSolver::CheckSatisfiability,
solver
.def(py_init_deprecated<DrealSolver>(doc.DrealSolver.ctor.doc_deprecated),
doc.DrealSolver.ctor.doc_deprecated)
.def_static("CheckSatisfiability",
WrapDeprecated(doc.DrealSolver.CheckSatisfiability.doc_deprecated,
&DrealSolver::CheckSatisfiability),
py::arg("f"), py::arg("delta"),
doc.DrealSolver.CheckSatisfiability.doc)
.def_static("Minimize", &DrealSolver::Minimize, py::arg("objective"),
py::arg("constraint"), py::arg("delta"),
py::arg("local_optimization"), doc.DrealSolver.Minimize.doc);
doc.DrealSolver.CheckSatisfiability.doc_deprecated)
.def_static("Minimize",
WrapDeprecated(
doc.DrealSolver.Minimize.doc_deprecated, &DrealSolver::Minimize),
py::arg("objective"), py::arg("constraint"), py::arg("delta"),
py::arg("local_optimization"),
doc.DrealSolver.Minimize.doc_deprecated);
}
#pragma GCC diagnostic pop

} // namespace internal
} // namespace pydrake
Expand Down
14 changes: 11 additions & 3 deletions bindings/pydrake/solvers/solvers_py_ibex.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "pybind11/eigen.h"
#include "pybind11/pybind11.h"

#include "drake/bindings/pydrake/common/deprecation_pybind.h"
#include "drake/bindings/pydrake/documentation_pybind.h"
#include "drake/bindings/pydrake/pydrake_pybind.h"
#include "drake/bindings/pydrake/solvers/solvers_py.h"
Expand All @@ -10,15 +11,22 @@ namespace drake {
namespace pydrake {
namespace internal {

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void DefineSolversIbex(py::module m) {
// NOLINTNEXTLINE(build/namespaces): Emulate placement in namespace.
using namespace drake::solvers;
constexpr auto& doc = pydrake_doc.drake.solvers;

py::class_<IbexSolver, SolverInterface>(m, "IbexSolver", doc.IbexSolver.doc)
.def(py::init<>(), doc.IbexSolver.ctor.doc)
.def_static("id", &IbexSolver::id, doc.IbexSolver.id.doc);
py::class_<IbexSolver, SolverInterface>(
m, "IbexSolver", doc.IbexSolver.doc_deprecated)
.def(py_init_deprecated<IbexSolver>(doc.IbexSolver.ctor.doc_deprecated),
doc.IbexSolver.ctor.doc_deprecated)
.def_static("id",
WrapDeprecated(doc.IbexSolver.id.doc_deprecated, &IbexSolver::id),
doc.IbexSolver.id.doc_deprecated);
}
#pragma GCC diagnostic pop

} // namespace internal
} // namespace pydrake
Expand Down
12 changes: 9 additions & 3 deletions bindings/pydrake/solvers/solvers_py_mathematicalprogram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,13 @@ void BindSolverInterfaceAndFlags(py::module m) {
.value("kLCP", ProgramType::kLCP, doc.ProgramType.kLCP.doc)
.value("kUnknown", ProgramType::kUnknown, doc.ProgramType.kUnknown.doc);

py::enum_<SolverType>(m, "SolverType", doc.SolverType.doc)
py::enum_<SolverType> solver_type(m, "SolverType", doc.SolverType.doc);
solver_type // BR
.value("kClp", SolverType::kClp, doc.SolverType.kClp.doc)
.value("kCsdp", SolverType::kCsdp, doc.SolverType.kCsdp.doc)
.value("kDReal", SolverType::kDReal, doc.SolverType.kDReal.doc)
.value("kEqualityConstrainedQP", SolverType::kEqualityConstrainedQP,
doc.SolverType.kEqualityConstrainedQP.doc)
.value("kGurobi", SolverType::kGurobi, doc.SolverType.kGurobi.doc)
.value("kIbex", SolverType::kIbex, doc.SolverType.kIbex.doc)
.value("kIpopt", SolverType::kIpopt, doc.SolverType.kIpopt.doc)
.value("kLinearSystem", SolverType::kLinearSystem,
doc.SolverType.kLinearSystem.doc)
Expand All @@ -476,6 +475,13 @@ void BindSolverInterfaceAndFlags(py::module m) {
.value("kScs", SolverType::kScs, doc.SolverType.kScs.doc)
.value("kSnopt", SolverType::kSnopt, doc.SolverType.kSnopt.doc);

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
solver_type // BR
.value("kDReal", SolverType::kDReal, "(Deprecated.)")
.value("kIbex", SolverType::kIbex, "(Deprecated.)");
#pragma GCC diagnostic pop

// TODO(jwnimmer-tri) Bind the accessors for SolverOptions.
py::class_<SolverOptions>(m, "SolverOptions", doc.SolverOptions.doc)
.def(py::init<>(), doc.SolverOptions.ctor.doc)
Expand Down
32 changes: 20 additions & 12 deletions bindings/pydrake/solvers/test/dreal_solver_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import numpy as np

from pydrake.common.containers import EqualToDict
from pydrake.common.test_utilities.deprecation import catch_drake_warnings
from pydrake.solvers import mathematicalprogram as mp
from pydrake.solvers.dreal import DrealSolver
from pydrake.symbolic import Variable, logical_and, logical_or
Expand All @@ -15,8 +16,11 @@ def test_dreal_solver(self):
prog = mp.MathematicalProgram()
x = prog.NewContinuousVariables(1, "x")
prog.AddBoundingBoxConstraint(-1, 1, x)
solver = DrealSolver()
self.assertEqual(solver.solver_id(), DrealSolver.id())
with catch_drake_warnings(expected_count=1):
solver = DrealSolver()
with catch_drake_warnings(expected_count=1):
dreal_id = DrealSolver.id()
self.assertEqual(solver.solver_id(), dreal_id)
self.assertTrue(solver.available())
self.assertEqual(solver.solver_id().name(), "dReal")
self.assertEqual(solver.SolverName(), "dReal")
Expand All @@ -25,7 +29,8 @@ def test_dreal_solver(self):
self.assertTrue(result.is_success())

def test_interval(self):
interval = DrealSolver.Interval(low=3.0, high=4.0)
with catch_drake_warnings(expected_count=1):
interval = DrealSolver.Interval(low=3.0, high=4.0)
self.assertEqual(interval.low(), 3.0)
self.assertEqual(interval.high(), 4.0)
self.assertEqual(interval.diam(), 1.0)
Expand All @@ -34,8 +39,9 @@ def test_interval(self):
def test_dreal_satisfiability(self):
x = Variable("x")
f = logical_and(x > 1, x < 2)
interval_box = EqualToDict(
DrealSolver.CheckSatisfiability(f=f, delta=0.01))
with catch_drake_warnings(expected_count=1):
interval_box = EqualToDict(
DrealSolver.CheckSatisfiability(f=f, delta=0.01))
self.assertEqual(len(interval_box), 1)
self.assertIsInstance(interval_box[x], DrealSolver.Interval)

Expand All @@ -47,18 +53,20 @@ def test_local_optimization(self):
def test_minimize(self):
x = Variable("x")
delta = 0.01
interval_box = EqualToDict(
DrealSolver.Minimize(
objective=x**2,
constraint=logical_and(x >= 1, x <= 10),
delta=delta,
local_optimization=DrealSolver.LocalOptimization.kUse))
with catch_drake_warnings(expected_count=1):
interval_box = EqualToDict(
DrealSolver.Minimize(
objective=x**2,
constraint=logical_and(x >= 1, x <= 10),
delta=delta,
local_optimization=DrealSolver.LocalOptimization.kUse))
self.assertEqual(len(interval_box), 1)
self.assertIsInstance(interval_box[x], DrealSolver.Interval)
print(interval_box[x].diam())
self.assertAlmostEqual(interval_box[x].mid(), 1.0, delta=delta)

def unavailable(self):
"""Per the BUILD file, this test is only run when dReal is disabled."""
solver = DrealSolver()
with catch_drake_warnings(expected_count=1):
solver = DrealSolver()
self.assertFalse(solver.available())
11 changes: 8 additions & 3 deletions bindings/pydrake/solvers/test/ibex_solver_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import numpy as np

from pydrake.common.test_utilities import numpy_compare
from pydrake.common.test_utilities.deprecation import catch_drake_warnings
from pydrake.solvers import mathematicalprogram as mp
from pydrake.solvers.ibex import IbexSolver

Expand All @@ -14,8 +15,11 @@ def test_ibex_solver(self):
prog.AddBoundingBoxConstraint(-1., 1., x[0])
prog.AddBoundingBoxConstraint(-1., 1., x[1])
prog.AddCost(x[0] - x[1])
solver = IbexSolver()
self.assertEqual(solver.solver_id(), IbexSolver.id())
with catch_drake_warnings(expected_count=1):
solver = IbexSolver()
with catch_drake_warnings(expected_count=1):
ibex_id = IbexSolver.id()
self.assertEqual(solver.solver_id(), ibex_id)

self.assertTrue(solver.available())
self.assertEqual(solver.solver_id().name(), "IBEX")
Expand All @@ -29,5 +33,6 @@ def test_ibex_solver(self):

def unavailable(self):
"""Per the BUILD file, this test is only run when Ibex is disabled."""
solver = IbexSolver()
with catch_drake_warnings(expected_count=1):
solver = IbexSolver()
self.assertFalse(solver.available())
2 changes: 2 additions & 0 deletions solvers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,7 @@ drake_cc_googletest(
drake_cc_googletest(
name = "dreal_solver_test",
timeout = "moderate",
copts = ["-Wno-deprecated-declarations"],
# For most of floating-point operations, Valgrind core only supports the
# IEEE default mode (round to nearest) while dReal uses to +infinity
# and to -infinity rounding modes intensively to maintain conservative
Expand Down Expand Up @@ -1348,6 +1349,7 @@ drake_cc_googletest(

drake_cc_googletest(
name = "ibex_solver_test",
copts = ["-Wno-deprecated-declarations"],
deps = [
":generic_trivial_constraint",
":generic_trivial_cost",
Expand Down
5 changes: 5 additions & 0 deletions solvers/dreal_solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#include "drake/common/text_logging.h"
#include "drake/solvers/mathematical_program.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

namespace drake {
namespace solvers {

Expand Down Expand Up @@ -603,3 +606,5 @@ void DrealSolver::DoSolve(

} // namespace solvers
} // namespace drake

#pragma GCC diagnostic pop
Loading

0 comments on commit b034166

Please sign in to comment.