tkurbad-overlay/sci-libs/or-tools/files/Support-for-USE_PDLP-C-23-a...

539 lines
22 KiB
Diff

From e401b3e7cda8047ba7c29fa85acd8cf2d63064e8 Mon Sep 17 00:00:00 2001
From: Amit Prakash Ambasta <amit.prakash.ambasta@gmail.com>
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 <amit.prakash.ambasta@gmail.com>
---
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 <cmath>
#include <limits>
#include <queue>
+#include <stdexcept>
#include <vector>
#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 <compare>
#include <iterator>
#include <vector>
@@ -102,15 +103,24 @@ BeginEndReverseIteratorWrapper<Container> Reverse(const Container& c) {
// Simple iterator on an integer range, see IntegerRange below.
template <typename IntegerType>
-class IntegerRangeIterator
- : public std::iterator<std::input_iterator_tag, IntegerType> {
+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<int>(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 <atomic>
#include <cstdint>
#include <optional>
@@ -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<MPSolutionResponse> 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<MPSolutionResponse> 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 <class Data>
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 <class Data>
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<MPModelProto> {
template <class Data>
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> data_wrapper(data);
data_wrapper.SetUp();
@@ -553,15 +553,15 @@ absl::Status MPSReaderImpl::ParseFile(const std::string& file_name, Data* data,
template <class Data>
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> 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<MPModelProto> 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<MPModelProto> 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<MPModelProto> MpsDataToMPModelProto(const std::string& mps_data);
// Parses an MPS model from a file.
absl::StatusOr<MPModelProto> 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<MPModelProto> 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<int> 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<int> 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