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: Sameer Agarwal (sameeragarwal@google.com) 30// David Gallup (dgallup@google.com) 31 32#ifndef CERES_NO_SUITESPARSE 33 34#include "ceres/canonical_views_clustering.h" 35 36#include "ceres/collections_port.h" 37#include "ceres/graph.h" 38#include "gtest/gtest.h" 39 40namespace ceres { 41namespace internal { 42 43const int kVertexIds[] = {0, 1, 2, 3}; 44class CanonicalViewsTest : public ::testing::Test { 45 protected: 46 virtual void SetUp() { 47 // The graph structure is as follows. 48 // 49 // Vertex weights: 0 2 2 0 50 // V0-----V1-----V2-----V3 51 // Edge weights: 0.8 0.9 0.3 52 const double kVertexWeights[] = {0.0, 2.0, 2.0, -1.0}; 53 for (int i = 0; i < 4; ++i) { 54 graph_.AddVertex(i, kVertexWeights[i]); 55 } 56 // Create self edges. 57 // CanonicalViews requires that every view "sees" itself. 58 for (int i = 0; i < 4; ++i) { 59 graph_.AddEdge(i, i, 1.0); 60 } 61 62 // Create three edges. 63 const double kEdgeWeights[] = {0.8, 0.9, 0.3}; 64 for (int i = 0; i < 3; ++i) { 65 // The graph interface is directed, so remember to create both 66 // edges. 67 graph_.AddEdge(kVertexIds[i], kVertexIds[i + 1], kEdgeWeights[i]); 68 } 69 } 70 71 void ComputeClustering() { 72 ComputeCanonicalViewsClustering(graph_, options_, ¢ers_, &membership_); 73 } 74 75 Graph<int> graph_; 76 77 CanonicalViewsClusteringOptions options_; 78 vector<int> centers_; 79 HashMap<int, int> membership_; 80}; 81 82TEST_F(CanonicalViewsTest, ComputeCanonicalViewsTest) { 83 options_.min_views = 0; 84 options_.size_penalty_weight = 0.5; 85 options_.similarity_penalty_weight = 0.0; 86 options_.view_score_weight = 0.0; 87 ComputeClustering(); 88 89 // 2 canonical views. 90 EXPECT_EQ(centers_.size(), 2); 91 EXPECT_EQ(centers_[0], kVertexIds[1]); 92 EXPECT_EQ(centers_[1], kVertexIds[3]); 93 94 // Check cluster membership. 95 EXPECT_EQ(FindOrDie(membership_, kVertexIds[0]), 0); 96 EXPECT_EQ(FindOrDie(membership_, kVertexIds[1]), 0); 97 EXPECT_EQ(FindOrDie(membership_, kVertexIds[2]), 0); 98 EXPECT_EQ(FindOrDie(membership_, kVertexIds[3]), 1); 99} 100 101// Increases size penalty so the second canonical view won't be 102// chosen. 103TEST_F(CanonicalViewsTest, SizePenaltyTest) { 104 options_.min_views = 0; 105 options_.size_penalty_weight = 2.0; 106 options_.similarity_penalty_weight = 0.0; 107 options_.view_score_weight = 0.0; 108 ComputeClustering(); 109 110 // 1 canonical view. 111 EXPECT_EQ(centers_.size(), 1); 112 EXPECT_EQ(centers_[0], kVertexIds[1]); 113} 114 115 116// Increases view score weight so vertex 2 will be chosen. 117TEST_F(CanonicalViewsTest, ViewScoreTest) { 118 options_.min_views = 0; 119 options_.size_penalty_weight = 0.5; 120 options_.similarity_penalty_weight = 0.0; 121 options_.view_score_weight = 1.0; 122 ComputeClustering(); 123 124 // 2 canonical views. 125 EXPECT_EQ(centers_.size(), 2); 126 EXPECT_EQ(centers_[0], kVertexIds[1]); 127 EXPECT_EQ(centers_[1], kVertexIds[2]); 128} 129 130// Increases similarity penalty so vertex 2 won't be chosen despite 131// it's view score. 132TEST_F(CanonicalViewsTest, SimilarityPenaltyTest) { 133 options_.min_views = 0; 134 options_.size_penalty_weight = 0.5; 135 options_.similarity_penalty_weight = 3.0; 136 options_.view_score_weight = 1.0; 137 ComputeClustering(); 138 139 // 2 canonical views. 140 EXPECT_EQ(centers_.size(), 1); 141 EXPECT_EQ(centers_[0], kVertexIds[1]); 142} 143 144} // namespace internal 145} // namespace ceres 146 147#endif // CERES_NO_SUITESPARSE 148