blob: a1999635b2bd1a9dbbfad32f2812839081d2999d [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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080049class VisibilityTest : public ::testing::Test {};
Austin Schuh70cc9552019-01-21 19:46:48 -080050
51TEST(VisibilityTest, SimpleMatrix) {
52 // A = [1 0 0 0 0 1
53 // 1 0 0 1 0 0
54 // 0 1 1 0 0 0
55 // 0 1 0 0 1 0]
56
57 int num_cols = 6;
58 int num_eliminate_blocks = 2;
59 CompressedRowBlockStructure bs;
60
61 // Row 1
62 {
63 bs.rows.push_back(CompressedRow());
64 CompressedRow& row = bs.rows.back();
65 row.block.size = 2;
66 row.block.position = 0;
67 row.cells.push_back(Cell(0, 0));
68 row.cells.push_back(Cell(5, 0));
69 }
70
71 // Row 2
72 {
73 bs.rows.push_back(CompressedRow());
74 CompressedRow& row = bs.rows.back();
75 row.block.size = 2;
76 row.block.position = 2;
77 row.cells.push_back(Cell(0, 1));
78 row.cells.push_back(Cell(3, 1));
79 }
80
81 // Row 3
82 {
83 bs.rows.push_back(CompressedRow());
84 CompressedRow& row = bs.rows.back();
85 row.block.size = 2;
86 row.block.position = 4;
87 row.cells.push_back(Cell(1, 2));
88 row.cells.push_back(Cell(2, 2));
89 }
90
91 // Row 4
92 {
93 bs.rows.push_back(CompressedRow());
94 CompressedRow& row = bs.rows.back();
95 row.block.size = 2;
96 row.block.position = 6;
97 row.cells.push_back(Cell(1, 3));
98 row.cells.push_back(Cell(4, 3));
99 }
100 bs.cols.resize(num_cols);
101
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800102 vector<set<int>> visibility;
Austin Schuh70cc9552019-01-21 19:46:48 -0800103 ComputeVisibility(bs, num_eliminate_blocks, &visibility);
104 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks);
105 for (int i = 0; i < visibility.size(); ++i) {
106 ASSERT_EQ(visibility[i].size(), 1);
107 }
108
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800109 std::unique_ptr<WeightedGraph<int>> graph(
110 CreateSchurComplementGraph(visibility));
Austin Schuh70cc9552019-01-21 19:46:48 -0800111 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)
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800124 << "Edge: " << i << " " << j << " weight: " << graph->EdgeWeight(i, j)
Austin Schuh70cc9552019-01-21 19:46:48 -0800125 << " expected weight: " << edge_weight;
126 }
127 }
128}
129
Austin Schuh70cc9552019-01-21 19:46:48 -0800130TEST(VisibilityTest, NoEBlocks) {
131 // A = [1 0 0 0 0 0
132 // 1 0 0 0 0 0
133 // 0 1 0 0 0 0
134 // 0 1 0 0 0 0]
135
136 int num_cols = 6;
137 int num_eliminate_blocks = 2;
138 CompressedRowBlockStructure bs;
139
140 // Row 1
141 {
142 bs.rows.push_back(CompressedRow());
143 CompressedRow& row = bs.rows.back();
144 row.block.size = 2;
145 row.block.position = 0;
146 row.cells.push_back(Cell(0, 0));
147 }
148
149 // Row 2
150 {
151 bs.rows.push_back(CompressedRow());
152 CompressedRow& row = bs.rows.back();
153 row.block.size = 2;
154 row.block.position = 2;
155 row.cells.push_back(Cell(0, 1));
156 }
157
158 // Row 3
159 {
160 bs.rows.push_back(CompressedRow());
161 CompressedRow& row = bs.rows.back();
162 row.block.size = 2;
163 row.block.position = 4;
164 row.cells.push_back(Cell(1, 2));
165 }
166
167 // Row 4
168 {
169 bs.rows.push_back(CompressedRow());
170 CompressedRow& row = bs.rows.back();
171 row.block.size = 2;
172 row.block.position = 6;
173 row.cells.push_back(Cell(1, 3));
174 }
175 bs.cols.resize(num_cols);
176
177 vector<set<int>> visibility;
178 ComputeVisibility(bs, num_eliminate_blocks, &visibility);
179 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks);
180 for (int i = 0; i < visibility.size(); ++i) {
181 ASSERT_EQ(visibility[i].size(), 0);
182 }
183
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800184 std::unique_ptr<WeightedGraph<int>> graph(
185 CreateSchurComplementGraph(visibility));
Austin Schuh70cc9552019-01-21 19:46:48 -0800186 EXPECT_EQ(graph->vertices().size(), visibility.size());
187 for (int i = 0; i < visibility.size(); ++i) {
188 EXPECT_EQ(graph->VertexWeight(i), 1.0);
189 }
190
191 for (int i = 0; i < visibility.size(); ++i) {
192 for (int j = i; j < visibility.size(); ++j) {
193 double edge_weight = 0.0;
194 if (i == j) {
195 edge_weight = 1.0;
196 }
197 EXPECT_EQ(graph->EdgeWeight(i, j), edge_weight)
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800198 << "Edge: " << i << " " << j << " weight: " << graph->EdgeWeight(i, j)
Austin Schuh70cc9552019-01-21 19:46:48 -0800199 << " expected weight: " << edge_weight;
200 }
201 }
202}
203
204} // namespace internal
205} // namespace ceres