10ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Ceres Solver - A fast non-linear least squares minimizer
20ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
30ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// http://code.google.com/p/ceres-solver/
40ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
50ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Redistribution and use in source and binary forms, with or without
60ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// modification, are permitted provided that the following conditions are met:
70ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
80ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions of source code must retain the above copyright notice,
90ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   this list of conditions and the following disclaimer.
100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions in binary form must reproduce the above copyright notice,
110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   this list of conditions and the following disclaimer in the documentation
120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   and/or other materials provided with the distribution.
130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Neither the name of Google Inc. nor the names of its contributors may be
140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   used to endorse or promote products derived from this software without
150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   specific prior written permission.
160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// POSSIBILITY OF SUCH DAMAGE.
280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Author: Sameer Agarwal (sameeragarwal@google.com)
300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//         David Gallup (dgallup@google.com)
310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
321d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#ifndef CERES_NO_SUITESPARSE
331d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/canonical_views_clustering.h"
350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/collections_port.h"
370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/graph.h"
380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "gtest/gtest.h"
390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace ceres {
410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace internal {
420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongconst int kVertexIds[] = {0, 1, 2, 3};
440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongclass CanonicalViewsTest : public ::testing::Test {
450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong protected:
460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  virtual void SetUp() {
470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // The graph structure is as follows.
480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    //
490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Vertex weights:   0      2      2      0
500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    //                   V0-----V1-----V2-----V3
510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Edge weights:        0.8    0.9    0.3
520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    const double kVertexWeights[] = {0.0, 2.0, 2.0, -1.0};
530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 4; ++i) {
540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      graph_.AddVertex(i, kVertexWeights[i]);
550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Create self edges.
570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // CanonicalViews requires that every view "sees" itself.
580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 4; ++i) {
590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      graph_.AddEdge(i, i, 1.0);
600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Create three edges.
630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    const double kEdgeWeights[] = {0.8, 0.9, 0.3};
640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 3; ++i) {
650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      // The graph interface is directed, so remember to create both
660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      // edges.
670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      graph_.AddEdge(kVertexIds[i], kVertexIds[i + 1], kEdgeWeights[i]);
680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  void ComputeClustering() {
720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    ComputeCanonicalViewsClustering(graph_, options_, &centers_, &membership_);
730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Graph<int> graph_;
760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CanonicalViewsClusteringOptions options_;
780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  vector<int> centers_;
790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  HashMap<int, int> membership_;
800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong};
810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST_F(CanonicalViewsTest, ComputeCanonicalViewsTest) {
830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.min_views = 0;
840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.size_penalty_weight = 0.5;
850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.similarity_penalty_weight = 0.0;
860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.view_score_weight = 0.0;
870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ComputeClustering();
880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // 2 canonical views.
900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_.size(), 2);
910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_[0], kVertexIds[1]);
920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_[1], kVertexIds[3]);
930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Check cluster membership.
950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(FindOrDie(membership_, kVertexIds[0]), 0);
960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(FindOrDie(membership_, kVertexIds[1]), 0);
970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(FindOrDie(membership_, kVertexIds[2]), 0);
980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(FindOrDie(membership_, kVertexIds[3]), 1);
990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Increases size penalty so the second canonical view won't be
1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// chosen.
1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST_F(CanonicalViewsTest, SizePenaltyTest) {
1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.min_views = 0;
1050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.size_penalty_weight = 2.0;
1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.similarity_penalty_weight = 0.0;
1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.view_score_weight = 0.0;
1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ComputeClustering();
1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // 1 canonical view.
1110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_.size(), 1);
1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_[0], kVertexIds[1]);
1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Increases view score weight so vertex 2 will be chosen.
1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST_F(CanonicalViewsTest, ViewScoreTest) {
1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.min_views = 0;
1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.size_penalty_weight = 0.5;
1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.similarity_penalty_weight = 0.0;
1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.view_score_weight = 1.0;
1220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ComputeClustering();
1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // 2 canonical views.
1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_.size(), 2);
1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_[0], kVertexIds[1]);
1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_[1], kVertexIds[2]);
1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Increases similarity penalty so vertex 2 won't be chosen despite
1310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// it's view score.
1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST_F(CanonicalViewsTest, SimilarityPenaltyTest) {
1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.min_views = 0;
1340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.size_penalty_weight = 0.5;
1350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.similarity_penalty_weight = 3.0;
1360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options_.view_score_weight = 1.0;
1370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ComputeClustering();
1380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // 2 canonical views.
1400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_.size(), 1);
1410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  EXPECT_EQ(centers_[0], kVertexIds[1]);
1420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace internal
1450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace ceres
1461d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1471d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#endif  // CERES_NO_SUITESPARSE
148