1 // Ceres Solver - A fast non-linear least squares minimizer 2 // Copyright 2010, 2011, 2012 Google Inc. All rights reserved. 3 // http://code.google.com/p/ceres-solver/ 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 (at) google.com (Avanish Kushal) 30 // sameeragarwal (at) google.com (Sameer Agarwal) 31 32 #include "ceres/visibility.h" 33 34 #include <set> 35 #include <vector> 36 #include "ceres/block_structure.h" 37 #include "ceres/graph.h" 38 #include "ceres/internal/scoped_ptr.h" 39 #include "glog/logging.h" 40 #include "gtest/gtest.h" 41 42 namespace ceres { 43 namespace internal { 44 45 class VisibilityTest : public ::testing::Test { 46 }; 47 48 TEST(VisibilityTest, SimpleMatrix) { 49 // A = [1 0 0 0 0 1 50 // 1 0 0 1 0 0 51 // 0 1 1 0 0 0 52 // 0 1 0 0 1 0] 53 54 int num_cols = 6; 55 int num_eliminate_blocks = 2; 56 CompressedRowBlockStructure bs; 57 58 // Row 1 59 { 60 bs.rows.push_back(CompressedRow()); 61 CompressedRow& row = bs.rows.back(); 62 row.block.size = 2; 63 row.block.position = 0; 64 row.cells.push_back(Cell(0, 0)); 65 row.cells.push_back(Cell(5, 0)); 66 } 67 68 // Row 2 69 { 70 bs.rows.push_back(CompressedRow()); 71 CompressedRow& row = bs.rows.back(); 72 row.block.size = 2; 73 row.block.position = 2; 74 row.cells.push_back(Cell(0, 1)); 75 row.cells.push_back(Cell(3, 1)); 76 } 77 78 // Row 3 79 { 80 bs.rows.push_back(CompressedRow()); 81 CompressedRow& row = bs.rows.back(); 82 row.block.size = 2; 83 row.block.position = 4; 84 row.cells.push_back(Cell(1, 2)); 85 row.cells.push_back(Cell(2, 2)); 86 } 87 88 // Row 4 89 { 90 bs.rows.push_back(CompressedRow()); 91 CompressedRow& row = bs.rows.back(); 92 row.block.size = 2; 93 row.block.position = 6; 94 row.cells.push_back(Cell(1, 3)); 95 row.cells.push_back(Cell(4, 3)); 96 } 97 bs.cols.resize(num_cols); 98 99 vector< set<int> > visibility; 100 ComputeVisibility(bs, num_eliminate_blocks, &visibility); 101 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks); 102 for (int i = 0; i < visibility.size(); ++i) { 103 ASSERT_EQ(visibility[i].size(), 1); 104 } 105 106 scoped_ptr<Graph<int> > graph(CreateSchurComplementGraph(visibility)); 107 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) 120 << "Edge: " << i << " " << j 121 << " weight: " << graph->EdgeWeight(i, j) 122 << " expected weight: " << edge_weight; 123 } 124 } 125 } 126 127 128 TEST(VisibilityTest, NoEBlocks) { 129 // A = [1 0 0 0 0 0 130 // 1 0 0 0 0 0 131 // 0 1 0 0 0 0 132 // 0 1 0 0 0 0] 133 134 int num_cols = 6; 135 int num_eliminate_blocks = 2; 136 CompressedRowBlockStructure bs; 137 138 // Row 1 139 { 140 bs.rows.push_back(CompressedRow()); 141 CompressedRow& row = bs.rows.back(); 142 row.block.size = 2; 143 row.block.position = 0; 144 row.cells.push_back(Cell(0, 0)); 145 } 146 147 // Row 2 148 { 149 bs.rows.push_back(CompressedRow()); 150 CompressedRow& row = bs.rows.back(); 151 row.block.size = 2; 152 row.block.position = 2; 153 row.cells.push_back(Cell(0, 1)); 154 } 155 156 // Row 3 157 { 158 bs.rows.push_back(CompressedRow()); 159 CompressedRow& row = bs.rows.back(); 160 row.block.size = 2; 161 row.block.position = 4; 162 row.cells.push_back(Cell(1, 2)); 163 } 164 165 // Row 4 166 { 167 bs.rows.push_back(CompressedRow()); 168 CompressedRow& row = bs.rows.back(); 169 row.block.size = 2; 170 row.block.position = 6; 171 row.cells.push_back(Cell(1, 3)); 172 } 173 bs.cols.resize(num_cols); 174 175 vector<set<int> > visibility; 176 ComputeVisibility(bs, num_eliminate_blocks, &visibility); 177 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks); 178 for (int i = 0; i < visibility.size(); ++i) { 179 ASSERT_EQ(visibility[i].size(), 0); 180 } 181 182 scoped_ptr<Graph<int> > graph(CreateSchurComplementGraph(visibility)); 183 EXPECT_EQ(graph->vertices().size(), visibility.size()); 184 for (int i = 0; i < visibility.size(); ++i) { 185 EXPECT_EQ(graph->VertexWeight(i), 1.0); 186 } 187 188 for (int i = 0; i < visibility.size(); ++i) { 189 for (int j = i; j < visibility.size(); ++j) { 190 double edge_weight = 0.0; 191 if (i == j) { 192 edge_weight = 1.0; 193 } 194 EXPECT_EQ(graph->EdgeWeight(i, j), edge_weight) 195 << "Edge: " << i << " " << j 196 << " weight: " << graph->EdgeWeight(i, j) 197 << " expected weight: " << edge_weight; 198 } 199 } 200 } 201 202 } // namespace internal 203 } // namespace ceres 204