diff --git a/CMakeLists.txt b/CMakeLists.txt index c78dc41e4..54e5e3a98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -440,10 +440,6 @@ endif (OPENMP) # they are used when checking for compiler features. set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS}) -# Set the Ceres option for C++11. -# TODO(alex): Remove when #defines are removed from source & config.h -list(APPEND CERES_COMPILE_OPTIONS CERES_STD_UNORDERED_MAP) - if (TBB) find_package(TBB QUIET) if (TBB_FOUND) diff --git a/cmake/config.h.in b/cmake/config.h.in index 76b853c58..d03165159 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -73,13 +73,6 @@ @CERES_HAVE_PTHREAD@ @CERES_HAVE_RWLOCK@ -// Which version of unordered map was used when Ceres was compiled. Exactly -// one of these will be defined for any given build. -@CERES_STD_UNORDERED_MAP@ -@CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE@ -@CERES_TR1_UNORDERED_MAP@ -@CERES_NO_UNORDERED_MAP@ - // If defined, the memory header is in , otherwise . @CERES_TR1_MEMORY_HEADER@ diff --git a/internal/ceres/block_random_access_diagonal_matrix.h b/internal/ceres/block_random_access_diagonal_matrix.h index 07ffc9d4a..2a8340b14 100644 --- a/internal/ceres/block_random_access_diagonal_matrix.h +++ b/internal/ceres/block_random_access_diagonal_matrix.h @@ -36,7 +36,6 @@ #include #include "ceres/mutex.h" #include "ceres/block_random_access_matrix.h" -#include "ceres/collections_port.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/integral_types.h" #include "ceres/internal/macros.h" diff --git a/internal/ceres/block_random_access_sparse_matrix.cc b/internal/ceres/block_random_access_sparse_matrix.cc index 5432ec106..540a8b913 100644 --- a/internal/ceres/block_random_access_sparse_matrix.cc +++ b/internal/ceres/block_random_access_sparse_matrix.cc @@ -69,11 +69,9 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( // object for looking into the values array of the // TripletSparseMatrix. int num_nonzeros = 0; - for (set >::const_iterator it = block_pairs.begin(); - it != block_pairs.end(); - ++it) { - const int row_block_size = blocks_[it->first]; - const int col_block_size = blocks_[it->second]; + for (const auto& block_pair : block_pairs) { + const int row_block_size = blocks_[block_pair.first]; + const int col_block_size = blocks_[block_pair.second]; num_nonzeros += row_block_size * col_block_size; } @@ -88,24 +86,19 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( double* values = tsm_->mutable_values(); int pos = 0; - for (set >::const_iterator it = block_pairs.begin(); - it != block_pairs.end(); - ++it) { - const int row_block_size = blocks_[it->first]; - const int col_block_size = blocks_[it->second]; - cell_values_.push_back(make_pair(make_pair(it->first, it->second), - values + pos)); - layout_[IntPairToLong(it->first, it->second)] = + for (const auto& block_pair : block_pairs) { + const int row_block_size = blocks_[block_pair.first]; + const int col_block_size = blocks_[block_pair.second]; + cell_values_.push_back(make_pair(block_pair, values + pos)); + layout_[IntPairToLong(block_pair.first, block_pair.second)] = new CellInfo(values + pos); pos += row_block_size * col_block_size; } // Fill the sparsity pattern of the underlying matrix. - for (set >::const_iterator it = block_pairs.begin(); - it != block_pairs.end(); - ++it) { - const int row_block_id = it->first; - const int col_block_id = it->second; + for (const auto& block_pair : block_pairs) { + const int row_block_id = block_pair.first; + const int col_block_id = block_pair.second; const int row_block_size = blocks_[row_block_id]; const int col_block_size = blocks_[col_block_id]; int pos = @@ -125,10 +118,8 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( // Assume that the user does not hold any locks on any cell blocks // when they are calling SetZero. BlockRandomAccessSparseMatrix::~BlockRandomAccessSparseMatrix() { - for (LayoutType::iterator it = layout_.begin(); - it != layout_.end(); - ++it) { - delete it->second; + for (const auto& entry : layout_) { + delete entry.second; } } @@ -163,19 +154,17 @@ void BlockRandomAccessSparseMatrix::SetZero() { void BlockRandomAccessSparseMatrix::SymmetricRightMultiply(const double* x, double* y) const { - vector< pair, double*> >::const_iterator it = - cell_values_.begin(); - for (; it != cell_values_.end(); ++it) { - const int row = it->first.first; + for (const auto& cell_position_and_data : cell_values_) { + const int row = cell_position_and_data.first.first; const int row_block_size = blocks_[row]; const int row_block_pos = block_positions_[row]; - const int col = it->first.second; + const int col = cell_position_and_data.first.second; const int col_block_size = blocks_[col]; const int col_block_pos = block_positions_[col]; MatrixVectorMultiply( - it->second, row_block_size, col_block_size, + cell_position_and_data.second, row_block_size, col_block_size, x + col_block_pos, y + row_block_pos); @@ -185,7 +174,7 @@ void BlockRandomAccessSparseMatrix::SymmetricRightMultiply(const double* x, // triangular multiply also. if (row != col) { MatrixTransposeVectorMultiply( - it->second, row_block_size, col_block_size, + cell_position_and_data.second, row_block_size, col_block_size, x + row_block_pos, y + col_block_pos); } diff --git a/internal/ceres/block_random_access_sparse_matrix.h b/internal/ceres/block_random_access_sparse_matrix.h index 2b3c7fdab..e79667b62 100644 --- a/internal/ceres/block_random_access_sparse_matrix.h +++ b/internal/ceres/block_random_access_sparse_matrix.h @@ -32,11 +32,11 @@ #define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ #include +#include #include #include #include "ceres/mutex.h" #include "ceres/block_random_access_matrix.h" -#include "ceres/collections_port.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/integral_types.h" #include "ceres/internal/macros.h" @@ -109,7 +109,7 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix { // A mapping from to the position in // the values array of tsm_ where the block is stored. - typedef HashMap LayoutType; + typedef std::unordered_map LayoutType; LayoutType layout_; // In order traversal of contents of the matrix. This allows us to diff --git a/internal/ceres/block_random_access_sparse_matrix_test.cc b/internal/ceres/block_random_access_sparse_matrix_test.cc index e4d82d017..688b09dc1 100644 --- a/internal/ceres/block_random_access_sparse_matrix_test.cc +++ b/internal/ceres/block_random_access_sparse_matrix_test.cc @@ -68,11 +68,9 @@ TEST(BlockRandomAccessSparseMatrix, GetCell) { EXPECT_EQ(m.num_rows(), num_rows); EXPECT_EQ(m.num_cols(), num_rows); - for (set >::const_iterator it = block_pairs.begin(); - it != block_pairs.end(); - ++it) { - const int row_block_id = it->first; - const int col_block_id = it->second; + for (const auto& block_pair : block_pairs) { + const int row_block_id = block_pair.first; + const int col_block_id = block_pair.second; int row; int col; int row_stride; diff --git a/internal/ceres/canonical_views_clustering.cc b/internal/ceres/canonical_views_clustering.cc index b3e9c2211..ca8dff589 100644 --- a/internal/ceres/canonical_views_clustering.cc +++ b/internal/ceres/canonical_views_clustering.cc @@ -31,7 +31,9 @@ #include "ceres/canonical_views_clustering.h" -#include "ceres/collections_port.h" +#include +#include + #include "ceres/graph.h" #include "ceres/internal/macros.h" #include "ceres/map_util.h" @@ -42,8 +44,8 @@ namespace internal { using std::vector; -typedef HashMap IntMap; -typedef HashSet IntSet; +typedef std::unordered_map IntMap; +typedef std::unordered_set IntSet; class CanonicalViewsClustering { public: @@ -76,7 +78,7 @@ class CanonicalViewsClustering { // center). IntMap view_to_canonical_view_; // Maps a view to its similarity to its current cluster center. - HashMap view_to_canonical_view_similarity_; + std::unordered_map view_to_canonical_view_similarity_; CERES_DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering); }; @@ -111,14 +113,12 @@ void CanonicalViewsClustering::ComputeClustering( int best_view = 0; // TODO(sameeragarwal): Make this loop multi-threaded. - for (IntSet::const_iterator view = valid_views.begin(); - view != valid_views.end(); - ++view) { + for (const auto& view : valid_views) { const double difference = - ComputeClusteringQualityDifference(*view, *centers); + ComputeClusteringQualityDifference(view, *centers); if (difference > best_difference) { best_difference = difference; - best_view = *view; + best_view = view; } } @@ -144,11 +144,9 @@ void CanonicalViewsClustering::ComputeClustering( void CanonicalViewsClustering::FindValidViews( IntSet* valid_views) const { const IntSet& views = graph_->vertices(); - for (IntSet::const_iterator view = views.begin(); - view != views.end(); - ++view) { - if (graph_->VertexWeight(*view) != WeightedGraph::InvalidWeight()) { - valid_views->insert(*view); + for (const auto& view : views) { + if (graph_->VertexWeight(view) != WeightedGraph::InvalidWeight()) { + valid_views->insert(view); } } } @@ -166,12 +164,10 @@ double CanonicalViewsClustering::ComputeClusteringQualityDifference( // was added to the list of canonical views and its nearest // neighbors became members of its cluster. const IntSet& neighbors = graph_->Neighbors(candidate); - for (IntSet::const_iterator neighbor = neighbors.begin(); - neighbor != neighbors.end(); - ++neighbor) { + for (const auto& neighbor : neighbors) { const double old_similarity = - FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0); - const double new_similarity = graph_->EdgeWeight(*neighbor, candidate); + FindWithDefault(view_to_canonical_view_similarity_, neighbor, 0.0); + const double new_similarity = graph_->EdgeWeight(neighbor, candidate); if (new_similarity > old_similarity) { difference += new_similarity - old_similarity; } @@ -193,16 +189,14 @@ double CanonicalViewsClustering::ComputeClusteringQualityDifference( void CanonicalViewsClustering::UpdateCanonicalViewAssignments( const int canonical_view) { const IntSet& neighbors = graph_->Neighbors(canonical_view); - for (IntSet::const_iterator neighbor = neighbors.begin(); - neighbor != neighbors.end(); - ++neighbor) { + for (const auto& neighbor : neighbors) { const double old_similarity = - FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0); + FindWithDefault(view_to_canonical_view_similarity_, neighbor, 0.0); const double new_similarity = - graph_->EdgeWeight(*neighbor, canonical_view); + graph_->EdgeWeight(neighbor, canonical_view); if (new_similarity > old_similarity) { - view_to_canonical_view_[*neighbor] = canonical_view; - view_to_canonical_view_similarity_[*neighbor] = new_similarity; + view_to_canonical_view_[neighbor] = canonical_view; + view_to_canonical_view_similarity_[neighbor] = new_similarity; } } } @@ -222,17 +216,14 @@ void CanonicalViewsClustering::ComputeClusterMembership( static const int kInvalidClusterId = -1; const IntSet& views = graph_->vertices(); - for (IntSet::const_iterator view = views.begin(); - view != views.end(); - ++view) { - IntMap::const_iterator it = - view_to_canonical_view_.find(*view); + for (const auto& view : views) { + auto it = view_to_canonical_view_.find(view); int cluster_id = kInvalidClusterId; if (it != view_to_canonical_view_.end()) { cluster_id = FindOrDie(center_to_cluster_id, it->second); } - InsertOrDie(membership, *view, cluster_id); + InsertOrDie(membership, view, cluster_id); } } diff --git a/internal/ceres/canonical_views_clustering.h b/internal/ceres/canonical_views_clustering.h index 0847f4844..651482746 100644 --- a/internal/ceres/canonical_views_clustering.h +++ b/internal/ceres/canonical_views_clustering.h @@ -41,9 +41,9 @@ #ifndef CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ #define CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ +#include #include -#include "ceres/collections_port.h" #include "ceres/graph.h" namespace ceres { @@ -98,7 +98,7 @@ void ComputeCanonicalViewsClustering( const CanonicalViewsClusteringOptions& options, const WeightedGraph& graph, std::vector* centers, - HashMap* membership); + std::unordered_map* membership); struct CanonicalViewsClusteringOptions { CanonicalViewsClusteringOptions() diff --git a/internal/ceres/canonical_views_clustering_test.cc b/internal/ceres/canonical_views_clustering_test.cc index 0c15fc797..a8db29352 100644 --- a/internal/ceres/canonical_views_clustering_test.cc +++ b/internal/ceres/canonical_views_clustering_test.cc @@ -31,7 +31,7 @@ #include "ceres/canonical_views_clustering.h" -#include "ceres/collections_port.h" +#include #include "ceres/graph.h" #include "gtest/gtest.h" @@ -74,7 +74,7 @@ class CanonicalViewsTest : public ::testing::Test { CanonicalViewsClusteringOptions options_; std::vector centers_; - HashMap membership_; + std::unordered_map membership_; }; TEST_F(CanonicalViewsTest, ComputeCanonicalViewsTest) { diff --git a/internal/ceres/coordinate_descent_minimizer.cc b/internal/ceres/coordinate_descent_minimizer.cc index a334ddeaf..e5569d496 100644 --- a/internal/ceres/coordinate_descent_minimizer.cc +++ b/internal/ceres/coordinate_descent_minimizer.cc @@ -80,18 +80,15 @@ bool CoordinateDescentMinimizer::Init( // offsets for parallel access. map parameter_block_index; map > group_to_elements = ordering.group_to_elements(); - for (map >::const_iterator it = group_to_elements.begin(); - it != group_to_elements.end(); - ++it) { - for (set::const_iterator ptr_it = it->second.begin(); - ptr_it != it->second.end(); - ++ptr_it) { - parameter_blocks_.push_back(parameter_map.find(*ptr_it)->second); + for (const auto& g_t_e : group_to_elements) { + const auto& elements = g_t_e.second; + for (double* parameter_block: elements) { + parameter_blocks_.push_back(parameter_map.find(parameter_block)->second); parameter_block_index[parameter_blocks_.back()] = parameter_blocks_.size() - 1; } independent_set_offsets_.push_back( - independent_set_offsets_.back() + it->second.size()); + independent_set_offsets_.back() + elements.size()); } // The ordering does not have to contain all parameter blocks, so @@ -114,8 +111,7 @@ bool CoordinateDescentMinimizer::Init( const int num_parameter_blocks = residual_block->NumParameterBlocks(); for (int j = 0; j < num_parameter_blocks; ++j) { ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; - const map::const_iterator it = - parameter_block_index.find(parameter_block); + const auto it = parameter_block_index.find(parameter_block); if (it != parameter_block_index.end()) { residual_blocks_[it->second].push_back(residual_block); } @@ -267,13 +263,12 @@ bool CoordinateDescentMinimizer::IsOrderingValid( ordering.group_to_elements(); // Verify that each group is an independent set - map >::const_iterator it = group_to_elements.begin(); - for (; it != group_to_elements.end(); ++it) { - if (!program.IsParameterBlockSetIndependent(it->second)) { + for (const auto& g_t_e : group_to_elements) { + if (!program.IsParameterBlockSetIndependent(g_t_e.second)) { *message = StringPrintf("The user-provided " "parameter_blocks_for_inner_iterations does not " - "form an independent set. Group Id: %d", it->first); + "form an independent set. Group Id: %d", g_t_e.first); return false; } } diff --git a/internal/ceres/covariance_impl.cc b/internal/ceres/covariance_impl.cc index c52866bc1..484c94ffa 100644 --- a/internal/ceres/covariance_impl.cc +++ b/internal/ceres/covariance_impl.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,6 @@ #include "Eigen/SparseQR" #include "Eigen/SVD" -#include "ceres/collections_port.h" #include "ceres/compressed_col_sparse_matrix_utils.h" #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/covariance.h" @@ -412,7 +412,7 @@ bool CovarianceImpl::ComputeCovarianceSparsity( vector all_parameter_blocks; problem->GetParameterBlocks(&all_parameter_blocks); const ProblemImpl::ParameterMap& parameter_map = problem->parameter_map(); - HashSet parameter_blocks_in_use; + std::unordered_set parameter_blocks_in_use; vector residual_blocks; problem->GetResidualBlocks(&residual_blocks); @@ -511,13 +511,10 @@ bool CovarianceImpl::ComputeCovarianceSparsity( // rows of the covariance matrix in order. int i = 0; // index into covariance_blocks. int cursor = 0; // index into the covariance matrix. - for (map::const_iterator it = - parameter_block_to_row_index_.begin(); - it != parameter_block_to_row_index_.end(); - ++it) { - const double* row_block = it->first; + for (const auto& entry : parameter_block_to_row_index_) { + const double* row_block = entry.first; const int row_block_size = problem->ParameterBlockLocalSize(row_block); - int row_begin = it->second; + int row_begin = entry.second; // Iterate over the covariance blocks contained in this row block // and count the number of columns in this row block. diff --git a/internal/ceres/covariance_test.cc b/internal/ceres/covariance_test.cc index 92a762661..96c962a03 100644 --- a/internal/ceres/covariance_test.cc +++ b/internal/ceres/covariance_test.cc @@ -564,9 +564,8 @@ class CovarianceTest : public ::testing::Test { } int dof = 0; // degrees of freedom = sum of LocalSize()s - for (BoundsMap::const_iterator iter = column_bounds.begin(); - iter != column_bounds.end(); ++iter) { - dof = std::max(dof, iter->second.second); + for (const auto& bound : column_bounds) { + dof = std::max(dof, bound.second.second); } ConstMatrixRef expected(expected_covariance, dof, dof); double diff_norm = (expected.block(row_begin, diff --git a/internal/ceres/graph.h b/internal/ceres/graph.h index b96b67265..25bb14195 100644 --- a/internal/ceres/graph.h +++ b/internal/ceres/graph.h @@ -32,11 +32,12 @@ #define CERES_INTERNAL_GRAPH_H_ #include +#include +#include #include #include "ceres/integral_types.h" #include "ceres/map_util.h" -#include "ceres/collections_port.h" -#include "ceres/internal/macros.h" +#include "ceres/pair_hash.h" #include "ceres/types.h" #include "glog/logging.h" @@ -53,7 +54,7 @@ class Graph { // Add a vertex. void AddVertex(const Vertex& vertex) { if (vertices_.insert(vertex).second) { - edges_[vertex] = HashSet(); + edges_[vertex] = std::unordered_set(); } } @@ -63,10 +64,9 @@ class Graph { } vertices_.erase(vertex); - const HashSet& sinks = edges_[vertex]; - for (typename HashSet::const_iterator it = sinks.begin(); - it != sinks.end(); ++it) { - edges_[*it].erase(vertex); + const std::unordered_set& sinks = edges_[vertex]; + for (const Vertex& s : sinks) { + edges_[s].erase(vertex); } edges_.erase(vertex); @@ -90,19 +90,17 @@ class Graph { // Calling Neighbors on a vertex not in the graph will result in // undefined behaviour. - const HashSet& Neighbors(const Vertex& vertex) const { + const std::unordered_set& Neighbors(const Vertex& vertex) const { return FindOrDie(edges_, vertex); } - const HashSet& vertices() const { + const std::unordered_set& vertices() const { return vertices_; } private: - HashSet vertices_; - HashMap > edges_; - - CERES_DISALLOW_COPY_AND_ASSIGN(Graph); + std::unordered_set vertices_; + std::unordered_map > edges_; }; // A weighted undirected graph templated over the vertex ids. Vertex @@ -117,7 +115,7 @@ class WeightedGraph { void AddVertex(const Vertex& vertex, double weight) { if (vertices_.find(vertex) == vertices_.end()) { vertices_.insert(vertex); - edges_[vertex] = HashSet(); + edges_[vertex] = std::unordered_set(); } vertex_weights_[vertex] = weight; } @@ -135,15 +133,14 @@ class WeightedGraph { vertices_.erase(vertex); vertex_weights_.erase(vertex); - const HashSet& sinks = edges_[vertex]; - for (typename HashSet::const_iterator it = sinks.begin(); - it != sinks.end(); ++it) { - if (vertex < *it) { - edge_weights_.erase(std::make_pair(vertex, *it)); + const std::unordered_set& sinks = edges_[vertex]; + for (const Vertex& s : sinks) { + if (vertex < s) { + edge_weights_.erase(std::make_pair(vertex, s)); } else { - edge_weights_.erase(std::make_pair(*it, vertex)); + edge_weights_.erase(std::make_pair(s, vertex)); } - edges_[*it].erase(vertex); + edges_[s].erase(vertex); } edges_.erase(vertex); @@ -198,11 +195,11 @@ class WeightedGraph { // Calling Neighbors on a vertex not in the graph will result in // undefined behaviour. - const HashSet& Neighbors(const Vertex& vertex) const { + const std::unordered_set& Neighbors(const Vertex& vertex) const { return FindOrDie(edges_, vertex); } - const HashSet& vertices() const { + const std::unordered_set& vertices() const { return vertices_; } @@ -211,12 +208,11 @@ class WeightedGraph { } private: - HashSet vertices_; - HashMap vertex_weights_; - HashMap > edges_; - HashMap, double> edge_weights_; - - CERES_DISALLOW_COPY_AND_ASSIGN(WeightedGraph); + std::unordered_set vertices_; + std::unordered_map vertex_weights_; + std::unordered_map> edges_; + std::unordered_map, double, pair_hash> + edge_weights_; }; } // namespace internal diff --git a/internal/ceres/graph_algorithms.h b/internal/ceres/graph_algorithms.h index d1d3f52cd..08837cf91 100644 --- a/internal/ceres/graph_algorithms.h +++ b/internal/ceres/graph_algorithms.h @@ -34,9 +34,10 @@ #define CERES_INTERNAL_GRAPH_ALGORITHMS_H_ #include +#include +#include #include #include -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/wall_time.h" #include "glog/logging.h" @@ -96,7 +97,7 @@ class VertexDegreeLessThan { template int IndependentSetOrdering(const Graph& graph, std::vector* ordering) { - const HashSet& vertices = graph.vertices(); + const std::unordered_set& vertices = graph.vertices(); const int num_vertices = vertices.size(); CHECK_NOTNULL(ordering); @@ -109,34 +110,29 @@ int IndependentSetOrdering(const Graph& graph, const char kBlack = 2; // Mark all vertices white. - HashMap vertex_color; + std::unordered_map vertex_color; std::vector vertex_queue; - for (typename HashSet::const_iterator it = vertices.begin(); - it != vertices.end(); - ++it) { - vertex_color[*it] = kWhite; - vertex_queue.push_back(*it); + for (const Vertex& vertex : vertices) { + vertex_color[vertex] = kWhite; + vertex_queue.push_back(vertex); } - - std::sort(vertex_queue.begin(), vertex_queue.end(), + std::sort(vertex_queue.begin(), + vertex_queue.end(), VertexTotalOrdering(graph)); // Iterate over vertex_queue. Pick the first white vertex, add it // to the independent set. Mark it black and its neighbors grey. - for (int i = 0; i < vertex_queue.size(); ++i) { - const Vertex& vertex = vertex_queue[i]; + for (const Vertex& vertex : vertex_queue) { if (vertex_color[vertex] != kWhite) { continue; } ordering->push_back(vertex); vertex_color[vertex] = kBlack; - const HashSet& neighbors = graph.Neighbors(vertex); - for (typename HashSet::const_iterator it = neighbors.begin(); - it != neighbors.end(); - ++it) { - vertex_color[*it] = kGrey; + const std::unordered_set& neighbors = graph.Neighbors(vertex); + for (const Vertex& neighbor : neighbors) { + vertex_color[neighbor] = kGrey; } } @@ -145,10 +141,7 @@ int IndependentSetOrdering(const Graph& graph, // Iterate over the vertices and add all the grey vertices to the // ordering. At this stage there should only be black or grey // vertices in the graph. - for (typename std::vector::const_iterator it = vertex_queue.begin(); - it != vertex_queue.end(); - ++it) { - const Vertex vertex = *it; + for (const Vertex& vertex : vertex_queue) { DCHECK(vertex_color[vertex] != kWhite); if (vertex_color[vertex] != kBlack) { ordering->push_back(vertex); @@ -173,7 +166,7 @@ template int StableIndependentSetOrdering(const Graph& graph, std::vector* ordering) { CHECK_NOTNULL(ordering); - const HashSet& vertices = graph.vertices(); + const std::unordered_set& vertices = graph.vertices(); const int num_vertices = vertices.size(); CHECK_EQ(vertices.size(), ordering->size()); @@ -188,11 +181,9 @@ int StableIndependentSetOrdering(const Graph& graph, VertexDegreeLessThan(graph)); // Mark all vertices white. - HashMap vertex_color; - for (typename HashSet::const_iterator it = vertices.begin(); - it != vertices.end(); - ++it) { - vertex_color[*it] = kWhite; + std::unordered_map vertex_color; + for (const Vertex& vertex : vertices) { + vertex_color[vertex] = kWhite; } ordering->clear(); @@ -207,11 +198,9 @@ int StableIndependentSetOrdering(const Graph& graph, ordering->push_back(vertex); vertex_color[vertex] = kBlack; - const HashSet& neighbors = graph.Neighbors(vertex); - for (typename HashSet::const_iterator it = neighbors.begin(); - it != neighbors.end(); - ++it) { - vertex_color[*it] = kGrey; + const std::unordered_set& neighbors = graph.Neighbors(vertex); + for (const Vertex& neighbor : neighbors) { + vertex_color[neighbor] = kGrey; } } @@ -220,10 +209,7 @@ int StableIndependentSetOrdering(const Graph& graph, // Iterate over the vertices and add all the grey vertices to the // ordering. At this stage there should only be black or grey // vertices in the graph. - for (typename std::vector::const_iterator it = vertex_queue.begin(); - it != vertex_queue.end(); - ++it) { - const Vertex vertex = *it; + for (const Vertex& vertex : vertex_queue) { DCHECK(vertex_color[vertex] != kWhite); if (vertex_color[vertex] != kBlack) { ordering->push_back(vertex); @@ -242,8 +228,8 @@ int StableIndependentSetOrdering(const Graph& graph, // is what gives this data structure its efficiency. template Vertex FindConnectedComponent(const Vertex& vertex, - HashMap* union_find) { - typename HashMap::iterator it = union_find->find(vertex); + std::unordered_map* union_find) { + auto it = union_find->find(vertex); DCHECK(it != union_find->end()); if (it->second != vertex) { it->second = FindConnectedComponent(it->second, union_find); @@ -279,25 +265,19 @@ Degree2MaximumSpanningForest(const WeightedGraph& graph) { // Disjoint-set to keep track of the connected components in the // maximum spanning tree. - HashMap disjoint_set; + std::unordered_map disjoint_set; // Sort of the edges in the graph in decreasing order of their // weight. Also add the vertices of the graph to the Maximum // Spanning Tree graph and set each vertex to be its own connected // component in the disjoint_set structure. - const HashSet& vertices = graph.vertices(); - for (typename HashSet::const_iterator it = vertices.begin(); - it != vertices.end(); - ++it) { - const Vertex vertex1 = *it; + const std::unordered_set& vertices = graph.vertices(); + for (const Vertex& vertex1 : vertices) { forest->AddVertex(vertex1, graph.VertexWeight(vertex1)); disjoint_set[vertex1] = vertex1; - const HashSet& neighbors = graph.Neighbors(vertex1); - for (typename HashSet::const_iterator it2 = neighbors.begin(); - it2 != neighbors.end(); - ++it2) { - const Vertex vertex2 = *it2; + const std::unordered_set& neighbors = graph.Neighbors(vertex1); + for (const Vertex& vertex2 : neighbors) { if (vertex1 >= vertex2) { continue; } diff --git a/internal/ceres/graph_algorithms_test.cc b/internal/ceres/graph_algorithms_test.cc index 107148811..160ece153 100644 --- a/internal/ceres/graph_algorithms_test.cc +++ b/internal/ceres/graph_algorithms_test.cc @@ -31,8 +31,8 @@ #include "ceres/graph_algorithms.h" #include +#include #include "gtest/gtest.h" -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" @@ -112,7 +112,7 @@ TEST(Degree2MaximumSpanningForest, PreserveWeights) { scoped_ptr > forest(Degree2MaximumSpanningForest(graph)); - const HashSet& vertices = forest->vertices(); + const std::unordered_set& vertices = forest->vertices(); EXPECT_EQ(vertices.size(), 2); EXPECT_EQ(forest->VertexWeight(0), 1.0); EXPECT_EQ(forest->VertexWeight(1), 2.0); @@ -134,35 +134,35 @@ TEST(Degree2MaximumSpanningForest, StarGraph) { graph.AddEdge(0, 4, 4.0); scoped_ptr > forest(Degree2MaximumSpanningForest(graph)); - const HashSet& vertices = forest->vertices(); + const std::unordered_set& vertices = forest->vertices(); EXPECT_EQ(vertices.size(), 5); { - const HashSet& neighbors = forest->Neighbors(0); + const std::unordered_set& neighbors = forest->Neighbors(0); EXPECT_EQ(neighbors.size(), 2); EXPECT_TRUE(neighbors.find(4) != neighbors.end()); EXPECT_TRUE(neighbors.find(3) != neighbors.end()); } { - const HashSet& neighbors = forest->Neighbors(3); + const std::unordered_set& neighbors = forest->Neighbors(3); EXPECT_EQ(neighbors.size(), 1); EXPECT_TRUE(neighbors.find(0) != neighbors.end()); } { - const HashSet& neighbors = forest->Neighbors(4); + const std::unordered_set& neighbors = forest->Neighbors(4); EXPECT_EQ(neighbors.size(), 1); EXPECT_TRUE(neighbors.find(0) != neighbors.end()); } { - const HashSet& neighbors = forest->Neighbors(1); + const std::unordered_set& neighbors = forest->Neighbors(1); EXPECT_EQ(neighbors.size(), 0); } { - const HashSet& neighbors = forest->Neighbors(2); + const std::unordered_set& neighbors = forest->Neighbors(2); EXPECT_EQ(neighbors.size(), 0); } } diff --git a/internal/ceres/graph_test.cc b/internal/ceres/graph_test.cc index e9d4e1cf5..0907f8694 100644 --- a/internal/ceres/graph_test.cc +++ b/internal/ceres/graph_test.cc @@ -30,8 +30,8 @@ #include "ceres/graph.h" +#include #include "gtest/gtest.h" -#include "ceres/collections_port.h" #include "ceres/internal/scoped_ptr.h" namespace ceres { @@ -48,7 +48,7 @@ TEST(Graph, AddVertexAndEdge) { graph.AddVertex(1); graph.AddEdge(0, 1); - const HashSet& vertices = graph.vertices(); + const std::unordered_set& vertices = graph.vertices(); EXPECT_EQ(vertices.size(), 2); EXPECT_EQ(graph.Neighbors(0).size(), 1); EXPECT_EQ(graph.Neighbors(1).size(), 1); @@ -60,7 +60,7 @@ TEST(Graph, AddVertexIdempotence) { graph.AddVertex(1); graph.AddEdge(0, 1); - const HashSet& vertices = graph.vertices(); + const std::unordered_set& vertices = graph.vertices(); EXPECT_EQ(vertices.size(), 2); @@ -93,7 +93,7 @@ TEST(WeightedGraph, AddVertexAndEdge) { graph.AddVertex(1, 2.0); graph.AddEdge(0, 1, 0.5); - const HashSet& vertices = graph.vertices(); + const std::unordered_set& vertices = graph.vertices(); EXPECT_EQ(vertices.size(), 2); EXPECT_EQ(graph.VertexWeight(0), 1.0); EXPECT_EQ(graph.VertexWeight(1), 2.0); @@ -109,7 +109,7 @@ TEST(WeightedGraph, AddVertexIdempotence) { graph.AddVertex(1, 2.0); graph.AddEdge(0, 1, 0.5); - const HashSet& vertices = graph.vertices(); + const std::unordered_set& vertices = graph.vertices(); EXPECT_EQ(vertices.size(), 2); diff --git a/internal/ceres/low_rank_inverse_hessian.cc b/internal/ceres/low_rank_inverse_hessian.cc index 1c6c9925f..f3953c460 100644 --- a/internal/ceres/low_rank_inverse_hessian.cc +++ b/internal/ceres/low_rank_inverse_hessian.cc @@ -175,12 +175,10 @@ void LowRankInverseHessian::RightMultiply(const double* x_ptr, << "approximation."; } - for (list::const_iterator it = indices_.begin(); - it != indices_.end(); - ++it) { - const double beta = delta_gradient_history_.col(*it).dot(search_direction) / - delta_x_dot_delta_gradient_(*it); - search_direction += delta_x_history_.col(*it) * (alpha(*it) - beta); + for (const int i : indices_) { + const double beta = delta_gradient_history_.col(i).dot(search_direction) / + delta_x_dot_delta_gradient_(i); + search_direction += delta_x_history_.col(i) * (alpha(i) - beta); } } diff --git a/internal/ceres/ordered_groups_test.cc b/internal/ceres/ordered_groups_test.cc index 4510686a3..8cf432461 100644 --- a/internal/ceres/ordered_groups_test.cc +++ b/internal/ceres/ordered_groups_test.cc @@ -33,7 +33,6 @@ #include #include #include "gtest/gtest.h" -#include "ceres/collections_port.h" namespace ceres { namespace internal { diff --git a/internal/ceres/collections_port.h b/internal/ceres/pair_hash.h similarity index 51% rename from internal/ceres/collections_port.h rename to internal/ceres/pair_hash.h index e699a661b..7fb32cfd9 100644 --- a/internal/ceres/collections_port.h +++ b/internal/ceres/pair_hash.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2018 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -28,85 +28,18 @@ // // Author: keir@google.com (Keir Mierle) // -// Portable HashMap and HashSet, and a specialized overload for hashing pairs. +// A hasher for std::pair. -#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_ -#define CERES_INTERNAL_COLLECTIONS_PORT_H_ +#ifndef CERES_INTERNAL_PAIR_HASH_H_ +#define CERES_INTERNAL_PAIR_HASH_H_ #include "ceres/internal/port.h" - -#if defined(CERES_NO_UNORDERED_MAP) -# include -# include -#endif - -#if defined(CERES_TR1_UNORDERED_MAP) -# include -# include -# define CERES_HASH_NAMESPACE_START namespace std { namespace tr1 { -# define CERES_HASH_NAMESPACE_END } } -#endif - -#if defined(CERES_STD_UNORDERED_MAP) -# include -# include -# define CERES_HASH_NAMESPACE_START namespace std { -# define CERES_HASH_NAMESPACE_END } -#endif - -#if defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) -# include -# include -# define CERES_HASH_NAMESPACE_START namespace std { namespace tr1 { -# define CERES_HASH_NAMESPACE_END } } -#endif - -#if !defined(CERES_NO_UNORDERED_MAP) && !defined(CERES_TR1_UNORDERED_MAP) && \ - !defined(CERES_STD_UNORDERED_MAP) && !defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT -# error One of: CERES_NO_UNORDERED_MAP, CERES_TR1_UNORDERED_MAP,\ - CERES_STD_UNORDERED_MAP, CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT -#endif - #include #include "ceres/integral_types.h" -// Some systems don't have access to unordered_map/unordered_set. In -// that case, substitute the hash map/set with normal map/set. The -// price to pay is slower speed for some operations. -#if defined(CERES_NO_UNORDERED_MAP) - namespace ceres { namespace internal { -template -struct HashMap : map {}; - -template -struct HashSet : set {}; - -} // namespace internal -} // namespace ceres - -#else - -namespace ceres { -namespace internal { - -#if defined(CERES_TR1_UNORDERED_MAP) || \ - defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) -template -struct HashMap : std::tr1::unordered_map {}; -template -struct HashSet : std::tr1::unordered_set {}; -#endif - -#if defined(CERES_STD_UNORDERED_MAP) -template -struct HashMap : std::unordered_map {}; -template -struct HashSet : std::unordered_set {}; -#endif - #if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__) #define GG_LONGLONG(x) x##I64 #define GG_ULONGLONG(x) x##UI64 @@ -160,37 +93,20 @@ inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) { return c; } +// Hasher for STL pairs. Requires hashers for both members to be defined. +struct pair_hash { + public: + template + std::size_t operator()(const std::pair& p) const { + const std::size_t h1 = std::hash()(p.first); + const std::size_t h2 = std::hash()(p.second); + // The decision below is at compile time + return (sizeof(h1) <= sizeof(uint32)) ? Hash32NumWithSeed(h1, h2) + : Hash64NumWithSeed(h1, h2); + } +}; + } // namespace internal } // namespace ceres -// Since on some platforms this is a doubly-nested namespace (std::tr1) and -// others it is not, the entire namespace line must be in a macro. -CERES_HASH_NAMESPACE_START - -// The outrageously annoying specializations below are for portability reasons. -// In short, it's not possible to have two overloads of hash - -// Hasher for STL pairs. Requires hashers for both members to be defined. -template -struct hash > { - size_t operator()(const pair& p) const { - size_t h1 = hash()(p.first); - size_t h2 = hash()(p.second); - // The decision below is at compile time - return (sizeof(h1) <= sizeof(ceres::internal::uint32)) ? - ceres::internal::Hash32NumWithSeed(h1, h2) : - ceres::internal::Hash64NumWithSeed(h1, h2); - } - // Less than operator for MSVC. - bool operator()(const pair& a, - const pair& b) const { - return a < b; - } - static const size_t bucket_size = 4; // These are required by MSVC - static const size_t min_buckets = 8; // 4 and 8 are defaults. -}; - -CERES_HASH_NAMESPACE_END - -#endif // CERES_NO_UNORDERED_MAP -#endif // CERES_INTERNAL_COLLECTIONS_PORT_H_ +#endif // CERES_INTERNAL_PAIR_HASH_H_ diff --git a/internal/ceres/parameter_block.h b/internal/ceres/parameter_block.h index 8e21553c6..a41d9d188 100644 --- a/internal/ceres/parameter_block.h +++ b/internal/ceres/parameter_block.h @@ -35,8 +35,8 @@ #include #include #include +#include #include "ceres/array_utils.h" -#include "ceres/collections_port.h" #include "ceres/integral_types.h" #include "ceres/internal/eigen.h" #include "ceres/internal/port.h" @@ -71,7 +71,7 @@ class ParameterBlock { // when it is small, but transitions to a hash set when it has more elements. // // For now, use a hash set. - typedef HashSet ResidualBlockSet; + typedef std::unordered_set ResidualBlockSet; // Create a parameter block with the user state, size, and index specified. // The size is the size of the parameter block and the index is the position diff --git a/internal/ceres/parameter_block_ordering.cc b/internal/ceres/parameter_block_ordering.cc index efba33997..649ce1427 100644 --- a/internal/ceres/parameter_block_ordering.cc +++ b/internal/ceres/parameter_block_ordering.cc @@ -30,6 +30,7 @@ #include "ceres/parameter_block_ordering.h" +#include #include "ceres/graph.h" #include "ceres/graph_algorithms.h" #include "ceres/internal/scoped_ptr.h" @@ -55,7 +56,7 @@ int ComputeStableSchurOrdering(const Program& program, event_logger.AddEvent("CreateHessianGraph"); const vector& parameter_blocks = program.parameter_blocks(); - const HashSet& vertices = graph->vertices(); + const std::unordered_set& vertices = graph->vertices(); for (int i = 0; i < parameter_blocks.size(); ++i) { if (vertices.count(parameter_blocks[i]) > 0) { ordering->push_back(parameter_blocks[i]); @@ -162,10 +163,8 @@ void OrderingToGroupSizes(const ParameterBlockOrdering* ordering, const map >& group_to_elements = ordering->group_to_elements(); - for (map >::const_iterator it = group_to_elements.begin(); - it != group_to_elements.end(); - ++it) { - group_sizes->push_back(it->second.size()); + for (const auto& g_t_e : group_to_elements) { + group_sizes->push_back(g_t_e.second.size()); } } diff --git a/internal/ceres/parameter_block_ordering_test.cc b/internal/ceres/parameter_block_ordering_test.cc index c98cdb510..41babffdf 100644 --- a/internal/ceres/parameter_block_ordering_test.cc +++ b/internal/ceres/parameter_block_ordering_test.cc @@ -31,9 +31,9 @@ #include "ceres/parameter_block_ordering.h" #include +#include #include #include "gtest/gtest.h" -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/problem_impl.h" #include "ceres/program.h" @@ -48,7 +48,7 @@ namespace internal { using std::vector; typedef Graph HessianGraph; -typedef HashSet VertexSet; +typedef std::unordered_set VertexSet; template class DummyCostFunction: public SizedCostFunction { diff --git a/internal/ceres/problem_impl.cc b/internal/ceres/problem_impl.cc index 3ed0efda8..1f3c55ba0 100644 --- a/internal/ceres/problem_impl.cc +++ b/internal/ceres/problem_impl.cc @@ -63,7 +63,6 @@ namespace internal { using std::map; using std::string; using std::vector; -typedef std::map ParameterMap; namespace { // Returns true if two regions of memory, a and b, with sizes size_a and size_b @@ -90,7 +89,7 @@ void CheckForNoAliasing(double* existing_block, template void DecrementValueOrDeleteKey(const KeyType key, std::map* container) { - typename std::map::iterator it = container->find(key); + auto it = container->find(key); if (it->second == 1) { delete key; container->erase(it); @@ -936,10 +935,9 @@ bool ProblemImpl::HasParameterBlock(const double* parameter_block) const { void ProblemImpl::GetParameterBlocks(vector* parameter_blocks) const { CHECK_NOTNULL(parameter_blocks); parameter_blocks->resize(0); - for (ParameterMap::const_iterator it = parameter_block_map_.begin(); - it != parameter_block_map_.end(); - ++it) { - parameter_blocks->push_back(it->first); + parameter_blocks->reserve(parameter_block_map_.size()); + for (const auto& entry : parameter_block_map_) { + parameter_blocks->push_back(entry.first); } } diff --git a/internal/ceres/problem_impl.h b/internal/ceres/problem_impl.h index 03e61d2a7..4c24e3b48 100644 --- a/internal/ceres/problem_impl.h +++ b/internal/ceres/problem_impl.h @@ -40,9 +40,9 @@ #define CERES_PUBLIC_PROBLEM_IMPL_H_ #include +#include #include -#include "ceres/collections_port.h" #include "ceres/context_impl.h" #include "ceres/internal/macros.h" #include "ceres/internal/port.h" @@ -65,7 +65,7 @@ class ResidualBlock; class ProblemImpl { public: typedef std::map ParameterMap; - typedef HashSet ResidualBlockSet; + typedef std::unordered_set ResidualBlockSet; typedef std::map CostFunctionRefCount; typedef std::map LossFunctionRefCount; @@ -203,7 +203,7 @@ class ProblemImpl { ContextImpl* context_impl_; // The mapping from user pointers to parameter blocks. - std::map parameter_block_map_; + ParameterMap parameter_block_map_; // Iff enable_fast_removal is enabled, contains the current residual blocks. ResidualBlockSet residual_block_set_; diff --git a/internal/ceres/program.cc b/internal/ceres/program.cc index 8e97f0721..f6cd13888 100644 --- a/internal/ceres/program.cc +++ b/internal/ceres/program.cc @@ -373,11 +373,10 @@ bool Program::IsParameterBlockSetIndependent( // blocks in the same residual block are part of // parameter_block_ptrs as that would violate the assumption that it // is an independent set in the Hessian matrix. - for (vector::const_iterator it = residual_blocks_.begin(); - it != residual_blocks_.end(); - ++it) { - ParameterBlock* const* parameter_blocks = (*it)->parameter_blocks(); - const int num_parameter_blocks = (*it)->NumParameterBlocks(); + for (const ResidualBlock* residual_block : residual_blocks_) { + ParameterBlock* const* parameter_blocks = + residual_block->parameter_blocks(); + const int num_parameter_blocks = residual_block->NumParameterBlocks(); int count = 0; for (int i = 0; i < num_parameter_blocks; ++i) { count += independent_set.count( diff --git a/internal/ceres/reorder_program.cc b/internal/ceres/reorder_program.cc index a7c371075..94a35bdab 100644 --- a/internal/ceres/reorder_program.cc +++ b/internal/ceres/reorder_program.cc @@ -234,23 +234,18 @@ bool ApplyOrdering(const ProblemImpl::ParameterMap& parameter_map, parameter_blocks->clear(); const map >& groups = ordering.group_to_elements(); - for (map >::const_iterator group_it = groups.begin(); - group_it != groups.end(); - ++group_it) { - const set& group = group_it->second; - for (set::const_iterator parameter_block_ptr_it = group.begin(); - parameter_block_ptr_it != group.end(); - ++parameter_block_ptr_it) { - ProblemImpl::ParameterMap::const_iterator parameter_block_it = - parameter_map.find(*parameter_block_ptr_it); - if (parameter_block_it == parameter_map.end()) { + for (const auto& p : groups) { + const set& group = p.second; + for (double* parameter_block_ptr : group) { + auto it = parameter_map.find(parameter_block_ptr); + if (it == parameter_map.end()) { *error = StringPrintf("User specified ordering contains a pointer " "to a double that is not a parameter block in " "the problem. The invalid double is in group: %d", - group_it->first); + p.first); return false; } - parameter_blocks->push_back(parameter_block_it->second); + parameter_blocks->push_back(it->second); } } return true; diff --git a/internal/ceres/schur_jacobi_preconditioner.cc b/internal/ceres/schur_jacobi_preconditioner.cc index d7f6fe971..13e6463fe 100644 --- a/internal/ceres/schur_jacobi_preconditioner.cc +++ b/internal/ceres/schur_jacobi_preconditioner.cc @@ -34,7 +34,6 @@ #include #include "ceres/block_random_access_diagonal_matrix.h" #include "ceres/block_sparse_matrix.h" -#include "ceres/collections_port.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/linear_solver.h" #include "ceres/schur_eliminator.h" diff --git a/internal/ceres/schur_jacobi_preconditioner.h b/internal/ceres/schur_jacobi_preconditioner.h index 5398f3ff3..fb7753bda 100644 --- a/internal/ceres/schur_jacobi_preconditioner.h +++ b/internal/ceres/schur_jacobi_preconditioner.h @@ -41,7 +41,6 @@ #include #include #include -#include "ceres/collections_port.h" #include "ceres/internal/macros.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/preconditioner.h" diff --git a/internal/ceres/single_linkage_clustering.cc b/internal/ceres/single_linkage_clustering.cc index 9e9342a6e..2d3213a03 100644 --- a/internal/ceres/single_linkage_clustering.cc +++ b/internal/ceres/single_linkage_clustering.cc @@ -30,8 +30,9 @@ #include "ceres/single_linkage_clustering.h" +#include +#include #include "ceres/graph.h" -#include "ceres/collections_port.h" #include "ceres/graph_algorithms.h" namespace ceres { @@ -40,27 +41,18 @@ namespace internal { int ComputeSingleLinkageClustering( const SingleLinkageClusteringOptions& options, const WeightedGraph& graph, - HashMap* membership) { + std::unordered_map* membership) { CHECK_NOTNULL(membership)->clear(); // Initially each vertex is in its own cluster. - const HashSet& vertices = graph.vertices(); - for (HashSet::const_iterator it = vertices.begin(); - it != vertices.end(); - ++it) { - (*membership)[*it] = *it; + const std::unordered_set& vertices = graph.vertices(); + for (const int v : vertices) { + (*membership)[v] = v; } - for (HashSet::const_iterator it1 = vertices.begin(); - it1 != vertices.end(); - ++it1) { - const int vertex1 = *it1; - const HashSet& neighbors = graph.Neighbors(vertex1); - for (HashSet::const_iterator it2 = neighbors.begin(); - it2 != neighbors.end(); - ++it2) { - const int vertex2 = *it2; - + for (const int vertex1 : vertices) { + const std::unordered_set& neighbors = graph.Neighbors(vertex1); + for (const int vertex2 : neighbors) { // Since the graph is undirected, only pay attention to one side // of the edge and ignore weak edges. if ((vertex1 > vertex2) || @@ -87,11 +79,9 @@ int ComputeSingleLinkageClustering( // Make sure that every vertex is connected directly to the vertex // identifying the cluster. int num_clusters = 0; - for (HashMap::iterator it = membership->begin(); - it != membership->end(); - ++it) { - it->second = FindConnectedComponent(it->first, membership); - if (it->first == it->second) { + for (auto& m : *membership) { + m.second = FindConnectedComponent(m.first, membership); + if (m.first == m.second) { ++num_clusters; } } diff --git a/internal/ceres/single_linkage_clustering.h b/internal/ceres/single_linkage_clustering.h index 8d1f02bcd..374125be8 100644 --- a/internal/ceres/single_linkage_clustering.h +++ b/internal/ceres/single_linkage_clustering.h @@ -31,7 +31,7 @@ #ifndef CERES_INTERNAL_SINGLE_LINKAGE_CLUSTERING_H_ #define CERES_INTERNAL_SINGLE_LINKAGE_CLUSTERING_H_ -#include "ceres/collections_port.h" +#include #include "ceres/graph.h" namespace ceres { @@ -60,7 +60,7 @@ struct SingleLinkageClusteringOptions { int ComputeSingleLinkageClustering( const SingleLinkageClusteringOptions& options, const WeightedGraph& graph, - HashMap* membership); + std::unordered_map* membership); } // namespace internal } // namespace ceres diff --git a/internal/ceres/single_linkage_clustering_test.cc b/internal/ceres/single_linkage_clustering_test.cc index ca1a661fa..281c281a2 100644 --- a/internal/ceres/single_linkage_clustering_test.cc +++ b/internal/ceres/single_linkage_clustering_test.cc @@ -30,7 +30,7 @@ #include "ceres/single_linkage_clustering.h" -#include "ceres/collections_port.h" +#include #include "ceres/graph.h" #include "gtest/gtest.h" @@ -52,7 +52,7 @@ TEST(SingleLinkageClustering, GraphHasTwoComponents) { graph.AddEdge(4, 5, 1.0); SingleLinkageClusteringOptions options; - HashMap membership; + std::unordered_map membership; ComputeSingleLinkageClustering(options, graph, &membership); EXPECT_EQ(membership.size(), kNumVertices); @@ -81,7 +81,7 @@ TEST(SingleLinkageClustering, ComponentWithWeakLink) { graph.AddEdge(4, 5, 0.5); SingleLinkageClusteringOptions options; - HashMap membership; + std::unordered_map membership; ComputeSingleLinkageClustering(options, graph, &membership); EXPECT_EQ(membership.size(), kNumVertices); @@ -111,7 +111,7 @@ TEST(SingleLinkageClustering, ComponentWithWeakLinkAndStrongLink) { graph.AddEdge(4, 5, 1.0); SingleLinkageClusteringOptions options; - HashMap membership; + std::unordered_map membership; ComputeSingleLinkageClustering(options, graph, &membership); EXPECT_EQ(membership.size(), kNumVertices); diff --git a/internal/ceres/visibility.cc b/internal/ceres/visibility.cc index cb962a6fb..a446b6b89 100644 --- a/internal/ceres/visibility.cc +++ b/internal/ceres/visibility.cc @@ -35,10 +35,11 @@ #include #include #include +#include #include #include "ceres/block_structure.h" -#include "ceres/collections_port.h" #include "ceres/graph.h" +#include "ceres/pair_hash.h" #include "glog/logging.h" namespace ceres { @@ -98,22 +99,17 @@ WeightedGraph* CreateSchurComplementGraph( vector > inverse_visibility(num_points); for (int i = 0; i < visibility.size(); i++) { const set& visibility_set = visibility[i]; - for (set::const_iterator it = visibility_set.begin(); - it != visibility_set.end(); - ++it) { - inverse_visibility[*it].insert(i); + for (const int v : visibility_set) { + inverse_visibility[v].insert(i); } } // Map from camera pairs to number of points visible to both cameras // in the pair. - HashMap, int > camera_pairs; + std::unordered_map, int, pair_hash> camera_pairs; // Count the number of points visible to each camera/f_block pair. - for (vector >::const_iterator it = inverse_visibility.begin(); - it != inverse_visibility.end(); - ++it) { - const set& inverse_visibility_set = *it; + for (const auto& inverse_visibility_set : inverse_visibility) { for (set::const_iterator camera1 = inverse_visibility_set.begin(); camera1 != inverse_visibility_set.end(); ++camera1) { @@ -136,14 +132,11 @@ WeightedGraph* CreateSchurComplementGraph( } // Add an edge for each camera pair. - for (HashMap, int>::const_iterator it = camera_pairs.begin(); - it != camera_pairs.end(); - ++it) { - const int camera1 = it->first.first; - const int camera2 = it->first.second; - CHECK_NE(camera1, camera2); - - const int count = it->second; + for (const auto& camera_pair_count : camera_pairs) { + const int camera1 = camera_pair_count.first.first; + const int camera2 = camera_pair_count.first.second; + const int count = camera_pair_count.second; + DCHECK_NE(camera1, camera2); // Static cast necessary for Windows. const double weight = static_cast(count) / (sqrt(static_cast( diff --git a/internal/ceres/visibility_based_preconditioner.cc b/internal/ceres/visibility_based_preconditioner.cc index 24563aef0..31d2cc31b 100644 --- a/internal/ceres/visibility_based_preconditioner.cc +++ b/internal/ceres/visibility_based_preconditioner.cc @@ -40,7 +40,6 @@ #include "ceres/block_random_access_sparse_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/canonical_views_clustering.h" -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/graph_algorithms.h" #include "ceres/internal/scoped_ptr.h" @@ -177,7 +176,7 @@ void VisibilityBasedPreconditioner::ClusterCameras( scoped_ptr > schur_complement_graph( CHECK_NOTNULL(CreateSchurComplementGraph(visibility))); - HashMap membership; + std::unordered_map membership; if (options_.visibility_clustering_type == CANONICAL_VIEWS) { vector centers; @@ -382,11 +381,9 @@ bool VisibilityBasedPreconditioner::UpdateImpl(const BlockSparseMatrix& A, // matrix. Scaling these off-diagonal entries by 1/2 forces this // matrix to be positive definite. void VisibilityBasedPreconditioner::ScaleOffDiagonalCells() { - for (set >::const_iterator it = block_pairs_.begin(); - it != block_pairs_.end(); - ++it) { - const int block1 = it->first; - const int block2 = it->second; + for (const auto& block_pair : block_pairs_) { + const int block1 = block_pair.first; + const int block2 = block_pair.second; if (!IsBlockPairOffDiagonal(block1, block2)) { continue; } @@ -464,23 +461,17 @@ bool VisibilityBasedPreconditioner::IsBlockPairOffDiagonal( // each vertex. void VisibilityBasedPreconditioner::ForestToClusterPairs( const WeightedGraph& forest, - HashSet >* cluster_pairs) const { + std::unordered_set, pair_hash >* cluster_pairs) const { CHECK_NOTNULL(cluster_pairs)->clear(); - const HashSet& vertices = forest.vertices(); + const std::unordered_set& vertices = forest.vertices(); CHECK_EQ(vertices.size(), num_clusters_); // Add all the cluster pairs corresponding to the edges in the // forest. - for (HashSet::const_iterator it1 = vertices.begin(); - it1 != vertices.end(); - ++it1) { - const int cluster1 = *it1; + for (const int cluster1 : vertices) { cluster_pairs->insert(make_pair(cluster1, cluster1)); - const HashSet& neighbors = forest.Neighbors(cluster1); - for (HashSet::const_iterator it2 = neighbors.begin(); - it2 != neighbors.end(); - ++it2) { - const int cluster2 = *it2; + const std::unordered_set& neighbors = forest.Neighbors(cluster1); + for (const int cluster2 : neighbors) { if (cluster1 < cluster2) { cluster_pairs->insert(make_pair(cluster1, cluster2)); } @@ -538,7 +529,7 @@ WeightedGraph* VisibilityBasedPreconditioner::CreateClusterGraph( return cluster_graph; } -// Canonical views clustering returns a HashMap from vertices to +// Canonical views clustering returns a std::unordered_map from vertices to // cluster ids. Convert this into a flat array for quick lookup. It is // possible that some of the vertices may not be associated with any // cluster. In that case, randomly assign them to one of the clusters. @@ -547,20 +538,18 @@ WeightedGraph* VisibilityBasedPreconditioner::CreateClusterGraph( // the membership_map, we also map the cluster ids to a contiguous set // of integers so that the cluster ids are in [0, num_clusters_). void VisibilityBasedPreconditioner::FlattenMembershipMap( - const HashMap& membership_map, + const std::unordered_map& membership_map, vector* membership_vector) const { CHECK_NOTNULL(membership_vector)->resize(0); membership_vector->resize(num_blocks_, -1); - HashMap cluster_id_to_index; + std::unordered_map cluster_id_to_index; // Iterate over the cluster membership map and update the // cluster_membership_ vector assigning arbitrary cluster ids to // the few cameras that have not been clustered. - for (HashMap::const_iterator it = membership_map.begin(); - it != membership_map.end(); - ++it) { - const int camera_id = it->first; - int cluster_id = it->second; + for (const auto& m : membership_map) { + const int camera_id = m.first; + int cluster_id = m.second; // If the view was not clustered, randomly assign it to one of the // clusters. This preserves the mathematical correctness of the diff --git a/internal/ceres/visibility_based_preconditioner.h b/internal/ceres/visibility_based_preconditioner.h index 40ce2c719..1c831d0a6 100644 --- a/internal/ceres/visibility_based_preconditioner.h +++ b/internal/ceres/visibility_based_preconditioner.h @@ -49,13 +49,15 @@ #define CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_ #include +#include +#include #include #include -#include "ceres/collections_port.h" #include "ceres/graph.h" #include "ceres/internal/macros.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/linear_solver.h" +#include "ceres/pair_hash.h" #include "ceres/preconditioner.h" #include "ceres/sparse_cholesky.h" @@ -150,7 +152,7 @@ class VisibilityBasedPreconditioner : public BlockSparseMatrixPreconditioner { void ScaleOffDiagonalCells(); void ClusterCameras(const std::vector >& visibility); - void FlattenMembershipMap(const HashMap& membership_map, + void FlattenMembershipMap(const std::unordered_map& membership_map, std::vector* membership_vector) const; void ComputeClusterVisibility( const std::vector >& visibility, @@ -158,7 +160,7 @@ class VisibilityBasedPreconditioner : public BlockSparseMatrixPreconditioner { WeightedGraph* CreateClusterGraph( const std::vector >& visibility) const; void ForestToClusterPairs(const WeightedGraph& forest, - HashSet >* cluster_pairs) const; + std::unordered_set, pair_hash>* cluster_pairs) const; void ComputeBlockPairsInPreconditioner(const CompressedRowBlockStructure& bs); bool IsBlockPairInPreconditioner(int block1, int block2) const; bool IsBlockPairOffDiagonal(int block1, int block2) const; @@ -182,7 +184,7 @@ class VisibilityBasedPreconditioner : public BlockSparseMatrixPreconditioner { // Set of cluster pairs (including self pairs (i,i)) in the // preconditioner. - HashSet > cluster_pairs_; + std::unordered_set, pair_hash> cluster_pairs_; scoped_ptr eliminator_; // Preconditioner matrix. diff --git a/internal/ceres/visibility_based_preconditioner_test.cc b/internal/ceres/visibility_based_preconditioner_test.cc index d2f13bce3..2227116c1 100644 --- a/internal/ceres/visibility_based_preconditioner_test.cc +++ b/internal/ceres/visibility_based_preconditioner_test.cc @@ -35,15 +35,14 @@ #include "ceres/block_random_access_sparse_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/casts.h" -#include "ceres/collections_port.h" #include "ceres/file.h" #include "ceres/internal/eigen.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/linear_least_squares_problems.h" #include "ceres/schur_eliminator.h" #include "ceres/stringprintf.h" -#include "ceres/types.h" #include "ceres/test_util.h" +#include "ceres/types.h" #include "glog/logging.h" #include "gtest/gtest.h" @@ -110,11 +109,11 @@ namespace internal { // schur_complement_.get(), rhs.data()); // } - // AssertionResult IsSparsityStructureValid() { // preconditioner_->InitStorage(*A_->block_structure()); -// const HashSet >& cluster_pairs = get_cluster_pairs(); -// const vector& cluster_membership = get_cluster_membership(); +// const std::unordered_set, pair_hash>& cluster_pairs = +// get_cluster_pairs(); const vector& cluster_membership = +// get_cluster_membership(); // for (int i = 0; i < num_camera_blocks_; ++i) { // for (int j = i; j < num_camera_blocks_; ++j) { @@ -137,8 +136,8 @@ namespace internal { // AssertionResult PreconditionerValuesMatch() { // preconditioner_->Update(*A_, D_.get()); -// const HashSet >& cluster_pairs = get_cluster_pairs(); -// const BlockRandomAccessSparseMatrix* m = get_m(); +// const std::unordered_set, pair_hash>& cluster_pairs = +// get_cluster_pairs(); const BlockRandomAccessSparseMatrix* m = get_m(); // Matrix preconditioner_matrix; // m->matrix()->ToDenseMatrix(&preconditioner_matrix); // ConstMatrixRef full_schur_complement(schur_complement_->values(), @@ -205,11 +204,12 @@ namespace internal { // return &preconditioner_->block_pairs_; // } -// const HashSet >& get_cluster_pairs() { +// const std::unordered_set, pair_hash>& get_cluster_pairs() { // return preconditioner_->cluster_pairs_; // } -// HashSet >* get_mutable_cluster_pairs() { +// std::unordered_set, pair_hash>* get_mutable_cluster_pairs() +// { // return &preconditioner_->cluster_pairs_; // } @@ -253,8 +253,8 @@ namespace internal { // *get_mutable_num_clusters() = 1; -// HashSet >& cluster_pairs = *get_mutable_cluster_pairs(); -// cluster_pairs.clear(); +// std::unordered_set, pair_hash>& cluster_pairs = +// *get_mutable_cluster_pairs(); cluster_pairs.clear(); // cluster_pairs.insert(make_pair(0, 0)); // EXPECT_TRUE(IsSparsityStructureValid()); @@ -284,8 +284,6 @@ namespace internal { // } // } - - // TEST_F(VisibilityBasedPreconditionerTest, ClusterJacobi) { // options_.type = CLUSTER_JACOBI; // preconditioner_.reset( @@ -301,9 +299,9 @@ namespace internal { // } // *get_mutable_num_clusters() = kNumClusters; -// HashSet >& cluster_pairs = *get_mutable_cluster_pairs(); -// cluster_pairs.clear(); -// for (int i = 0; i < kNumClusters; ++i) { +// std::unordered_set, pair_hash>& cluster_pairs = +// *get_mutable_cluster_pairs(); cluster_pairs.clear(); for (int i = 0; i < +// kNumClusters; ++i) { // cluster_pairs.insert(make_pair(i, i)); // } @@ -311,7 +309,6 @@ namespace internal { // EXPECT_TRUE(PreconditionerValuesMatch()); // } - // TEST_F(VisibilityBasedPreconditionerTest, ClusterTridiagonal) { // options_.type = CLUSTER_TRIDIAGONAL; // preconditioner_.reset( @@ -327,9 +324,9 @@ namespace internal { // *get_mutable_num_clusters() = kNumClusters; // // Spanning forest has structure 0-1 2 -// HashSet >& cluster_pairs = *get_mutable_cluster_pairs(); -// cluster_pairs.clear(); -// for (int i = 0; i < kNumClusters; ++i) { +// std::unordered_set, pair_hash>& cluster_pairs = +// *get_mutable_cluster_pairs(); cluster_pairs.clear(); for (int i = 0; i < +// kNumClusters; ++i) { // cluster_pairs.insert(make_pair(i, i)); // } // cluster_pairs.insert(make_pair(0, 1));