Home | History | Annotate | Download | only in ceres
      1 // Ceres Solver - A fast non-linear least squares minimizer
      2 // Copyright 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: sameeragarwal (at) google.com (Sameer Agarwal)
     30 
     31 #include "ceres/ordered_groups.h"
     32 
     33 #include <cstddef>
     34 #include <vector>
     35 #include "gtest/gtest.h"
     36 #include "ceres/collections_port.h"
     37 
     38 namespace ceres {
     39 namespace internal {
     40 
     41 TEST(OrderedGroups, EmptyOrderedGroupBehavesCorrectly) {
     42   ParameterBlockOrdering ordering;
     43   EXPECT_EQ(ordering.NumGroups(), 0);
     44   EXPECT_EQ(ordering.NumElements(), 0);
     45   EXPECT_EQ(ordering.GroupSize(1), 0);
     46   double x;
     47   EXPECT_EQ(ordering.GroupId(&x), -1);
     48   EXPECT_FALSE(ordering.Remove(&x));
     49 }
     50 
     51 TEST(OrderedGroups, EverythingInOneGroup) {
     52   ParameterBlockOrdering ordering;
     53   double x[3];
     54   ordering.AddElementToGroup(x, 1);
     55   ordering.AddElementToGroup(x + 1, 1);
     56   ordering.AddElementToGroup(x + 2, 1);
     57   ordering.AddElementToGroup(x, 1);
     58 
     59   EXPECT_EQ(ordering.NumGroups(), 1);
     60   EXPECT_EQ(ordering.NumElements(), 3);
     61   EXPECT_EQ(ordering.GroupSize(1), 3);
     62   EXPECT_EQ(ordering.GroupSize(0), 0);
     63   EXPECT_EQ(ordering.GroupId(x), 1);
     64   EXPECT_EQ(ordering.GroupId(x + 1), 1);
     65   EXPECT_EQ(ordering.GroupId(x + 2), 1);
     66 
     67   ordering.Remove(x);
     68   EXPECT_EQ(ordering.NumGroups(), 1);
     69   EXPECT_EQ(ordering.NumElements(), 2);
     70   EXPECT_EQ(ordering.GroupSize(1), 2);
     71   EXPECT_EQ(ordering.GroupSize(0), 0);
     72 
     73   EXPECT_EQ(ordering.GroupId(x), -1);
     74   EXPECT_EQ(ordering.GroupId(x + 1), 1);
     75   EXPECT_EQ(ordering.GroupId(x + 2), 1);
     76 }
     77 
     78 TEST(OrderedGroups, StartInOneGroupAndThenSplit) {
     79   ParameterBlockOrdering ordering;
     80   double x[3];
     81   ordering.AddElementToGroup(x, 1);
     82   ordering.AddElementToGroup(x + 1, 1);
     83   ordering.AddElementToGroup(x + 2, 1);
     84   ordering.AddElementToGroup(x, 1);
     85 
     86   EXPECT_EQ(ordering.NumGroups(), 1);
     87   EXPECT_EQ(ordering.NumElements(), 3);
     88   EXPECT_EQ(ordering.GroupSize(1), 3);
     89   EXPECT_EQ(ordering.GroupSize(0), 0);
     90   EXPECT_EQ(ordering.GroupId(x), 1);
     91   EXPECT_EQ(ordering.GroupId(x + 1), 1);
     92   EXPECT_EQ(ordering.GroupId(x + 2), 1);
     93 
     94   ordering.AddElementToGroup(x, 5);
     95   EXPECT_EQ(ordering.NumGroups(), 2);
     96   EXPECT_EQ(ordering.NumElements(), 3);
     97   EXPECT_EQ(ordering.GroupSize(1), 2);
     98   EXPECT_EQ(ordering.GroupSize(5), 1);
     99   EXPECT_EQ(ordering.GroupSize(0), 0);
    100 
    101   EXPECT_EQ(ordering.GroupId(x), 5);
    102   EXPECT_EQ(ordering.GroupId(x + 1), 1);
    103   EXPECT_EQ(ordering.GroupId(x + 2), 1);
    104 }
    105 
    106 TEST(OrderedGroups, AddAndRemoveEveryThingFromOneGroup) {
    107   ParameterBlockOrdering ordering;
    108   double x[3];
    109   ordering.AddElementToGroup(x, 1);
    110   ordering.AddElementToGroup(x + 1, 1);
    111   ordering.AddElementToGroup(x + 2, 1);
    112   ordering.AddElementToGroup(x, 1);
    113 
    114   EXPECT_EQ(ordering.NumGroups(), 1);
    115   EXPECT_EQ(ordering.NumElements(), 3);
    116   EXPECT_EQ(ordering.GroupSize(1), 3);
    117   EXPECT_EQ(ordering.GroupSize(0), 0);
    118   EXPECT_EQ(ordering.GroupId(x), 1);
    119   EXPECT_EQ(ordering.GroupId(x + 1), 1);
    120   EXPECT_EQ(ordering.GroupId(x + 2), 1);
    121 
    122   ordering.AddElementToGroup(x, 5);
    123   ordering.AddElementToGroup(x + 1, 5);
    124   ordering.AddElementToGroup(x + 2, 5);
    125   EXPECT_EQ(ordering.NumGroups(), 1);
    126   EXPECT_EQ(ordering.NumElements(), 3);
    127   EXPECT_EQ(ordering.GroupSize(1), 0);
    128   EXPECT_EQ(ordering.GroupSize(5), 3);
    129   EXPECT_EQ(ordering.GroupSize(0), 0);
    130 
    131   EXPECT_EQ(ordering.GroupId(x), 5);
    132   EXPECT_EQ(ordering.GroupId(x + 1), 5);
    133   EXPECT_EQ(ordering.GroupId(x + 2), 5);
    134 }
    135 
    136 TEST(OrderedGroups, ReverseOrdering) {
    137   ParameterBlockOrdering ordering;
    138   double x[3];
    139   ordering.AddElementToGroup(x, 1);
    140   ordering.AddElementToGroup(x + 1, 2);
    141   ordering.AddElementToGroup(x + 2, 2);
    142 
    143   EXPECT_EQ(ordering.NumGroups(), 2);
    144   EXPECT_EQ(ordering.NumElements(), 3);
    145   EXPECT_EQ(ordering.GroupSize(1), 1);
    146   EXPECT_EQ(ordering.GroupSize(2), 2);
    147   EXPECT_EQ(ordering.GroupId(x), 1);
    148   EXPECT_EQ(ordering.GroupId(x + 1), 2);
    149   EXPECT_EQ(ordering.GroupId(x + 2), 2);
    150 
    151   ordering.Reverse();
    152 
    153   EXPECT_EQ(ordering.NumGroups(), 2);
    154   EXPECT_EQ(ordering.NumElements(), 3);
    155   EXPECT_EQ(ordering.GroupSize(3), 1);
    156   EXPECT_EQ(ordering.GroupSize(2), 2);
    157   EXPECT_EQ(ordering.GroupId(x), 3);
    158   EXPECT_EQ(ordering.GroupId(x + 1), 2);
    159   EXPECT_EQ(ordering.GroupId(x + 2), 2);
    160 }
    161 
    162 TEST(OrderedGroups, BulkRemove) {
    163   ParameterBlockOrdering ordering;
    164   double x[3];
    165   ordering.AddElementToGroup(x, 1);
    166   ordering.AddElementToGroup(x + 1, 2);
    167   ordering.AddElementToGroup(x + 2, 2);
    168 
    169   vector<double*> elements_to_remove;
    170   elements_to_remove.push_back(x);
    171   elements_to_remove.push_back(x + 2);
    172 
    173   EXPECT_EQ(ordering.Remove(elements_to_remove), 2);
    174   EXPECT_EQ(ordering.NumElements(), 1);
    175   EXPECT_EQ(ordering.GroupId(x), -1);
    176   EXPECT_EQ(ordering.GroupId(x + 1), 2);
    177   EXPECT_EQ(ordering.GroupId(x + 2), -1);
    178 }
    179 
    180 TEST(OrderedGroups, BulkRemoveWithNoElements) {
    181   ParameterBlockOrdering ordering;
    182 
    183   double x[3];
    184   vector<double*> elements_to_remove;
    185   elements_to_remove.push_back(x);
    186   elements_to_remove.push_back(x + 2);
    187 
    188   EXPECT_EQ(ordering.Remove(elements_to_remove), 0);
    189 
    190   ordering.AddElementToGroup(x, 1);
    191   ordering.AddElementToGroup(x + 1, 2);
    192   ordering.AddElementToGroup(x + 2, 2);
    193 
    194   elements_to_remove.clear();
    195   EXPECT_EQ(ordering.Remove(elements_to_remove), 0);
    196 }
    197 
    198 TEST(OrderedGroups, MinNonZeroGroup) {
    199   ParameterBlockOrdering ordering;
    200   double x[3];
    201 
    202   ordering.AddElementToGroup(x, 1);
    203   ordering.AddElementToGroup(x + 1, 1);
    204   ordering.AddElementToGroup(x + 2, 2);
    205 
    206   EXPECT_EQ(ordering.MinNonZeroGroup(), 1);
    207   ordering.Remove(x);
    208 
    209   EXPECT_EQ(ordering.MinNonZeroGroup(), 1);
    210   ordering.Remove(x + 1);
    211 
    212   EXPECT_EQ(ordering.MinNonZeroGroup(), 2);
    213   ordering.Remove(x + 2);
    214 
    215   // No non-zero groups left.
    216   EXPECT_DEATH_IF_SUPPORTED(ordering.MinNonZeroGroup(), "NumGroups()");
    217 }
    218 }  // namespace internal
    219 }  // namespace ceres
    220