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 #ifndef CERES_NO_SUITESPARSE 33 34 #include "ceres/visibility.h" 35 36 #include <set> 37 #include <vector> 38 #include "ceres/block_structure.h" 39 #include "ceres/graph.h" 40 #include "ceres/internal/scoped_ptr.h" 41 #include "glog/logging.h" 42 #include "gtest/gtest.h" 43 44 namespace ceres { 45 namespace internal { 46 47 class VisibilityTest : public ::testing::Test { 48 }; 49 50 TEST(VisibilityTest, SimpleMatrix) { 51 // A = [1 0 0 0 0 1 52 // 1 0 0 1 0 0 53 // 0 1 1 0 0 0 54 // 0 1 0 0 1 0] 55 56 int num_cols = 6; 57 int num_eliminate_blocks = 2; 58 CompressedRowBlockStructure bs; 59 60 // Row 1 61 { 62 bs.rows.push_back(CompressedRow()); 63 CompressedRow& row = bs.rows.back(); 64 row.block.size = 2; 65 row.block.position = 0; 66 row.cells.push_back(Cell(0, 0)); 67 row.cells.push_back(Cell(5, 0)); 68 } 69 70 // Row 2 71 { 72 bs.rows.push_back(CompressedRow()); 73 CompressedRow& row = bs.rows.back(); 74 row.block.size = 2; 75 row.block.position = 2; 76 row.cells.push_back(Cell(0, 1)); 77 row.cells.push_back(Cell(3, 1)); 78 } 79 80 // Row 3 81 { 82 bs.rows.push_back(CompressedRow()); 83 CompressedRow& row = bs.rows.back(); 84 row.block.size = 2; 85 row.block.position = 4; 86 row.cells.push_back(Cell(1, 2)); 87 row.cells.push_back(Cell(2, 2)); 88 } 89 90 // Row 4 91 { 92 bs.rows.push_back(CompressedRow()); 93 CompressedRow& row = bs.rows.back(); 94 row.block.size = 2; 95 row.block.position = 6; 96 row.cells.push_back(Cell(1, 3)); 97 row.cells.push_back(Cell(4, 3)); 98 } 99 bs.cols.resize(num_cols); 100 101 vector< set<int> > visibility; 102 ComputeVisibility(bs, num_eliminate_blocks, &visibility); 103 ASSERT_EQ(visibility.size(), num_cols - num_eliminate_blocks); 104 for (int i = 0; i < visibility.size(); ++i) { 105 ASSERT_EQ(visibility[i].size(), 1); 106 } 107 108 scoped_ptr<Graph<int> > graph(CreateSchurComplementGraph(visibility)); 109 EXPECT_EQ(graph->vertices().size(), visibility.size()); 110 for (int i = 0; i < visibility.size(); ++i) { 111 EXPECT_EQ(graph->VertexWeight(i), 1.0); 112 } 113 114 for (int i = 0; i < visibility.size(); ++i) { 115 for (int j = i; j < visibility.size(); ++j) { 116 double edge_weight = 0.0; 117 if ((i == 1 && j == 3) || (i == 0 && j == 2) || (i == j)) { 118 edge_weight = 1.0; 119 } 120 121 EXPECT_EQ(graph->EdgeWeight(i, j), edge_weight) 122 << "Edge: " << i << " " << j 123 << " weight: " << graph->EdgeWeight(i, j) 124 << " expected weight: " << edge_weight; 125 } 126 } 127 } 128 129 130 TEST(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 184 scoped_ptr<Graph<int> > graph(CreateSchurComplementGraph(visibility)); 185 EXPECT_EQ(graph->vertices().size(), visibility.size()); 186 for (int i = 0; i < visibility.size(); ++i) { 187 EXPECT_EQ(graph->VertexWeight(i), 1.0); 188 } 189 190 for (int i = 0; i < visibility.size(); ++i) { 191 for (int j = i; j < visibility.size(); ++j) { 192 double edge_weight = 0.0; 193 if (i == j) { 194 edge_weight = 1.0; 195 } 196 EXPECT_EQ(graph->EdgeWeight(i, j), edge_weight) 197 << "Edge: " << i << " " << j 198 << " weight: " << graph->EdgeWeight(i, j) 199 << " expected weight: " << edge_weight; 200 } 201 } 202 } 203 204 } // namespace internal 205 } // namespace ceres 206 207 #endif // CERES_NO_SUITESPARSE 208