Skip to content

Commit 8493078

Browse files
authored
Merge pull request #2332 from borglab/fix/constraints
Handle noise and NonlinearEquality constraints
2 parents 90f6f33 + d2d3280 commit 8493078

16 files changed

+925
-418
lines changed

gtsam/base/SymmetricBlockMatrix.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,25 @@ VerticalBlockMatrix SymmetricBlockMatrix::split(DenseIndex nFrontals) {
107107
}
108108

109109
/* ************************************************************************* */
110+
void SymmetricBlockMatrix::updateFromMappedBlocks(
111+
const SymmetricBlockMatrix& other,
112+
const std::vector<DenseIndex>& blockIndices) {
113+
assert(static_cast<DenseIndex>(blockIndices.size()) == other.nBlocks());
114+
const DenseIndex otherBlocks = other.nBlocks();
115+
for (DenseIndex i = 0; i < otherBlocks; ++i) {
116+
const DenseIndex I = blockIndices[i];
117+
if (I < 0) continue;
118+
assert(I < nBlocks());
119+
updateDiagonalBlock(I, other.diagonalBlock(i));
120+
for (DenseIndex j = i + 1; j < otherBlocks; ++j) {
121+
const DenseIndex J = blockIndices[j];
122+
if (J < 0) continue;
123+
assert(J < nBlocks());
124+
updateOffDiagonalBlock(I, J, other.aboveDiagonalBlock(i, j));
125+
}
126+
}
127+
}
110128

111-
} //\ namespace gtsam
129+
/* ************************************************************************* */
112130

131+
} //\ namespace gtsam

gtsam/base/SymmetricBlockMatrix.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <cassert>
2828
#include <stdexcept>
2929
#include <array>
30+
#include <vector>
3031

3132
namespace boost {
3233
namespace serialization {
@@ -245,6 +246,11 @@ namespace gtsam {
245246
}
246247
}
247248

249+
/// Update this matrix with blocks from another block matrix using a mapping.
250+
/// Entries with index -1 are skipped.
251+
void updateFromMappedBlocks(const SymmetricBlockMatrix& other,
252+
const std::vector<DenseIndex>& blockIndices);
253+
248254
/// @}
249255
/// @name Accessing the full matrix.
250256
/// @{

gtsam/base/tests/testSymmetricBlockMatrix.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ static SymmetricBlockMatrix testBlockMatrix(
3232
6, 12, 18, 24, 30, 36).finished());
3333

3434
/* ************************************************************************* */
35+
// Read block accessors.
3536
TEST(SymmetricBlockMatrix, ReadBlocks)
3637
{
3738
// On the diagonal
@@ -51,6 +52,7 @@ TEST(SymmetricBlockMatrix, ReadBlocks)
5152
}
5253

5354
/* ************************************************************************* */
55+
// Write block setters.
5456
TEST(SymmetricBlockMatrix, WriteBlocks)
5557
{
5658
// On the diagonal
@@ -77,6 +79,7 @@ TEST(SymmetricBlockMatrix, WriteBlocks)
7779
}
7880

7981
/* ************************************************************************* */
82+
// Verify block range access.
8083
TEST(SymmetricBlockMatrix, Ranges)
8184
{
8285
// On the diagonal
@@ -97,6 +100,7 @@ TEST(SymmetricBlockMatrix, Ranges)
97100
}
98101

99102
/* ************************************************************************* */
103+
// Exercise block expression helpers.
100104
TEST(SymmetricBlockMatrix, expressions)
101105
{
102106
const std::vector<size_t> dimensions{2, 3, 1};
@@ -151,6 +155,40 @@ TEST(SymmetricBlockMatrix, expressions)
151155
}
152156

