forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
integer_optimization_util.cc
78 lines (73 loc) · 3.13 KB
/
integer_optimization_util.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "drake/solvers/integer_optimization_util.h"
#include "drake/solvers/binding.h"
#include "drake/solvers/create_constraint.h"
namespace drake {
namespace solvers {
Binding<LinearConstraint> CreateLogicalAndConstraint(
const symbolic::Expression& b1, const symbolic::Expression& b2,
const symbolic::Expression& b1_and_b2) {
return internal::BindingDynamicCast<LinearConstraint>(
// clang-format off
internal::ParseConstraint(b1_and_b2 >= b1 + b2 - 1 &&
b1_and_b2 <= b1 &&
b1_and_b2 <= b2 &&
0 <= b1_and_b2 &&
b1_and_b2 <= 1));
// clang-format on
}
Binding<LinearConstraint> CreateLogicalOrConstraint(
const symbolic::Expression& b1, const symbolic::Expression& b2,
const symbolic::Expression& b1_or_b2) {
return internal::BindingDynamicCast<LinearConstraint>(
// clang-format off
internal::ParseConstraint(b1_or_b2 <= b1 + b2 &&
b1_or_b2 >= b1 &&
b1_or_b2 >= b2 &&
0 <= b1_or_b2 &&
b1_or_b2 <= 1));
// clang-format on
}
Binding<LinearConstraint> CreateLogicalXorConstraint(
const symbolic::Expression& b1, const symbolic::Expression& b2,
const symbolic::Expression& b1_xor_b2) {
return internal::BindingDynamicCast<LinearConstraint>(
// clang-format off
internal::ParseConstraint(b1_xor_b2 <= b1 + b2 &&
b1_xor_b2 >= b1 - b2 &&
b1_xor_b2 >= b2 - b1 &&
b1_xor_b2 <= 2 - b1 - b2 &&
0 <= b1_xor_b2 &&
b1_xor_b2 <= 1));
// clang-format on
}
Binding<LinearConstraint> CreateBinaryCodeMatchConstraint(
const VectorX<symbolic::Expression>& code,
const Eigen::Ref<const Eigen::VectorXi>& expected,
const symbolic::Expression& match) {
DRAKE_ASSERT(code.rows() == expected.rows());
// match_element(i) = 1 <=> code(i) = expected(i).
// We then take the conjunction
// match = match_element(0) && match_element(1) && ... && match_element(n)
// This conjunction can be transformed to the following constraints
// match >= match_element(0) + match_element(1) + ... + match_element(n) - n
// match <= match_element(i) ∀i
// 0 <= match <= 1
VectorX<symbolic::Expression> match_element(code.rows());
symbolic::Formula f = match >= 0 && match <= 1;
for (int i = 0; i < code.rows(); ++i) {
// match_element(i) = 1 iff code(i) == expected(i)
if (expected(i) == 1) {
match_element(i) = code(i);
} else if (expected(i) == 0) {
match_element(i) = 1 - code(i);
} else {
throw std::logic_error("expected should only contain either 0 or 1.");
}
f = f && match <= match_element(i);
}
f = f && match >= match_element.sum() - (code.rows() - 1);
return internal::BindingDynamicCast<LinearConstraint>(
internal::ParseConstraint(f));
}
} // namespace solvers
} // namespace drake