Skip to content

Commit

Permalink
Leverage parallelization where possible when checking boundedness of …
Browse files Browse the repository at this point in the history
…a ConvexSet. (#22084)

This parallelizes the generic method for checking boundedness of a convex set, which is sometimes used by various derived classes of ConvexSet.

Also fixes a bug in the boundedness check of MinkowskiSum.
  • Loading branch information
cohnt authored Nov 5, 2024
1 parent bf2408a commit bde2f2d
Show file tree
Hide file tree
Showing 28 changed files with 414 additions and 84 deletions.
4 changes: 3 additions & 1 deletion bindings/pydrake/geometry/geometry_py_optimization.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ void DefineConvexSetBaseClassAndSubclasses(py::module m) {
cls_doc.ambient_dimension.doc)
.def("IntersectsWith", &ConvexSet::IntersectsWith, py::arg("other"),
cls_doc.IntersectsWith.doc)
.def("IsBounded", &ConvexSet::IsBounded, cls_doc.IsBounded.doc)
.def("IsBounded", &ConvexSet::IsBounded,
py::arg("parallelism") = Parallelism::None(),
py::call_guard<py::gil_scoped_release>(), cls_doc.IsBounded.doc)
.def("IsEmpty", &ConvexSet::IsEmpty, cls_doc.IsEmpty.doc)
.def("MaybeGetPoint", &ConvexSet::MaybeGetPoint,
cls_doc.MaybeGetPoint.doc)
Expand Down
3 changes: 2 additions & 1 deletion bindings/pydrake/geometry/test/optimization_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import numpy as np

from pydrake.common import RandomGenerator, temp_directory
from pydrake.common import RandomGenerator, temp_directory, Parallelism
from pydrake.common.test_utilities.deprecation import catch_drake_warnings
from pydrake.common.test_utilities.pickle_compare import assert_pickle
from pydrake.geometry import (
Expand Down Expand Up @@ -456,6 +456,7 @@ def test_spectrahedron(self):
self.assertFalse(s.IsEmpty())
self.assertFalse(s.MaybeGetFeasiblePoint() is None)
self.assertTrue(s.PointInSet(s.MaybeGetFeasiblePoint()))
self.assertTrue(s.IsBounded(Parallelism.Max()))

def test_v_polytope(self):
mut.VPolytope()
Expand Down
3 changes: 3 additions & 0 deletions geometry/optimization/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ drake_cc_library(
"//solvers:mosek_solver",
"//solvers:scs_solver",
"//solvers:solve",
"@common_robotics_utilities",
"@qhull_internal//:qhull",
],
)
Expand Down Expand Up @@ -536,6 +537,7 @@ drake_cc_googletest(

drake_cc_googletest(
name = "intersection_test",
num_threads = 2,
deps = [
":convex_set",
":test_utilities",
Expand Down Expand Up @@ -612,6 +614,7 @@ drake_cc_googletest(

drake_cc_googletest(
name = "spectrahedron_test",
num_threads = 2,
deps = [
":convex_set",
"//common/test_utilities:eigen_matrix_compare",
Expand Down
4 changes: 4 additions & 0 deletions geometry/optimization/affine_ball.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ double AffineBall::DoCalcVolume() const {
std::abs(B_.determinant());
}

std::optional<bool> AffineBall::DoIsBoundedShortcut() const {
return true;
}

AffineBall AffineBall::MakeAxisAligned(
const Eigen::Ref<const VectorXd>& radius,
const Eigen::Ref<const VectorXd>& center) {
Expand Down
8 changes: 7 additions & 1 deletion geometry/optimization/affine_ball.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,17 @@ class AffineBall final : public ConvexSet {
CheckInvariants();
}

/** Every AffineBall is bounded by construction.
@param parallelism Ignored -- no parallelization is used.
@note See @ref ConvexSet::IsBounded "parent class's documentation" for more
details. */
using ConvexSet::IsBounded;

private:
std::unique_ptr<ConvexSet> DoClone() const final;

/* AffineBall can only represent bounded sets. */
std::optional<bool> DoIsBoundedShortcut() const final { return true; };
std::optional<bool> DoIsBoundedShortcut() const final;

/* AffineBall can only represent nonempty sets. */
bool DoIsEmpty() const final { return false; };
Expand Down
7 changes: 7 additions & 0 deletions geometry/optimization/affine_subspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ class AffineSubspace final : public ConvexSet {
to this AffineSubspace.*/
Eigen::MatrixXd OrthogonalComplementBasis() const;

/** An AffineSubspace is bounded if and only if it is zero-dimensional (i.e.,
a point).
@param parallelism Ignored -- no parallelization is used.
@note See @ref ConvexSet::IsBounded "parent class's documentation" for more
details. */
using ConvexSet::IsBounded;

private:
std::unique_ptr<ConvexSet> DoClone() const final;

Expand Down
5 changes: 3 additions & 2 deletions geometry/optimization/cartesian_product.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,11 @@ std::unique_ptr<ConvexSet> CartesianProduct::DoClone() const {
return std::make_unique<CartesianProduct>(*this);
}

std::optional<bool> CartesianProduct::DoIsBoundedShortcut() const {
std::optional<bool> CartesianProduct::DoIsBoundedShortcutParallel(
Parallelism parallelism) const {
// Note: The constructor enforces that A_ is full column rank.
for (const auto& s : sets_) {
if (!s->IsBounded()) {
if (!s->IsBounded(parallelism)) {
return false;
}
}
Expand Down
11 changes: 10 additions & 1 deletion geometry/optimization/cartesian_product.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,19 @@ class CartesianProduct final : public ConvexSet {
product. */
using ConvexSet::CalcVolume;

/** A CartesianProduct is bounded if and only if each constituent set is
bounded. This class honors requests for parallelism only so far as its
constituent sets do.
@param parallelism The maximum number of threads to use.
@note See @ref ConvexSet::IsBounded "parent class's documentation" for more
details. */
using ConvexSet::IsBounded;

private:
std::unique_ptr<ConvexSet> DoClone() const final;

std::optional<bool> DoIsBoundedShortcut() const final;
std::optional<bool> DoIsBoundedShortcutParallel(
Parallelism parallelism) const final;

bool DoIsEmpty() const final;

Expand Down
10 changes: 8 additions & 2 deletions geometry/optimization/convex_hull.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,14 @@ std::unique_ptr<ConvexSet> ConvexHull::DoClone() const {
return std::make_unique<ConvexHull>(*this);
}

std::optional<bool> ConvexHull::DoIsBoundedShortcut() const {
return std::nullopt;
std::optional<bool> ConvexHull::DoIsBoundedShortcutParallel(
Parallelism parallelism) const {
for (const auto& s : sets_) {
if (!s->IsBounded(parallelism)) {
return false;
}
}
return true;
}

bool ConvexHull::DoIsEmpty() const {
Expand Down
11 changes: 10 additions & 1 deletion geometry/optimization/convex_hull.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,19 @@ class ConvexHull final : public ConvexSet, private ShapeReifier {
/** @throws Not implemented. */
using ConvexSet::CalcVolume;

/** A ConvexHull is bounded if and only if each constituent set is bounded.
This class honors requests for parallelism only so far as its constituent sets
do.
@param parallelism The maximum number of threads to use.
@note See @ref ConvexSet::IsBounded "parent class's documentation" for more
details. */
using ConvexSet::IsBounded;

private:
std::unique_ptr<ConvexSet> DoClone() const final;

std::optional<bool> DoIsBoundedShortcut() const final;
std::optional<bool> DoIsBoundedShortcutParallel(
Parallelism parallelism) const final;

bool DoIsEmpty() const final;

Expand Down
Loading

0 comments on commit bde2f2d

Please sign in to comment.