blob: ef521c0e11b06fe28f3d2ea6fe4b968ab6d9805c [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2015 Google Inc. All rights reserved.
3// http://ceres-solver.org/
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@google.com (Sameer Agarwal)
30
31#include "ceres/parameter_block_ordering.h"
32
33#include <memory>
34#include <unordered_set>
35
36#include "ceres/graph.h"
37#include "ceres/graph_algorithms.h"
38#include "ceres/map_util.h"
39#include "ceres/parameter_block.h"
40#include "ceres/program.h"
41#include "ceres/residual_block.h"
42#include "ceres/wall_time.h"
43#include "glog/logging.h"
44
45namespace ceres {
46namespace internal {
47
48using std::map;
49using std::set;
50using std::vector;
51
52int ComputeStableSchurOrdering(const Program& program,
53 vector<ParameterBlock*>* ordering) {
54 CHECK(ordering != nullptr);
55 ordering->clear();
56 EventLogger event_logger("ComputeStableSchurOrdering");
57 std::unique_ptr<Graph< ParameterBlock*> > graph(CreateHessianGraph(program));
58 event_logger.AddEvent("CreateHessianGraph");
59
60 const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
61 const std::unordered_set<ParameterBlock*>& vertices = graph->vertices();
62 for (int i = 0; i < parameter_blocks.size(); ++i) {
63 if (vertices.count(parameter_blocks[i]) > 0) {
64 ordering->push_back(parameter_blocks[i]);
65 }
66 }
67 event_logger.AddEvent("Preordering");
68
69 int independent_set_size = StableIndependentSetOrdering(*graph, ordering);
70 event_logger.AddEvent("StableIndependentSet");
71
72 // Add the excluded blocks to back of the ordering vector.
73 for (int i = 0; i < parameter_blocks.size(); ++i) {
74 ParameterBlock* parameter_block = parameter_blocks[i];
75 if (parameter_block->IsConstant()) {
76 ordering->push_back(parameter_block);
77 }
78 }
79 event_logger.AddEvent("ConstantParameterBlocks");
80
81 return independent_set_size;
82}
83
84int ComputeSchurOrdering(const Program& program,
85 vector<ParameterBlock*>* ordering) {
86 CHECK(ordering != nullptr);
87 ordering->clear();
88
89 std::unique_ptr<Graph< ParameterBlock*> > graph(CreateHessianGraph(program));
90 int independent_set_size = IndependentSetOrdering(*graph, ordering);
91 const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
92
93 // Add the excluded blocks to back of the ordering vector.
94 for (int i = 0; i < parameter_blocks.size(); ++i) {
95 ParameterBlock* parameter_block = parameter_blocks[i];
96 if (parameter_block->IsConstant()) {
97 ordering->push_back(parameter_block);
98 }
99 }
100
101 return independent_set_size;
102}
103
104void ComputeRecursiveIndependentSetOrdering(const Program& program,
105 ParameterBlockOrdering* ordering) {
106 CHECK(ordering != nullptr);
107 ordering->Clear();
108 const vector<ParameterBlock*> parameter_blocks = program.parameter_blocks();
109 std::unique_ptr<Graph< ParameterBlock*> > graph(CreateHessianGraph(program));
110
111 int num_covered = 0;
112 int round = 0;
113 while (num_covered < parameter_blocks.size()) {
114 vector<ParameterBlock*> independent_set_ordering;
115 const int independent_set_size =
116 IndependentSetOrdering(*graph, &independent_set_ordering);
117 for (int i = 0; i < independent_set_size; ++i) {
118 ParameterBlock* parameter_block = independent_set_ordering[i];
119 ordering->AddElementToGroup(parameter_block->mutable_user_state(), round);
120 graph->RemoveVertex(parameter_block);
121 }
122 num_covered += independent_set_size;
123 ++round;
124 }
125}
126
127Graph<ParameterBlock*>* CreateHessianGraph(const Program& program) {
128 Graph<ParameterBlock*>* graph = new Graph<ParameterBlock*>;
129 CHECK(graph != nullptr);
130 const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
131 for (int i = 0; i < parameter_blocks.size(); ++i) {
132 ParameterBlock* parameter_block = parameter_blocks[i];
133 if (!parameter_block->IsConstant()) {
134 graph->AddVertex(parameter_block);
135 }
136 }
137
138 const vector<ResidualBlock*>& residual_blocks = program.residual_blocks();
139 for (int i = 0; i < residual_blocks.size(); ++i) {
140 const ResidualBlock* residual_block = residual_blocks[i];
141 const int num_parameter_blocks = residual_block->NumParameterBlocks();
142 ParameterBlock* const* parameter_blocks =
143 residual_block->parameter_blocks();
144 for (int j = 0; j < num_parameter_blocks; ++j) {
145 if (parameter_blocks[j]->IsConstant()) {
146 continue;
147 }
148
149 for (int k = j + 1; k < num_parameter_blocks; ++k) {
150 if (parameter_blocks[k]->IsConstant()) {
151 continue;
152 }
153
154 graph->AddEdge(parameter_blocks[j], parameter_blocks[k]);
155 }
156 }
157 }
158
159 return graph;
160}
161
162void OrderingToGroupSizes(const ParameterBlockOrdering* ordering,
163 vector<int>* group_sizes) {
164 CHECK(group_sizes != nullptr);
165 group_sizes->clear();
166 if (ordering == NULL) {
167 return;
168 }
169
170 const map<int, set<double*>>& group_to_elements =
171 ordering->group_to_elements();
172 for (const auto& g_t_e : group_to_elements) {
173 group_sizes->push_back(g_t_e.second.size());
174 }
175}
176
177} // namespace internal
178} // namespace ceres