Start of the new ordering API. Change-Id: I37b0f39011f590d54962ad3e1da1f42712008f82
diff --git a/examples/bundle_adjuster.cc b/examples/bundle_adjuster.cc index 3e13c86..2bbffcf 100644 --- a/examples/bundle_adjuster.cc +++ b/examples/bundle_adjuster.cc
@@ -126,7 +126,6 @@ void SetOrdering(BALProblem* bal_problem, Solver::Options* options) { options->use_block_amd = FLAGS_use_block_amd; - CHECK(StringToOrderingType(FLAGS_ordering, &options->ordering_type)); // Bundle adjustment problems have a sparsity structure that makes // them amenable to more specialized and much more efficient @@ -142,11 +141,11 @@ // the right ParameterBlock ordering, or by manually specifying a // suitable ordering vector and defining // Options::num_eliminate_blocks. - if (options->ordering_type == ceres::SCHUR) { + options->use_new_ordering_api = true; + if (FLAGS_ordering == "schur") { return; } - options->ordering_type = ceres::USER; const int num_points = bal_problem->num_points(); const int point_block_size = bal_problem->point_block_size(); double* points = bal_problem->mutable_points(); @@ -154,24 +153,26 @@ const int camera_block_size = bal_problem->camera_block_size(); double* cameras = bal_problem->mutable_cameras(); + ceres::Ordering* ordering = new ceres::Ordering; + // The points come before the cameras. for (int i = 0; i < num_points; ++i) { - options->ordering.push_back(points + point_block_size * i); + ordering->AddParameterBlockToGroup(points + point_block_size * i, 0); } for (int i = 0; i < num_cameras; ++i) { // When using axis-angle, there is a single parameter block for // the entire camera. - options->ordering.push_back(cameras + camera_block_size * i); - + ordering->AddParameterBlockToGroup(cameras + camera_block_size * i, 1); // If quaternions are used, there are two blocks, so add the // second block to the ordering. if (FLAGS_use_quaternions) { - options->ordering.push_back(cameras + camera_block_size * i + 4); + ordering->AddParameterBlockToGroup( + cameras + camera_block_size * i + 4, 1); } } - options->num_eliminate_blocks = num_points; + options->ordering_new_api = ordering; } void SetMinimizerOptions(Solver::Options* options) {
diff --git a/include/ceres/ceres.h b/include/ceres/ceres.h index 2db19cb..1ea782a 100644 --- a/include/ceres/ceres.h +++ b/include/ceres/ceres.h
@@ -43,6 +43,7 @@ #include "ceres/local_parameterization.h" #include "ceres/loss_function.h" #include "ceres/numeric_diff_cost_function.h" +#include "ceres/ordering.h" #include "ceres/problem.h" #include "ceres/sized_cost_function.h" #include "ceres/solver.h"
diff --git a/include/ceres/ordering.h b/include/ceres/ordering.h new file mode 100644 index 0000000..b3cd1b1 --- /dev/null +++ b/include/ceres/ordering.h
@@ -0,0 +1,126 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include <map> +#include <set> +#include "ceres/internal/port.h" +#include "glog/logging.h" + +namespace ceres { + +// The order in which variables are eliminated in a linear solver can +// have a significant of impact on the efficiency and accuracy of the +// method. e.g., when doing sparse Cholesky factorization, there are +// matrices for which a good ordering will give a Cholesky factor with +// O(n) storage, where as a bad ordering will result in an completely +// dense factor. +// +// Ceres allows the user to provide varying amounts of hints to the +// solver about the variable elimination ordering to use. This can +// range from no hints, where the solver is free to decide the best +// possible ordering based on the user's choices like the linear +// solver being used, to an exact order in which the variables should +// be eliminated, and a variety of possibilities in between. Instances +// of the Ordering class are used to communicate this infornation to +// Ceres. +// +// Formally an ordering is an ordered partitioning of the parameter +// blocks, i.e, each parameter block belongs to exactly one group, and +// each group has a unique integer associated with it, that determines +// its order in the set of groups. +// +// Given such an ordering, Ceres ensures that the parameter blocks in +// the lowest numbered group are eliminated first, and then the +// parmeter blocks in the next lowest numbered group and so on. Within +// each group, Ceres is free to order the parameter blocks as it +// chooses. +// e.g. Consider the linear system +// +// x + y = 3 +// 2x + 3y = 7 +// +// There are two ways in which it can be solved. First eliminating x +// from the two equations, solving for y and then back substituting +// for x, or first eliminating y, solving for x and back substituting +// for y. The user can construct three orderings here. +// +// {0: x}, {1: y} - eliminate x first. +// {0: y}, {1: x} - eliminate y first. +// {0: x, y} - Solver gets to decide the elimination order. +// +// Thus, to have Ceres determine the ordering automatically using +// heuristics, put all the variables in group 0 and to control the +// ordering for every variable, create groups 0..N-1, one per +// variable, in the desired order. +// +// Bundle Adjustment +// ----------------- +// +// A particular case of interest is bundle adjustment, where the user +// has two options. The default is to not specify an ordering at all, +// the solver will see that the user wants to use a Schur type solver +// and figure out the right elimination ordering. +// +// But if the user already knows what parameter blocks are points and +// what are cameras, they can save preprocessing time by partitioning +// the parameter blocks into two groups, one for the points and one +// for the cameras, where the group containing the points has an id +// smaller than the group containing cameras. +class Ordering { + public: + // Add a parameter block to a group with id group_id. If a group + // with this id does not exist, one is created. This method can be + // called any number of times for a parameter block. + void AddParameterBlockToGroup(double* parameter_block, int group_id); + + // Remove the parameter block from the ordering, no matter what + // group it is in. If the parameter block is not known to the + // ordering, calling this method will result in a crash. + void RemoveParameterBlock(double* parameter_block); + + // Return the group id for the parameter block. If the parameter + // block is not known to the Ordering, calling this method results + // in a crash. + int GroupIdForParameterBlock(double* parameter_block) const; + int NumParameterBlocks() const; + int NumGroups() const; + + // This function always succeeds. For a group_id unknown to the + // ordering is treated as empty groups and the function returns + // zero. + int GroupSize(int group_id) const; + const map<int, set<double*> >& group_id_to_parameter_blocks() const; + + private: + map<int, set<double*> > group_id_to_parameter_blocks_; + map<double*, int> parameter_block_to_group_id_; +}; + +} // namespace ceres
diff --git a/include/ceres/solver.h b/include/ceres/solver.h index 31d5e8d..0e94ee8 100644 --- a/include/ceres/solver.h +++ b/include/ceres/solver.h
@@ -42,6 +42,7 @@ namespace ceres { +class Ordering; class Problem; // Interface for non-linear least squares solvers. @@ -89,6 +90,8 @@ #endif num_linear_solver_threads = 1; + use_new_ordering_api = false; + ordering_new_api = NULL; num_eliminate_blocks = 0; ordering_type = NATURAL; @@ -229,6 +232,18 @@ // using this setting. int num_linear_solver_threads; + // Whether the old or the new ordering API should be used. If this + // is true, all assignments to Solve::Options::ordering_type, + // Solver::Options::ordering and + // Solver::Options::num_eliminate_blocks are ignored. + bool use_new_ordering_api; + + // Ordering object for the new ordering API. If NULL, then all + // parameter blocks are assumed to be in the same group and the + // solver is free to decide the best ordering. (See ordering.h for + // more details). + Ordering* ordering_new_api; + // For Schur reduction based methods, the first 0 to num blocks are // eliminated using the Schur reduction. For example, when solving // traditional structure from motion problems where the parameters are in
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index cd4e6ac..862b7cf 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -63,6 +63,7 @@ local_parameterization.cc loss_function.cc normal_prior.cc + ordering.cc partitioned_matrix_view.cc polynomial_solver.cc problem.cc @@ -232,6 +233,7 @@ CERES_TEST(minimizer) CERES_TEST(normal_prior) CERES_TEST(numeric_diff_cost_function) + CERES_TEST(ordering) CERES_TEST(parameter_block) CERES_TEST(partitioned_matrix_view) CERES_TEST(polynomial_solver)
diff --git a/internal/ceres/ordering.cc b/internal/ceres/ordering.cc new file mode 100644 index 0000000..8b53ea5 --- /dev/null +++ b/internal/ceres/ordering.cc
@@ -0,0 +1,89 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include <map> +#include <set> +#include "ceres/internal/port.h" +#include "ceres/ordering.h" +#include "glog/logging.h" + +namespace ceres { + +void Ordering::AddParameterBlockToGroup(double* parameter_block, int group_id) { + const map<double*, int>::const_iterator it = + parameter_block_to_group_id_.find(parameter_block); + + if (it != parameter_block_to_group_id_.end()) { + group_id_to_parameter_blocks_[it->second].erase(parameter_block); + if (group_id_to_parameter_blocks_[it->second].size() == 0) { + group_id_to_parameter_blocks_.erase(it->second); + } + } + + parameter_block_to_group_id_[parameter_block] = group_id; + group_id_to_parameter_blocks_[group_id].insert(parameter_block); +} + +void Ordering::RemoveParameterBlock(double* parameter_block) { + const int current_group_id = GroupIdForParameterBlock(parameter_block); + group_id_to_parameter_blocks_[current_group_id].erase(parameter_block); + if (group_id_to_parameter_blocks_[current_group_id].size() == 0) { + group_id_to_parameter_blocks_.erase(current_group_id); + } + + parameter_block_to_group_id_.erase(parameter_block); +} + +int Ordering::GroupIdForParameterBlock(double* parameter_block) const { + const map<double*, int>::const_iterator it = + parameter_block_to_group_id_.find(parameter_block); + CHECK(it != parameter_block_to_group_id_.end()) + << "Tried finding the group id of a parameter block unknown to " + << "the ordering: " << parameter_block; + return it->second; +} + +int Ordering::NumParameterBlocks() const { + return parameter_block_to_group_id_.size(); +} + +int Ordering::NumGroups() const { return group_id_to_parameter_blocks_.size(); } + +int Ordering::GroupSize(int group_id) const { + map<int, set<double*> >::const_iterator it = + group_id_to_parameter_blocks_.find(group_id); + return (it == group_id_to_parameter_blocks_.end()) ? 0 : it->second.size(); +} + +const map<int, set<double*> >& Ordering::group_id_to_parameter_blocks() const { + return group_id_to_parameter_blocks_; +} + +} // namespace ceres
diff --git a/internal/ceres/ordering_test.cc b/internal/ceres/ordering_test.cc new file mode 100644 index 0000000..9bd43b3 --- /dev/null +++ b/internal/ceres/ordering_test.cc
@@ -0,0 +1,140 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/ordering.h" + +#include <cstddef> +#include <vector> +#include "gtest/gtest.h" +#include "ceres/collections_port.h" + +namespace ceres { +namespace internal { + +TEST(Ordering, EmptyOrderingBehavesCorrectly) { + Ordering ordering; + EXPECT_EQ(ordering.NumGroups(), 0); + EXPECT_EQ(ordering.NumParameterBlocks(), 0); + EXPECT_EQ(ordering.GroupSize(1), 0); + double x; + EXPECT_DEATH_IF_SUPPORTED(ordering.GroupIdForParameterBlock(&x), + "Tried finding"); + EXPECT_DEATH_IF_SUPPORTED(ordering.RemoveParameterBlock(&x), + "Tried finding"); +} + +TEST(Ordering, EverythingInOneGroup) { + Ordering ordering; + double x[3]; + ordering.AddParameterBlockToGroup(x, 1); + ordering.AddParameterBlockToGroup(x + 1, 1); + ordering.AddParameterBlockToGroup(x + 2, 1); + ordering.AddParameterBlockToGroup(x, 1); + + EXPECT_EQ(ordering.NumGroups(), 1); + EXPECT_EQ(ordering.NumParameterBlocks(), 3); + EXPECT_EQ(ordering.GroupSize(1), 3); + EXPECT_EQ(ordering.GroupSize(0), 0); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x), 1); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 1), 1); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 2), 1); + + ordering.RemoveParameterBlock(x); + EXPECT_EQ(ordering.NumGroups(), 1); + EXPECT_EQ(ordering.NumParameterBlocks(), 2); + EXPECT_EQ(ordering.GroupSize(1), 2); + EXPECT_EQ(ordering.GroupSize(0), 0); + + EXPECT_DEATH_IF_SUPPORTED(ordering.GroupIdForParameterBlock(x), + "Tried finding"); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 1), 1); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 2), 1); +} + +TEST(Ordering, StartInOneGroupAndThenSplit) { + Ordering ordering; + double x[3]; + ordering.AddParameterBlockToGroup(x, 1); + ordering.AddParameterBlockToGroup(x + 1, 1); + ordering.AddParameterBlockToGroup(x + 2, 1); + ordering.AddParameterBlockToGroup(x, 1); + + EXPECT_EQ(ordering.NumGroups(), 1); + EXPECT_EQ(ordering.NumParameterBlocks(), 3); + EXPECT_EQ(ordering.GroupSize(1), 3); + EXPECT_EQ(ordering.GroupSize(0), 0); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x), 1); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 1), 1); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 2), 1); + + ordering.AddParameterBlockToGroup(x, 5); + EXPECT_EQ(ordering.NumGroups(), 2); + EXPECT_EQ(ordering.NumParameterBlocks(), 3); + EXPECT_EQ(ordering.GroupSize(1), 2); + EXPECT_EQ(ordering.GroupSize(5), 1); + EXPECT_EQ(ordering.GroupSize(0), 0); + + EXPECT_EQ(ordering.GroupIdForParameterBlock(x), 5); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 1), 1); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 2), 1); +} + +TEST(Ordering, AddAndRemoveEveryThingFromOneGroup) { + Ordering ordering; + double x[3]; + ordering.AddParameterBlockToGroup(x, 1); + ordering.AddParameterBlockToGroup(x + 1, 1); + ordering.AddParameterBlockToGroup(x + 2, 1); + ordering.AddParameterBlockToGroup(x, 1); + + EXPECT_EQ(ordering.NumGroups(), 1); + EXPECT_EQ(ordering.NumParameterBlocks(), 3); + EXPECT_EQ(ordering.GroupSize(1), 3); + EXPECT_EQ(ordering.GroupSize(0), 0); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x), 1); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 1), 1); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 2), 1); + + ordering.AddParameterBlockToGroup(x, 5); + ordering.AddParameterBlockToGroup(x + 1, 5); + ordering.AddParameterBlockToGroup(x + 2, 5); + EXPECT_EQ(ordering.NumGroups(), 1); + EXPECT_EQ(ordering.NumParameterBlocks(), 3); + EXPECT_EQ(ordering.GroupSize(1), 0); + EXPECT_EQ(ordering.GroupSize(5), 3); + EXPECT_EQ(ordering.GroupSize(0), 0); + + EXPECT_EQ(ordering.GroupIdForParameterBlock(x), 5); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 1), 5); + EXPECT_EQ(ordering.GroupIdForParameterBlock(x + 2), 5); +} + +} // namespace internal +} // namespace ceres
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index 0ece8ee..8f2f38b 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -40,6 +40,7 @@ #include "ceres/linear_solver.h" #include "ceres/map_util.h" #include "ceres/minimizer.h" +#include "ceres/ordering.h" #include "ceres/parameter_block.h" #include "ceres/problem.h" #include "ceres/problem_impl.h" @@ -201,6 +202,51 @@ Solver::Summary* summary) { double solver_start_time = WallTimeInSeconds(); Solver::Options options(original_options); + + // Code for supporting both the old and the new ordering API. This + // code will get refactored and re-written as the old API is + // steadily deprecated. + + // Clobber all the input parameters from the old api parameters. + if (options.use_new_ordering_api) { + // For linear solvers which are not of Schur type, do nothing. + options.ordering.clear(); + options.num_eliminate_blocks = 0; + options.ordering_type = NATURAL; + + if (IsSchurType(options.linear_solver_type)) { + if (options.ordering_new_api == NULL) { + // User says we are free to find the independent set, and order + // any which way. + options.ordering_type = SCHUR; + } else { + // User has given an ordering and asked for a Schur type solver. + options.ordering_type = USER; + + // The lowest numbered group corresponds to + // num_eliminate_blocks e_blocks. + const map<int, set<double*> >& group_id_to_parameter_block + = options.ordering_new_api->group_id_to_parameter_blocks(); + + map<int, set<double*> >::const_iterator it = + group_id_to_parameter_block.begin(); + CHECK(it != group_id_to_parameter_block.end()); + + options.num_eliminate_blocks = it->second.size(); + for (; it != group_id_to_parameter_block.end(); ++it) { + options.ordering.insert(options.ordering.end(), + it->second.begin(), + it->second.end()); + } + CHECK_EQ(options.ordering.size(), + original_problem_impl->NumParameterBlocks()); + } + } + } else { + CHECK(options.ordering_new_api == NULL); + } + + Program* original_program = original_problem_impl->mutable_program(); ProblemImpl* problem_impl = original_problem_impl; // Reset the summary object to its default values.
diff --git a/jni/Android.mk b/jni/Android.mk index eaccb29..98e16f5 100644 --- a/jni/Android.mk +++ b/jni/Android.mk
@@ -123,6 +123,7 @@ $(CERES_SRC_PATH)/local_parameterization.cc \ $(CERES_SRC_PATH)/loss_function.cc \ $(CERES_SRC_PATH)/normal_prior.cc \ + $(CERES_SRC_PATH)/ordering.cc \ $(CERES_SRC_PATH)/partitioned_matrix_view.cc \ $(CERES_SRC_PATH)/polynomial_solver.cc \ $(CERES_SRC_PATH)/problem.cc \