blob: 3efc77cc1efc97fda84c71ed9ec7ec53ab3ccf99 [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
Austin Schuh3de38b02024-06-25 18:25:10 -07002// Copyright 2023 Google Inc. All rights reserved.
Austin Schuh70cc9552019-01-21 19:46:48 -08003// http://ceres-solver.org/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28//
29// Author: kushalav@google.com (Avanish Kushal)
30// sameeragarwal@google.com (Sameer Agarwal)
31
32#include "ceres/visibility.h"
33
34#include <memory>
35#include <set>
36#include <vector>
37
38#include "ceres/block_structure.h"
39#include "ceres/graph.h"
40#include "glog/logging.h"
41#include "gtest/gtest.h"
42
Austin Schuh3de38b02024-06-25 18:25:10 -070043namespace ceres::internal {
Austin Schuh70cc9552019-01-21 19:46:48 -080044
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080045class VisibilityTest : public ::testing::Test {};
Austin Schuh70cc9552019-01-21 19:46:48 -080046
47TEST(VisibilityTest, SimpleMatrix) {
48 // A = [1 0 0 0 0 1
49 // 1 0 0 1 0 0
50 // 0 1 1 0 0 0
51 // 0 1 0 0 1 0]
52
53 int num_cols = 6;
54 int num_eliminate_blocks = 2;
55 CompressedRowBlockStructure bs;
56
57 // Row 1
58 {
Austin Schuh3de38b02024-06-25 18:25:10 -070059 bs.rows.emplace_back();
Austin Schuh70cc9552019-01-21 19:46:48 -080060 CompressedRow& row = bs.rows.back();
61 row.block.size = 2;
62 row.block.position = 0;
Austin Schuh3de38b02024-06-25 18:25:10 -070063 row.cells.emplace_back(0, 0);
64 row.cells.emplace_back(5, 0);
Austin Schuh70cc9552019-01-21 19:46:48 -080065 }
66
67 // Row 2
68 {
Austin Schuh3de38b02024-06-25 18:25:10 -070069 bs.rows.emplace_back();
Austin Schuh70cc9552019-01-21 19:46:48 -080070 CompressedRow& row = bs.rows.back();
71 row.block.size = 2;
72 row.block.position = 2;
Austin Schuh3de38b02024-06-25 18:25:10 -070073 row.cells.emplace_back(0, 1);
74 row.cells.emplace_back(3, 1);
Austin Schuh70cc9552019-01-21 19:46:48 -080075 }
76
77 // Row 3
78 {
Austin Schuh3de38b02024-06-25 18:25:10 -070079 bs.rows.emplace_back();
Austin Schuh70cc9552019-01-21 19:46:48 -080080 CompressedRow& row = bs.rows.back();
81 row.block.size = 2;
82 row.block.position = 4;
Austin Schuh3de38b02024-06-25 18:25:10 -070083 row.cells.emplace_back(1, 2);
84 row.cells.emplace_back(2, 2);
Austin Schuh70cc9552019-01-21 19:46:48 -080085 }
86
87 // Row 4
88 {
Austin Schuh3de38b02024-06-25 18:25:10 -070089 bs.rows.emplace_back();
Austin Schuh70cc9552019-01-21 19:46:48 -080090 CompressedRow& row = bs.rows.back();
91 row.block.size = 2;
92 row.block.position = 6;
Austin Schuh3de38b02024-06-25 18:25:10 -070093 row.cells.emplace_back(1, 3);
94 row.cells.emplace_back(4, 3);
Austin Schuh70cc9552019-01-21 19:46:48 -080095 }
96 bs.cols.resize(num_cols);
97
Austin Schuh3de38b02024-06-25 18:25:10 -070098 std::vector<std::set<int>> visibility;
Austin Schuh70cc9552019-01-21 19:46:48 -080099 ComputeVisibility(bs, num_eliminate_blocks, &visibility);
100 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks);
Austin Schuh3de38b02024-06-25 18:25:10 -0700101 for (const auto& visible : visibility) {
102 ASSERT_EQ(visible.size(), 1);
Austin Schuh70cc9552019-01-21 19:46:48 -0800103 }
104
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800105 std::unique_ptr<WeightedGraph<int>> graph(
106 CreateSchurComplementGraph(visibility));
Austin Schuh70cc9552019-01-21 19:46:48 -0800107 EXPECT_EQ(graph->vertices().size(), visibility.size());
108 for (int i = 0; i < visibility.size(); ++i) {
109 EXPECT_EQ(graph->VertexWeight(i), 1.0);
110 }
111
112 for (int i = 0; i < visibility.size(); ++i) {
113 for (int j = i; j < visibility.size(); ++j) {
114 double edge_weight = 0.0;
115 if ((i == 1 && j == 3) || (i == 0 && j == 2) || (i == j)) {
116 edge_weight = 1.0;
117 }
118
119 EXPECT_EQ(graph->EdgeWeight(i, j), edge_weight)
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800120 << "Edge: " << i << " " << j << " weight: " << graph->EdgeWeight(i, j)
Austin Schuh70cc9552019-01-21 19:46:48 -0800121 << " expected weight: " << edge_weight;
122 }
123 }
124}
125
Austin Schuh70cc9552019-01-21 19:46:48 -0800126TEST(VisibilityTest, NoEBlocks) {
127 // A = [1 0 0 0 0 0
128 // 1 0 0 0 0 0
129 // 0 1 0 0 0 0
130 // 0 1 0 0 0 0]
131
132 int num_cols = 6;
133 int num_eliminate_blocks = 2;
134 CompressedRowBlockStructure bs;
135
136 // Row 1
137 {
Austin Schuh3de38b02024-06-25 18:25:10 -0700138 bs.rows.emplace_back();
Austin Schuh70cc9552019-01-21 19:46:48 -0800139 CompressedRow& row = bs.rows.back();
140 row.block.size = 2;
141 row.block.position = 0;
Austin Schuh3de38b02024-06-25 18:25:10 -0700142 row.cells.emplace_back(0, 0);
Austin Schuh70cc9552019-01-21 19:46:48 -0800143 }
144
145 // Row 2
146 {
Austin Schuh3de38b02024-06-25 18:25:10 -0700147 bs.rows.emplace_back();
Austin Schuh70cc9552019-01-21 19:46:48 -0800148 CompressedRow& row = bs.rows.back();
149 row.block.size = 2;
150 row.block.position = 2;
Austin Schuh3de38b02024-06-25 18:25:10 -0700151 row.cells.emplace_back(0, 1);
Austin Schuh70cc9552019-01-21 19:46:48 -0800152 }
153
154 // Row 3
155 {
Austin Schuh3de38b02024-06-25 18:25:10 -0700156 bs.rows.emplace_back();
Austin Schuh70cc9552019-01-21 19:46:48 -0800157 CompressedRow& row = bs.rows.back();
158 row.block.size = 2;
159 row.block.position = 4;
Austin Schuh3de38b02024-06-25 18:25:10 -0700160 row.cells.emplace_back(1, 2);
Austin Schuh70cc9552019-01-21 19:46:48 -0800161 }
162
163 // Row 4
164 {
Austin Schuh3de38b02024-06-25 18:25:10 -0700165 bs.rows.emplace_back();
Austin Schuh70cc9552019-01-21 19:46:48 -0800166 CompressedRow& row = bs.rows.back();
167 row.block.size = 2;
168 row.block.position = 6;
Austin Schuh3de38b02024-06-25 18:25:10 -0700169 row.cells.emplace_back(1, 3);
Austin Schuh70cc9552019-01-21 19:46:48 -0800170 }
171 bs.cols.resize(num_cols);
172
Austin Schuh3de38b02024-06-25 18:25:10 -0700173 std::vector<std::set<int>> visibility;
Austin Schuh70cc9552019-01-21 19:46:48 -0800174 ComputeVisibility(bs, num_eliminate_blocks, &visibility);
175 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks);
Austin Schuh3de38b02024-06-25 18:25:10 -0700176 for (const auto& visible : visibility) {
177 ASSERT_EQ(visible.size(), 0);
Austin Schuh70cc9552019-01-21 19:46:48 -0800178 }
179
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800180 std::unique_ptr<WeightedGraph<int>> graph(
181 CreateSchurComplementGraph(visibility));
Austin Schuh70cc9552019-01-21 19:46:48 -0800182 EXPECT_EQ(graph->vertices().size(), visibility.size());
183 for (int i = 0; i < visibility.size(); ++i) {
184 EXPECT_EQ(graph->VertexWeight(i), 1.0);
185 }
186
187 for (int i = 0; i < visibility.size(); ++i) {
188 for (int j = i; j < visibility.size(); ++j) {
189 double edge_weight = 0.0;
190 if (i == j) {
191 edge_weight = 1.0;
192 }
193 EXPECT_EQ(graph->EdgeWeight(i, j), edge_weight)
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800194 << "Edge: " << i << " " << j << " weight: " << graph->EdgeWeight(i, j)
Austin Schuh70cc9552019-01-21 19:46:48 -0800195 << " expected weight: " << edge_weight;
196 }
197 }
198}
199
Austin Schuh3de38b02024-06-25 18:25:10 -0700200} // namespace ceres::internal