153157
/* ************************************************************************* */
158+
// Update via block mapping.
159+
TEST(SymmetricBlockMatrix, UpdateFromMappedBlocks)
160+
{
161+
const std::vector<size_t> destDims{1, 3, 2};
162+
const std::vector<DenseIndex> mapping{1, 2, 0};
163+
164+
SymmetricBlockMatrix actual(destDims);
165+
actual.setZero();
166+
actual.updateFromMappedBlocks(testBlockMatrix, mapping);
167+
168+
SymmetricBlockMatrix expected(destDims);
169+
expected.setZero();
170+
for (DenseIndex i = 0; i < testBlockMatrix.nBlocks(); ++i) {
171+
const DenseIndex I = static_cast<DenseIndex>(mapping[i]);
172+
expected.updateDiagonalBlock(I, testBlockMatrix.diagonalBlock(i));
173+
for (DenseIndex j = i + 1; j < testBlockMatrix.nBlocks(); ++j) {
174+
const DenseIndex J = static_cast<DenseIndex>(mapping[j]);
175+
expected.setOffDiagonalBlock(I, J,
176+
testBlockMatrix.aboveDiagonalBlock(i, j));
177+
}
178+
}
179+
EXPECT(assert_equal(Matrix(expected.selfadjointView()),
180+
actual.selfadjointView()));
181+
182+
SymmetricBlockMatrix doubled(destDims);
183+
doubled.setZero();
184+
doubled.updateFromMappedBlocks(testBlockMatrix, mapping);
185+
doubled.updateFromMappedBlocks(testBlockMatrix, mapping);
186+
EXPECT(assert_equal(2.0 * Matrix(expected.selfadjointView()),
187+
Matrix(doubled.selfadjointView())));
188+
}
189+
190+
/* ************************************************************************* */
191+
// In-place inversion path.
154192
TEST(SymmetricBlockMatrix, inverseInPlace) {
155193
// generate an invertible matrix
156194
const Vector3 a(1.0, 0.2, 2.0), b(0.3, 0.8, -1.0), c(0.1, 0.2, 0.7);
@@ -171,4 +209,3 @@ TEST(SymmetricBlockMatrix, inverseInPlace) {
171209
/* ************************************************************************* */
172210
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
173211
/* ************************************************************************* */
174-

gtsam/inference/ClusterTree-inst.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,34 @@ std::vector<size_t> ClusterTree<GRAPH>::Cluster::nrFrontalsOfChildren() const {
4040
return nrFrontals;
4141
}
4242

43+
/* ************************************************************************* */
44+
template <class GRAPH>
45+
KeySet ClusterTree<GRAPH>::Cluster::separatorKeys(KeySetMap* cache) const {
46+
if (cache) {
47+
auto it = cache->find(this);
48+
if (it != cache->end()) return it->second;
49+
}
50+
51+
KeySet keys;
52+
for (const auto& factor : factors) {
53+
if (!factor) continue;
54+
keys.insert(factor->begin(), factor->end());
55+
}
56+
for (const auto& child : children) {
57+
KeySet childSeparators = child->separatorKeys(cache);
58+
keys.insert(childSeparators.begin(), childSeparators.end());
59+
}
60+
for (Key key : orderedFrontalKeys) {
61+
keys.erase(key);
62+
}
63+
64+
if (cache) {
65+
auto result = cache->emplace(this, std::move(keys));
66+
return result.first->second;
67+
}
68+
return keys;
69+
}
70+
4371
/* ************************************************************************* */
4472
template <class GRAPH>
4573
void ClusterTree<GRAPH>::Cluster::merge(const std::shared_ptr<Cluster>& cluster) {

gtsam/inference/ClusterTree.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#pragma once
1111

1212
#include <gtsam/base/Testable.h>
13+
#include <gtsam/base/FastMap.h>
1314
#include <gtsam/base/FastVector.h>
1415
#include <gtsam/inference/Ordering.h>
1516

@@ -96,6 +97,11 @@ class ClusterTree {
9697
/// Return a vector with nrFrontal keys for each child
9798
std::vector<size_t> nrFrontalsOfChildren() const;
9899

100+
using KeySetMap = FastMap<const Cluster*, KeySet>;
101+
102+
/// Return the separator keys (subtree keys minus frontals), optionally cached.
103+
KeySet separatorKeys(KeySetMap* cache = nullptr) const;
104+
99105
/// Merge in given cluster
100106
void merge(const std::shared_ptr<Cluster>& cluster);
101107

gtsam/linear/HessianFactor.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -357,19 +357,7 @@ void HessianFactor::updateHessian(const KeyVector& infoKeys,
357357
slots[j] = Slot(infoKeys, keys_[j]);
358358
slots[nrVariablesInThisFactor] = info->nBlocks() - 1;
359359

360-
// Apply updates to the upper triangle
361-
// Loop over this factor's blocks with indices (i,j)
362-
// For every block (i,j), we determine the block (I,J) in info.
363-
for (DenseIndex j = 0; j <= nrVariablesInThisFactor; ++j) {
364-
const DenseIndex J = slots[j];
365-
info->updateDiagonalBlock(J, info_.diagonalBlock(j));
366-
for (DenseIndex i = 0; i < j; ++i) {
367-
const DenseIndex I = slots[i];
368-
assert(i < j);
369-
assert(I != J);
370-
info->updateOffDiagonalBlock(I, J, info_.aboveDiagonalBlock(i, j));
371-
}
372-
}
360+
info->updateFromMappedBlocks(info_, slots);
373361
}
374362

375363
/* ************************************************************************* */

0 commit comments

Comments
 (0)