blob: 5028e01f4ac6f98b6dd3426c7bad9cca5382a979 [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2015 Google Inc. All rights reserved.
3// 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
43namespace ceres {
44namespace internal {
45
46using std::set;
47using std::vector;
48
49class VisibilityTest : public ::testing::Test {
50};
51
52TEST(VisibilityTest, SimpleMatrix) {
53 // A = [1 0 0 0 0 1
54 // 1 0 0 1 0 0
55 // 0 1 1 0 0 0
56 // 0 1 0 0 1 0]
57
58 int num_cols = 6;
59 int num_eliminate_blocks = 2;
60 CompressedRowBlockStructure bs;
61
62 // Row 1
63 {
64 bs.rows.push_back(CompressedRow());
65 CompressedRow& row = bs.rows.back();
66 row.block.size = 2;
67 row.block.position = 0;
68 row.cells.push_back(Cell(0, 0));
69 row.cells.push_back(Cell(5, 0));
70 }
71
72 // Row 2
73 {
74 bs.rows.push_back(CompressedRow());
75 CompressedRow& row = bs.rows.back();
76 row.block.size = 2;
77 row.block.position = 2;
78 row.cells.push_back(Cell(0, 1));
79 row.cells.push_back(Cell(3, 1));
80 }
81
82 // Row 3
83 {
84 bs.rows.push_back(CompressedRow());
85 CompressedRow& row = bs.rows.back();
86 row.block.size = 2;
87 row.block.position = 4;
88 row.cells.push_back(Cell(1, 2));
89 row.cells.push_back(Cell(2, 2));
90 }
91
92 // Row 4
93 {
94 bs.rows.push_back(CompressedRow());
95 CompressedRow& row = bs.rows.back();
96 row.block.size = 2;
97 row.block.position = 6;
98 row.cells.push_back(Cell(1, 3));
99 row.cells.push_back(Cell(4, 3));
100 }
101 bs.cols.resize(num_cols);
102
103 vector< set<int>> visibility;
104 ComputeVisibility(bs, num_eliminate_blocks, &visibility);
105 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks);
106 for (int i = 0; i < visibility.size(); ++i) {
107 ASSERT_EQ(visibility[i].size(), 1);
108 }
109
110 std::unique_ptr<WeightedGraph<int> > graph(CreateSchurComplementGraph(visibility));
111 EXPECT_EQ(graph->vertices().size(), visibility.size());
112 for (int i = 0; i < visibility.size(); ++i) {
113 EXPECT_EQ(graph->VertexWeight(i), 1.0);
114 }
115
116 for (int i = 0; i < visibility.size(); ++i) {
117 for (int j = i; j < visibility.size(); ++j) {
118 double edge_weight = 0.0;
119 if ((i == 1 && j == 3) || (i == 0 && j == 2) || (i == j)) {
120 edge_weight = 1.0;
121 }
122
123 EXPECT_EQ(graph->EdgeWeight(i, j), edge_weight)
124 << "Edge: " << i << " " << j
125 << " weight: " << graph->EdgeWeight(i, j)
126 << " expected weight: " << edge_weight;
127 }
128 }
129}
130
131
132TEST(VisibilityTest, NoEBlocks) {
133 // A = [1 0 0 0 0 0
134 // 1 0 0 0 0 0
135 // 0 1 0 0 0 0
136 // 0 1 0 0 0 0]
137
138 int num_cols = 6;
139 int num_eliminate_blocks = 2;
140 CompressedRowBlockStructure bs;
141
142 // Row 1
143 {
144 bs.rows.push_back(CompressedRow());
145 CompressedRow& row = bs.rows.back();
146 row.block.size = 2;
147 row.block.position = 0;
148 row.cells.push_back(Cell(0, 0));
149 }
150
151 // Row 2
152 {
153 bs.rows.push_back(CompressedRow());
154 CompressedRow& row = bs.rows.back();
155 row.block.size = 2;
156 row.block.position = 2;
157 row.cells.push_back(Cell(0, 1));
158 }
159
160 // Row 3
161 {
162 bs.rows.push_back(CompressedRow());
163 CompressedRow& row = bs.rows.back();
164 row.block.size = 2;
165 row.block.position = 4;
166 row.cells.push_back(Cell(1, 2));
167 }
168
169 // Row 4
170 {
171 bs.rows.push_back(CompressedRow());
172 CompressedRow& row = bs.rows.back();
173 row.block.size = 2;
174 row.block.position = 6;
175 row.cells.push_back(Cell(1, 3));
176 }
177 bs.cols.resize(num_cols);
178
179 vector<set<int>> visibility;
180 ComputeVisibility(bs, num_eliminate_blocks, &visibility);
181 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks);
182 for (int i = 0; i < visibility.size(); ++i) {
183 ASSERT_EQ(visibility[i].size(), 0);
184 }
185
186 std::unique_ptr<WeightedGraph<int> > graph(
187 CreateSchurComplementGraph(visibility));
188 EXPECT_EQ(graph->vertices().size(), visibility.size());
189 for (int i = 0; i < visibility.size(); ++i) {
190 EXPECT_EQ(graph->VertexWeight(i), 1.0);
191 }
192
193 for (int i = 0; i < visibility.size(); ++i) {
194 for (int j = i; j < visibility.size(); ++j) {
195 double edge_weight = 0.0;
196 if (i == j) {
197 edge_weight = 1.0;
198 }
199 EXPECT_EQ(graph->EdgeWeight(i, j), edge_weight)
200 << "Edge: " << i << " " << j
201 << " weight: " << graph->EdgeWeight(i, j)
202 << " expected weight: " << edge_weight;
203 }
204 }
205}
206
207} // namespace internal
208} // namespace ceres