From e401b3e7cda8047ba7c29fa85acd8cf2d63064e8 Mon Sep 17 00:00:00 2001 From: Amit Prakash Ambasta Date: Fri, 9 Jun 2023 17:32:29 +0530 Subject: [PATCH] Support for USE_PDLP, C++23 and Werror changes Signed-off-by: Amit Prakash Ambasta --- CMakeLists.txt | 5 +-- cmake/cpp.cmake | 2 +- ortools/base/file.cc | 5 ++- .../routing_lp_scheduling.cc | 1 + ortools/constraint_solver/search.cc | 5 +-- ortools/glop/initial_basis.cc | 4 +++ ortools/glop/primal_edge_norms.cc | 1 + ortools/graph/iterators.h | 17 +++++++-- ortools/linear_solver/linear_solver.cc | 4 +++ ortools/linear_solver/pdlp_interface.cc | 3 ++ .../proto_solver/pdlp_proto_solver.cc | 3 ++ .../proto_solver/pdlp_proto_solver.h | 3 ++ ortools/linear_solver/solve.cc | 5 +-- ortools/lp_data/mps_reader.cc | 36 +++++++++---------- ortools/lp_data/mps_reader.h | 12 +++---- ortools/pdlp/iteration_stats.h | 4 +++ ortools/pdlp/primal_dual_hybrid_gradient.h | 3 ++ ortools/pdlp/quadratic_program.h | 3 ++ ortools/sat/cp_model_utils.cc | 1 + ortools/sat/linear_programming_constraint.cc | 3 +- 20 files changed, 82 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07bcaccc0b..aec8fc79d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,10 +28,11 @@ message(STATUS "${PROJECT_NAME} version: ${PROJECT_VERSION}") if(MSVC) set(CMAKE_CXX_STANDARD 20) else() - set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD 23) endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_EXTENSIONS ON) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") # Set max os target version. set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15) diff --git a/cmake/cpp.cmake b/cmake/cpp.cmake index daf6ba7eb8..35a94e3e8f 100644 --- a/cmake/cpp.cmake +++ b/cmake/cpp.cmake @@ -230,7 +230,7 @@ endforeach() if(MSVC) set(CMAKE_CXX_STANDARD 20) else() - set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD 23) endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/ortools/base/file.cc b/ortools/base/file.cc index fa627c9393..f3bbda2d57 100644 --- a/ortools/base/file.cc +++ b/ortools/base/file.cc @@ -184,9 +184,8 @@ absl::Status GetContents(const absl::string_view& filename, std::string* output, status.Update(file->Close(flags)); return status; } -#endif // _MSC_VER - - file->Close(flags); // Even if ReadToString() fails! +#endif // _MSC_VER + auto closed = file->Close(flags); // Even if ReadToString() fails! return absl::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Could not read from '", filename, "'.")); } diff --git a/ortools/constraint_solver/routing_lp_scheduling.cc b/ortools/constraint_solver/routing_lp_scheduling.cc index a8370e71c0..e1acf01500 100644 --- a/ortools/constraint_solver/routing_lp_scheduling.cc +++ b/ortools/constraint_solver/routing_lp_scheduling.cc @@ -1337,6 +1337,7 @@ int64_t ComputeConvexPiecewiseLinearFormulationValue( return PieceWiseLinearFormulationValueKnownSegment( pwl, x, pwl.x_anchors.size() - 1, delta); } + throw std::logic_error("Unhandled enum value"); } bool DimensionCumulOptimizerCore::SetRouteTravelConstraints( diff --git a/ortools/constraint_solver/search.cc b/ortools/constraint_solver/search.cc index 4ea7186695..a71e99768d 100644 --- a/ortools/constraint_solver/search.cc +++ b/ortools/constraint_solver/search.cc @@ -2406,6 +2406,7 @@ int SolutionCollector::solution_count() const { return solution_data_.size(); } int64_t SolutionCollector::wall_time(int n) const { check_index(n); + auto rr = solution_data_[n]; return solution_data_[n].time; } @@ -4233,8 +4234,8 @@ SearchLimit* RegularLimit::MakeClone() const { return MakeIdenticalClone(); } RegularLimit* RegularLimit::MakeIdenticalClone() const { Solver* const s = solver(); - return s->MakeLimit(wall_time(), branches_, failures_, solutions_, - smart_time_check_); + return s->MakeLimit(absl::Milliseconds(wall_time()), branches_, failures_, + solutions_, smart_time_check_); } bool RegularLimit::CheckWithOffset(absl::Duration offset) { diff --git a/ortools/glop/initial_basis.cc b/ortools/glop/initial_basis.cc index ed4d5a65d8..060c583a92 100644 --- a/ortools/glop/initial_basis.cc +++ b/ortools/glop/initial_basis.cc @@ -17,9 +17,11 @@ #include #include #include +#include #include #include "ortools/glop/markowitz.h" +#include "ortools/lp_data/lp_types.h" #include "ortools/lp_data/lp_utils.h" namespace operations_research { @@ -218,6 +220,7 @@ int InitialBasis::GetMarosPriority(ColIndex col) const { case VariableType::FIXED_VARIABLE: return 0; } + throw std::logic_error("Unhandled VariableType enum value"); } int InitialBasis::GetMarosPriority(RowIndex row) const { @@ -387,6 +390,7 @@ int InitialBasis::GetColumnCategory(ColIndex col) const { case VariableType::FIXED_VARIABLE: return 5; } + throw std::logic_error("Unhandled VariableType enum value"); } Fractional InitialBasis::GetColumnPenalty(ColIndex col) const { diff --git a/ortools/glop/primal_edge_norms.cc b/ortools/glop/primal_edge_norms.cc index 0c54245faf..83e38097ce 100644 --- a/ortools/glop/primal_edge_norms.cc +++ b/ortools/glop/primal_edge_norms.cc @@ -58,6 +58,7 @@ const DenseRow& PrimalEdgeNorms::GetSquaredNorms() { case GlopParameters::DEVEX: return GetDevexWeights(); } + throw std::logic_error("Unhandled pricing rule"); } const DenseRow& PrimalEdgeNorms::GetEdgeSquaredNorms() { diff --git a/ortools/graph/iterators.h b/ortools/graph/iterators.h index a89a8f5730..97398f1ad9 100644 --- a/ortools/graph/iterators.h +++ b/ortools/graph/iterators.h @@ -16,6 +16,7 @@ #ifndef UTIL_GRAPH_ITERATORS_H_ #define UTIL_GRAPH_ITERATORS_H_ +#include #include #include @@ -102,15 +103,24 @@ BeginEndReverseIteratorWrapper Reverse(const Container& c) { // Simple iterator on an integer range, see IntegerRange below. template -class IntegerRangeIterator - : public std::iterator { +class IntegerRangeIterator { public: + using iterator_category = std::input_iterator_tag; + using value_type = IntegerType; + using difference_type = std::ptrdiff_t; + using pointer = IntegerType*; + using reference = IntegerType&; + explicit IntegerRangeIterator(IntegerType value) : index_(value) {} IntegerRangeIterator(const IntegerRangeIterator& other) : index_(other.index_) {} IntegerRangeIterator& operator=(const IntegerRangeIterator& other) { index_ = other.index_; } + + auto operator<=>(const IntegerRangeIterator& other) const = default; + + /* bool operator!=(const IntegerRangeIterator& other) const { // This may seems weird, but using < instead of != avoid almost-infinite // loop if one use IntegerRange(1, 0) below for instance. @@ -119,7 +129,8 @@ class IntegerRangeIterator bool operator==(const IntegerRangeIterator& other) const { return index_ == other.index_; } - IntegerType operator*() const { return index_; } + */ + value_type operator*() const { return index_; } IntegerRangeIterator& operator++() { ++index_; return *this; diff --git a/ortools/linear_solver/linear_solver.cc b/ortools/linear_solver/linear_solver.cc index ef4f68560b..4e796d8f08 100644 --- a/ortools/linear_solver/linear_solver.cc +++ b/ortools/linear_solver/linear_solver.cc @@ -378,7 +378,9 @@ extern MPSolverInterface* BuildHighsInterface(bool mip, MPSolver* const solver); #endif extern MPSolverInterface* BuildBopInterface(MPSolver* const solver); extern MPSolverInterface* BuildGLOPInterface(MPSolver* const solver); +#if defined(USE_PDLP) extern MPSolverInterface* BuildPdlpInterface(MPSolver* const solver); +#endif extern MPSolverInterface* BuildSatInterface(MPSolver* const solver); #if defined(USE_SCIP) extern MPSolverInterface* BuildSCIPInterface(MPSolver* const solver); @@ -401,8 +403,10 @@ MPSolverInterface* BuildSolverInterface(MPSolver* const solver) { return BuildBopInterface(solver); case MPSolver::GLOP_LINEAR_PROGRAMMING: return BuildGLOPInterface(solver); +#if defined(USE_PDLP) case MPSolver::PDLP_LINEAR_PROGRAMMING: return BuildPdlpInterface(solver); +#endif case MPSolver::SAT_INTEGER_PROGRAMMING: return BuildSatInterface(solver); #if defined(USE_CLP) || defined(USE_CBC) diff --git a/ortools/linear_solver/pdlp_interface.cc b/ortools/linear_solver/pdlp_interface.cc index 166c8082c6..cb2ea00b55 100644 --- a/ortools/linear_solver/pdlp_interface.cc +++ b/ortools/linear_solver/pdlp_interface.cc @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if defined(USE_PDLP) + #include #include #include @@ -305,3 +307,4 @@ MPSolverInterface* BuildPdlpInterface(MPSolver* const solver) { } } // namespace operations_research +#endif // #if defined(USE_PDLP) diff --git a/ortools/linear_solver/proto_solver/pdlp_proto_solver.cc b/ortools/linear_solver/proto_solver/pdlp_proto_solver.cc index f4e89531d1..c1434a5e23 100644 --- a/ortools/linear_solver/proto_solver/pdlp_proto_solver.cc +++ b/ortools/linear_solver/proto_solver/pdlp_proto_solver.cc @@ -10,6 +10,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#if defined(USE_PDLP) #include "ortools/linear_solver/proto_solver/pdlp_proto_solver.h" @@ -133,3 +134,5 @@ absl::StatusOr PdlpSolveProto( } } // namespace operations_research + +#endif // #if defined(USE_PDLP) diff --git a/ortools/linear_solver/proto_solver/pdlp_proto_solver.h b/ortools/linear_solver/proto_solver/pdlp_proto_solver.h index 8a0ce53136..2195389f33 100644 --- a/ortools/linear_solver/proto_solver/pdlp_proto_solver.h +++ b/ortools/linear_solver/proto_solver/pdlp_proto_solver.h @@ -10,6 +10,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#if defined(USE_PDLP) #ifndef OR_TOOLS_LINEAR_SOLVER_PROTO_SOLVER_PDLP_PROTO_SOLVER_H_ #define OR_TOOLS_LINEAR_SOLVER_PROTO_SOLVER_PDLP_PROTO_SOLVER_H_ @@ -43,3 +44,5 @@ absl::StatusOr PdlpSolveProto( } // namespace operations_research #endif // OR_TOOLS_LINEAR_SOLVER_PROTO_SOLVER_PDLP_PROTO_SOLVER_H_ + +#endif // #if defined(USE_PDLP) diff --git a/ortools/linear_solver/solve.cc b/ortools/linear_solver/solve.cc index 187d451eb5..84947fce99 100644 --- a/ortools/linear_solver/solve.cc +++ b/ortools/linear_solver/solve.cc @@ -140,8 +140,9 @@ MPModelRequest ReadMipModel(const std::string& input) { model_proto = std::move(result).value(); } else if (absl::EndsWith(input, ".mps") || absl::EndsWith(input, ".mps.gz")) { - QCHECK_OK(glop::MPSReader().ParseFile(input, &model_proto)) - << "Error while parsing the mps file '" << input << "'."; + auto retval = glop::MpsFileToMPModelProto(input); + QCHECK_OK(retval) << "Error while parsing the mps file '" << input << "'."; + model_proto = *retval; } else { ReadFileToProto(input, &model_proto); ReadFileToProto(input, &request_proto); diff --git a/ortools/lp_data/mps_reader.cc b/ortools/lp_data/mps_reader.cc index 806d5f9cde..681b2c477a 100644 --- a/ortools/lp_data/mps_reader.cc +++ b/ortools/lp_data/mps_reader.cc @@ -39,13 +39,13 @@ class MPSReaderImpl { // MpModelProto for the Data type, but it should be easy to add more. template absl::Status ParseFile(const std::string& file_name, Data* data, - MPSReader::Form form); + MPSReaderForm form); // Loads instance from string. Useful with MapReduce. Automatically detects // the file's format (free or fixed). template absl::Status ParseProblemFromString(const std::string& source, Data* data, - MPSReader::Form form); + MPSReaderForm form); private: // Number of fields in one line of MPS file. @@ -523,19 +523,19 @@ class DataWrapper { template absl::Status MPSReaderImpl::ParseFile(const std::string& file_name, Data* data, - MPSReader::Form form) { + MPSReaderForm form) { if (data == nullptr) { return absl::InvalidArgumentError("NULL pointer passed as argument."); } - if (form == MPSReader::AUTO_DETECT) { - if (ParseFile(file_name, data, MPSReader::FIXED).ok()) { + if (form == MPSReaderForm::AUTO_DETECT) { + if (ParseFile(file_name, data, MPSReaderForm::FIXED).ok()) { return absl::OkStatus(); } - return ParseFile(file_name, data, MPSReader::FREE); + return ParseFile(file_name, data, MPSReaderForm::FREE); } - free_form_ = form == MPSReader::FREE; + free_form_ = form == MPSReaderForm::FREE; Reset(); DataWrapper data_wrapper(data); data_wrapper.SetUp(); @@ -553,15 +553,15 @@ absl::Status MPSReaderImpl::ParseFile(const std::string& file_name, Data* data, template absl::Status MPSReaderImpl::ParseProblemFromString(const std::string& source, Data* data, - MPSReader::Form form) { - if (form == MPSReader::AUTO_DETECT) { - if (ParseProblemFromString(source, data, MPSReader::FIXED).ok()) { + MPSReaderForm form) { + if (form == MPSReaderForm::AUTO_DETECT) { + if (ParseProblemFromString(source, data, MPSReaderForm::FIXED).ok()) { return absl::OkStatus(); } - return ParseProblemFromString(source, data, MPSReader::FREE); + return ParseProblemFromString(source, data, MPSReaderForm::FREE); } - free_form_ = form == MPSReader::FREE; + free_form_ = form == MPSReaderForm::FREE; Reset(); DataWrapper data_wrapper(data); data_wrapper.SetUp(); @@ -1167,12 +1167,12 @@ absl::Status MPSReaderImpl::AppendLineToError(const absl::Status& status) { // Parses instance from a file. absl::Status MPSReader::ParseFile(const std::string& file_name, - LinearProgram* data, Form form) { + LinearProgram* data, MPSReaderForm form) { return MPSReaderImpl().ParseFile(file_name, data, form); } absl::Status MPSReader::ParseFile(const std::string& file_name, - MPModelProto* data, Form form) { + MPModelProto* data, MPSReaderForm form) { return MPSReaderImpl().ParseFile(file_name, data, form); } @@ -1180,13 +1180,13 @@ absl::Status MPSReader::ParseFile(const std::string& file_name, // the file's format (free or fixed). absl::Status MPSReader::ParseProblemFromString(const std::string& source, LinearProgram* data, - MPSReader::Form form) { + MPSReaderForm form) { return MPSReaderImpl().ParseProblemFromString(source, data, form); } absl::Status MPSReader::ParseProblemFromString(const std::string& source, MPModelProto* data, - MPSReader::Form form) { + MPSReaderForm form) { return MPSReaderImpl().ParseProblemFromString(source, data, form); } @@ -1194,7 +1194,7 @@ absl::StatusOr MpsDataToMPModelProto( const std::string& mps_data) { MPModelProto model; RETURN_IF_ERROR(MPSReaderImpl().ParseProblemFromString( - mps_data, &model, MPSReader::AUTO_DETECT)); + mps_data, &model, MPSReaderForm::AUTO_DETECT)); return model; } @@ -1202,7 +1202,7 @@ absl::StatusOr MpsFileToMPModelProto( const std::string& mps_file) { MPModelProto model; RETURN_IF_ERROR( - MPSReaderImpl().ParseFile(mps_file, &model, MPSReader::AUTO_DETECT)); + MPSReaderImpl().ParseFile(mps_file, &model, MPSReaderForm::AUTO_DETECT)); return model; } diff --git a/ortools/lp_data/mps_reader.h b/ortools/lp_data/mps_reader.h index 33af74971e..202fdb42fb 100644 --- a/ortools/lp_data/mps_reader.h +++ b/ortools/lp_data/mps_reader.h @@ -55,6 +55,8 @@ absl::StatusOr MpsDataToMPModelProto(const std::string& mps_data); // Parses an MPS model from a file. absl::StatusOr MpsFileToMPModelProto(const std::string& mps_file); +enum MPSReaderForm { AUTO_DETECT, FREE, FIXED }; + // Implementation class. Please use the 2 functions above. // // Reads a linear program in the mps format. @@ -65,22 +67,20 @@ absl::StatusOr MpsFileToMPModelProto(const std::string& mps_file); // TODO(user): Remove the MPSReader class. class ABSL_DEPRECATED("Use the direct methods instead") MPSReader { public: - enum Form { AUTO_DETECT, FREE, FIXED }; - // Parses instance from a file. absl::Status ParseFile(const std::string& file_name, LinearProgram* data, - Form form = AUTO_DETECT); + MPSReaderForm form = AUTO_DETECT); absl::Status ParseFile(const std::string& file_name, MPModelProto* data, - Form form = AUTO_DETECT); + MPSReaderForm form = AUTO_DETECT); // Loads instance from string. Useful with MapReduce. Automatically detects // the file's format (free or fixed). absl::Status ParseProblemFromString(const std::string& source, LinearProgram* data, - MPSReader::Form form = AUTO_DETECT); + MPSReaderForm form = AUTO_DETECT); absl::Status ParseProblemFromString(const std::string& source, MPModelProto* data, - MPSReader::Form form = AUTO_DETECT); + MPSReaderForm form = AUTO_DETECT); }; } // namespace glop diff --git a/ortools/pdlp/iteration_stats.h b/ortools/pdlp/iteration_stats.h index 8e85f04172..0fb6291eba 100644 --- a/ortools/pdlp/iteration_stats.h +++ b/ortools/pdlp/iteration_stats.h @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if defined(USE_PDLP) + #ifndef PDLP_ITERATION_STATS_H_ #define PDLP_ITERATION_STATS_H_ @@ -114,3 +116,5 @@ void SetRandomProjections(const ShardedQuadraticProgram& sharded_qp, } // namespace operations_research::pdlp #endif // PDLP_ITERATION_STATS_H_ + +#endif // #if defined(USE_PDLP) diff --git a/ortools/pdlp/primal_dual_hybrid_gradient.h b/ortools/pdlp/primal_dual_hybrid_gradient.h index d5d38c1c5a..c68cfd76c2 100644 --- a/ortools/pdlp/primal_dual_hybrid_gradient.h +++ b/ortools/pdlp/primal_dual_hybrid_gradient.h @@ -10,6 +10,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#if defined(USE_PDLP) #ifndef PDLP_PRIMAL_DUAL_HYBRID_GRADIENT_H_ #define PDLP_PRIMAL_DUAL_HYBRID_GRADIENT_H_ @@ -148,3 +149,5 @@ glop::ProblemSolution ComputeStatuses(const QuadraticProgram& qp, } // namespace operations_research::pdlp #endif // PDLP_PRIMAL_DUAL_HYBRID_GRADIENT_H_ + +#endif // #if defined(USE_PDLP) diff --git a/ortools/pdlp/quadratic_program.h b/ortools/pdlp/quadratic_program.h index a88e1eabc8..05d41df5b2 100644 --- a/ortools/pdlp/quadratic_program.h +++ b/ortools/pdlp/quadratic_program.h @@ -10,6 +10,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#if defined(USE_PDLP) #ifndef PDLP_QUADRATIC_PROGRAM_H_ #define PDLP_QUADRATIC_PROGRAM_H_ @@ -214,3 +215,5 @@ void CombineRepeatedTripletsInPlace( } // namespace operations_research::pdlp #endif // PDLP_QUADRATIC_PROGRAM_H_ + +#endif // #if defined(USE_PDLP) diff --git a/ortools/sat/cp_model_utils.cc b/ortools/sat/cp_model_utils.cc index 194a486253..4bca1c61e9 100644 --- a/ortools/sat/cp_model_utils.cc +++ b/ortools/sat/cp_model_utils.cc @@ -439,6 +439,7 @@ std::string ConstraintCaseName( case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET: return "kEmpty"; } + throw std::logic_error("Unhandled ConstraintCase enum value"); } std::vector UsedVariables(const ConstraintProto& ct) { diff --git a/ortools/sat/linear_programming_constraint.cc b/ortools/sat/linear_programming_constraint.cc index 532d16caf4..d7084f1244 100644 --- a/ortools/sat/linear_programming_constraint.cc +++ b/ortools/sat/linear_programming_constraint.cc @@ -2616,7 +2616,8 @@ LinearProgrammingConstraint::HeuristicLpReducedCostBinary(Model* model) { std::vector num_cost_to_zero(num_vars); int num_calls = 0; - return [=]() mutable { + return [this, &num_calls, &num_vars, &cost_to_zero, &num_cost_to_zero, + &variables]() mutable { const double kEpsilon = 1e-6; // Every 10000 calls, decay pseudocosts. -- 2.41.0