Update linear solver build (#4945)
This commit is contained in:
committed by
Corentin Le Molgat
parent
6d76575f3d
commit
69dc22f35d
@@ -14,6 +14,7 @@
|
||||
// Integer programming example that shows how to use the API.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -26,47 +27,40 @@
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
|
||||
namespace operations_research {
|
||||
void RunIntegerProgrammingExample(absl::string_view solver_id) {
|
||||
void RunIntegerProgrammingExample(const std::string& solver_id) {
|
||||
LOG(INFO) << "---- Integer programming example with " << solver_id << " ----";
|
||||
|
||||
MPSolver::OptimizationProblemType problem_type;
|
||||
if (!MPSolver::ParseSolverType(solver_id, &problem_type)) {
|
||||
LOG(INFO) << "Solver id " << solver_id << " not recognized";
|
||||
std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver(solver_id));
|
||||
if (!solver) {
|
||||
LOG(INFO) << "Unable to create solver : " << solver_id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MPSolver::SupportsProblemType(problem_type)) {
|
||||
LOG(INFO) << "Supports for solver " << solver_id << " not linked in.";
|
||||
return;
|
||||
}
|
||||
|
||||
MPSolver solver("IntegerProgrammingExample", problem_type);
|
||||
|
||||
const double infinity = solver.infinity();
|
||||
const double infinity = solver->infinity();
|
||||
// x and y are integer non-negative variables.
|
||||
MPVariable* const x = solver.MakeIntVar(0.0, infinity, "x");
|
||||
MPVariable* const y = solver.MakeIntVar(0.0, infinity, "y");
|
||||
MPVariable* const x = solver->MakeIntVar(0.0, infinity, "x");
|
||||
MPVariable* const y = solver->MakeIntVar(0.0, infinity, "y");
|
||||
|
||||
// Maximize x + 10 * y.
|
||||
MPObjective* const objective = solver.MutableObjective();
|
||||
MPObjective* const objective = solver->MutableObjective();
|
||||
objective->SetCoefficient(x, 1);
|
||||
objective->SetCoefficient(y, 10);
|
||||
objective->SetMaximization();
|
||||
|
||||
// x + 7 * y <= 17.5.
|
||||
MPConstraint* const c0 = solver.MakeRowConstraint(-infinity, 17.5);
|
||||
MPConstraint* const c0 = solver->MakeRowConstraint(-infinity, 17.5);
|
||||
c0->SetCoefficient(x, 1);
|
||||
c0->SetCoefficient(y, 7);
|
||||
|
||||
// x <= 3.5
|
||||
MPConstraint* const c1 = solver.MakeRowConstraint(-infinity, 3.5);
|
||||
MPConstraint* const c1 = solver->MakeRowConstraint(-infinity, 3.5);
|
||||
c1->SetCoefficient(x, 1);
|
||||
c1->SetCoefficient(y, 0);
|
||||
|
||||
LOG(INFO) << "Number of variables = " << solver.NumVariables();
|
||||
LOG(INFO) << "Number of constraints = " << solver.NumConstraints();
|
||||
LOG(INFO) << "Number of variables = " << solver->NumVariables();
|
||||
LOG(INFO) << "Number of constraints = " << solver->NumConstraints();
|
||||
|
||||
const MPSolver::ResultStatus result_status = solver.Solve();
|
||||
const MPSolver::ResultStatus result_status = solver->Solve();
|
||||
// Check that the problem has an optimal solution.
|
||||
if (result_status != MPSolver::OPTIMAL) {
|
||||
LOG(FATAL) << "The problem does not have an optimal solution!";
|
||||
@@ -77,21 +71,33 @@ void RunIntegerProgrammingExample(absl::string_view solver_id) {
|
||||
LOG(INFO) << "Optimal objective value = " << objective->Value();
|
||||
LOG(INFO) << "";
|
||||
LOG(INFO) << "Advanced usage:";
|
||||
LOG(INFO) << "Problem solved in " << solver.wall_time() << " milliseconds";
|
||||
LOG(INFO) << "Problem solved in " << solver.iterations() << " iterations";
|
||||
LOG(INFO) << "Problem solved in " << solver.nodes()
|
||||
LOG(INFO) << "Problem solved in " << solver->wall_time() << " milliseconds";
|
||||
LOG(INFO) << "Problem solved in " << solver->iterations() << " iterations";
|
||||
LOG(INFO) << "Problem solved in " << solver->nodes()
|
||||
<< " branch-and-bound nodes";
|
||||
}
|
||||
|
||||
void RunAllExamples() {
|
||||
RunIntegerProgrammingExample("CBC");
|
||||
RunIntegerProgrammingExample("SAT");
|
||||
RunIntegerProgrammingExample("SCIP");
|
||||
RunIntegerProgrammingExample("GUROBI");
|
||||
RunIntegerProgrammingExample("GLPK");
|
||||
RunIntegerProgrammingExample("CPLEX");
|
||||
RunIntegerProgrammingExample("XPRESS");
|
||||
RunIntegerProgrammingExample("HIGHS");
|
||||
std::vector<MPSolver::OptimizationProblemType> supported_problem_types =
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()
|
||||
->ListAllRegisteredProblemTypes();
|
||||
for (MPSolver::OptimizationProblemType type : supported_problem_types) {
|
||||
const std::string type_name = MPModelRequest::SolverType_Name(
|
||||
static_cast<MPModelRequest::SolverType>(type));
|
||||
if (!SolverTypeIsMip(type)) continue;
|
||||
if (absl::StrContains(type_name, "KNAPSACK")) continue;
|
||||
if (absl::StrContains(type_name, "BOP")) continue;
|
||||
if (absl::StrContains(type_name, "HIGHS")) continue;
|
||||
// ASAN issues a warning in CBC code which cannot be avoided for now:
|
||||
// AddressSanitizer: float-cast-overflow
|
||||
// third_party/cbc/Cgl/src/CglPreProcess/CglPreProcess.cpp:1717:36
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
if (type_name.find("CBC") != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
RunIntegerProgrammingExample(type_name);
|
||||
}
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// Linear programming example that shows how to use the API.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -22,71 +23,64 @@
|
||||
#include "absl/log/log.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "ortools/base/commandlineflags.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
#include "ortools/linear_solver/linear_solver.pb.h"
|
||||
|
||||
namespace operations_research {
|
||||
void RunLinearProgrammingExample(absl::string_view solver_id) {
|
||||
void RunLinearProgrammingExample(const std::string& solver_id) {
|
||||
LOG(INFO) << "---- Linear programming example with " << solver_id << " ----";
|
||||
MPSolver::OptimizationProblemType problem_type;
|
||||
if (!MPSolver::ParseSolverType(solver_id, &problem_type)) {
|
||||
LOG(INFO) << "Solver id " << solver_id << " not recognized";
|
||||
|
||||
std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver(solver_id));
|
||||
if (!solver) {
|
||||
LOG(INFO) << "Unable to create solver : " << solver_id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MPSolver::SupportsProblemType(problem_type)) {
|
||||
LOG(INFO) << "Supports for solver " << solver_id << " not linked in.";
|
||||
return;
|
||||
}
|
||||
|
||||
MPSolver solver("IntegerProgrammingExample", problem_type);
|
||||
|
||||
const double infinity = solver.infinity();
|
||||
const double infinity = solver->infinity();
|
||||
// x1, x2 and x3 are continuous non-negative variables.
|
||||
MPVariable* const x1 = solver.MakeNumVar(0.0, infinity, "x1");
|
||||
MPVariable* const x2 = solver.MakeNumVar(0.0, infinity, "x2");
|
||||
MPVariable* const x3 = solver.MakeNumVar(0.0, infinity, "x3");
|
||||
MPVariable* const x1 = solver->MakeNumVar(0.0, infinity, "x1");
|
||||
MPVariable* const x2 = solver->MakeNumVar(0.0, infinity, "x2");
|
||||
MPVariable* const x3 = solver->MakeNumVar(0.0, infinity, "x3");
|
||||
|
||||
// Maximize 10 * x1 + 6 * x2 + 4 * x3.
|
||||
MPObjective* const objective = solver.MutableObjective();
|
||||
MPObjective* const objective = solver->MutableObjective();
|
||||
objective->SetCoefficient(x1, 10);
|
||||
objective->SetCoefficient(x2, 6);
|
||||
objective->SetCoefficient(x3, 4);
|
||||
objective->SetMaximization();
|
||||
|
||||
// x1 + x2 + x3 <= 100.
|
||||
MPConstraint* const c0 = solver.MakeRowConstraint(-infinity, 100.0);
|
||||
MPConstraint* const c0 = solver->MakeRowConstraint(-infinity, 100.0);
|
||||
c0->SetCoefficient(x1, 1);
|
||||
c0->SetCoefficient(x2, 1);
|
||||
c0->SetCoefficient(x3, 1);
|
||||
|
||||
// 10 * x1 + 4 * x2 + 5 * x3 <= 600.
|
||||
MPConstraint* const c1 = solver.MakeRowConstraint(-infinity, 600.0);
|
||||
MPConstraint* const c1 = solver->MakeRowConstraint(-infinity, 600.0);
|
||||
c1->SetCoefficient(x1, 10);
|
||||
c1->SetCoefficient(x2, 4);
|
||||
c1->SetCoefficient(x3, 5);
|
||||
|
||||
// 2 * x1 + 2 * x2 + 6 * x3 <= 300.
|
||||
MPConstraint* const c2 = solver.MakeRowConstraint(-infinity, 300.0);
|
||||
MPConstraint* const c2 = solver->MakeRowConstraint(-infinity, 300.0);
|
||||
c2->SetCoefficient(x1, 2);
|
||||
c2->SetCoefficient(x2, 2);
|
||||
c2->SetCoefficient(x3, 6);
|
||||
|
||||
// TODO(user): Change example to show = and >= constraints.
|
||||
|
||||
LOG(INFO) << "Number of variables = " << solver.NumVariables();
|
||||
LOG(INFO) << "Number of constraints = " << solver.NumConstraints();
|
||||
LOG(INFO) << "Number of variables = " << solver->NumVariables();
|
||||
LOG(INFO) << "Number of constraints = " << solver->NumConstraints();
|
||||
|
||||
const MPSolver::ResultStatus result_status = solver.Solve();
|
||||
const MPSolver::ResultStatus result_status = solver->Solve();
|
||||
|
||||
// Check that the problem has an optimal solution.
|
||||
if (result_status != MPSolver::OPTIMAL) {
|
||||
LOG(FATAL) << "The problem does not have an optimal solution!";
|
||||
}
|
||||
|
||||
LOG(INFO) << "Problem solved in " << solver.wall_time() << " milliseconds";
|
||||
LOG(INFO) << "Problem solved in " << solver->wall_time() << " milliseconds";
|
||||
|
||||
// The objective value of the solution.
|
||||
LOG(INFO) << "Optimal objective value = " << objective->Value();
|
||||
@@ -97,11 +91,11 @@ void RunLinearProgrammingExample(absl::string_view solver_id) {
|
||||
LOG(INFO) << "x3 = " << x3->solution_value();
|
||||
|
||||
LOG(INFO) << "Advanced usage:";
|
||||
LOG(INFO) << "Problem solved in " << solver.iterations() << " iterations";
|
||||
LOG(INFO) << "Problem solved in " << solver->iterations() << " iterations";
|
||||
LOG(INFO) << "x1: reduced cost = " << x1->reduced_cost();
|
||||
LOG(INFO) << "x2: reduced cost = " << x2->reduced_cost();
|
||||
LOG(INFO) << "x3: reduced cost = " << x3->reduced_cost();
|
||||
const std::vector<double> activities = solver.ComputeConstraintActivities();
|
||||
const std::vector<double> activities = solver->ComputeConstraintActivities();
|
||||
LOG(INFO) << "c0: dual value = " << c0->dual_value()
|
||||
<< " activity = " << activities[c0->index()];
|
||||
LOG(INFO) << "c1: dual value = " << c1->dual_value()
|
||||
@@ -111,14 +105,16 @@ void RunLinearProgrammingExample(absl::string_view solver_id) {
|
||||
}
|
||||
|
||||
void RunAllExamples() {
|
||||
RunLinearProgrammingExample("GLOP");
|
||||
RunLinearProgrammingExample("CLP");
|
||||
RunLinearProgrammingExample("GUROBI_LP");
|
||||
RunLinearProgrammingExample("CPLEX_LP");
|
||||
RunLinearProgrammingExample("GLPK_LP");
|
||||
RunLinearProgrammingExample("XPRESS_LP");
|
||||
RunLinearProgrammingExample("PDLP");
|
||||
RunLinearProgrammingExample("HIGHS_LP");
|
||||
std::vector<MPSolver::OptimizationProblemType> supported_problem_types =
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()
|
||||
->ListAllRegisteredProblemTypes();
|
||||
for (MPSolver::OptimizationProblemType type : supported_problem_types) {
|
||||
const std::string type_name = MPModelRequest::SolverType_Name(
|
||||
static_cast<MPModelRequest::SolverType>(type));
|
||||
if (!absl::StrContains(type_name, "LINEAR_PROGRAMMING")) continue;
|
||||
if (absl::StrContains(type_name, "HIGHS")) continue;
|
||||
RunLinearProgrammingExample(type_name);
|
||||
}
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
|
||||
@@ -610,36 +610,29 @@ int main(int argc, char** argv) {
|
||||
|
||||
operations_research::MPSolver::OptimizationProblemType solver_type;
|
||||
bool found = false;
|
||||
#if defined(USE_CLP)
|
||||
if (absl::GetFlag(FLAGS_colgen_solver) == "clp") {
|
||||
const std::string solver_name = absl::GetFlag(FLAGS_colgen_solver);
|
||||
if (solver_name == "clp") {
|
||||
solver_type = operations_research::MPSolver::CLP_LINEAR_PROGRAMMING;
|
||||
found = true;
|
||||
}
|
||||
#endif // USE_CLP
|
||||
if (absl::GetFlag(FLAGS_colgen_solver) == "glop") {
|
||||
if (solver_name == "glop") {
|
||||
solver_type = operations_research::MPSolver::GLOP_LINEAR_PROGRAMMING;
|
||||
found = true;
|
||||
}
|
||||
#if defined(USE_XPRESS)
|
||||
if (absl::GetFlag(FLAGS_colgen_solver) == "xpress") {
|
||||
if (solver_name == "xpress") {
|
||||
solver_type = operations_research::MPSolver::XPRESS_LINEAR_PROGRAMMING;
|
||||
// solver_type = operations_research::MPSolver::CPLEX_LINEAR_PROGRAMMING;
|
||||
found = true;
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_CPLEX)
|
||||
if (absl::GetFlag(FLAGS_colgen_solver) == "cplex") {
|
||||
if (solver_name == "cplex") {
|
||||
solver_type = operations_research::MPSolver::CPLEX_LINEAR_PROGRAMMING;
|
||||
found = true;
|
||||
}
|
||||
#endif
|
||||
if (!found) {
|
||||
LOG(ERROR) << "Unknown solver " << absl::GetFlag(FLAGS_colgen_solver);
|
||||
return 1;
|
||||
LOG(ERROR) << "Unknown solver " << solver_name;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Chosen solver: " << absl::GetFlag(FLAGS_colgen_solver)
|
||||
<< std::endl;
|
||||
LOG(INFO) << "Chosen solver: " << solver_name << std::endl;
|
||||
|
||||
if (absl::GetFlag(FLAGS_colgen_instance) == -1) {
|
||||
for (int i = 0; i < operations_research::kInstanceCount; ++i) {
|
||||
|
||||
@@ -11,36 +11,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("@rules_cc//cc:cc_test.bzl", "cc_test")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
# Description:
|
||||
# Home of algorithms used in OR solvers
|
||||
|
||||
# OSS solvers
|
||||
bool_flag(
|
||||
name = "with_cbc",
|
||||
build_setting_default = False,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "use_cbc",
|
||||
flag_values = {":with_cbc": "true"},
|
||||
)
|
||||
|
||||
bool_flag(
|
||||
name = "with_scip",
|
||||
build_setting_default = True,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "use_scip",
|
||||
flag_values = {":with_scip": "true"},
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "binary_search",
|
||||
srcs = [],
|
||||
@@ -190,14 +165,8 @@ cc_library(
|
||||
name = "knapsack_solver_lib",
|
||||
srcs = ["knapsack_solver.cc"],
|
||||
hdrs = ["knapsack_solver.h"],
|
||||
copts = [] + select({
|
||||
":use_cbc": ["-DUSE_CBC"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_scip": ["-DUSE_SCIP"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
deps = [
|
||||
"@abseil-cpp//absl/log",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/strings",
|
||||
"@abseil-cpp//absl/time",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/log/log.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "ortools/base/stl_util.h"
|
||||
@@ -1071,7 +1072,7 @@ class KnapsackDivideAndConquerSolver : public BaseKnapsackSolver {
|
||||
}
|
||||
|
||||
private:
|
||||
// 'DP 2' computes solution 'z' for 0 up to capacitiy
|
||||
// 'DP 2' computes solution 'z' for 0 up to capacity
|
||||
void SolveSubProblem(bool first_storage, int64_t capacity, int start_item,
|
||||
int end_item);
|
||||
|
||||
@@ -1411,30 +1412,22 @@ KnapsackSolver::KnapsackSolver(SolverType solver_type,
|
||||
case KNAPSACK_DIVIDE_AND_CONQUER_SOLVER:
|
||||
solver_ = std::make_unique<KnapsackDivideAndConquerSolver>(solver_name);
|
||||
break;
|
||||
#if defined(USE_CBC)
|
||||
case KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER:
|
||||
solver_ = std::make_unique<KnapsackMIPSolver>(
|
||||
MPSolver::CBC_MIXED_INTEGER_PROGRAMMING, solver_name);
|
||||
break;
|
||||
#endif // USE_CBC
|
||||
#if defined(USE_SCIP)
|
||||
case KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER:
|
||||
solver_ = std::make_unique<KnapsackMIPSolver>(
|
||||
MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING, solver_name);
|
||||
break;
|
||||
#endif // USE_SCIP
|
||||
#if defined(USE_XPRESS)
|
||||
case KNAPSACK_MULTIDIMENSION_XPRESS_MIP_SOLVER:
|
||||
solver_ = std::make_unique<KnapsackMIPSolver>(
|
||||
MPSolver::XPRESS_MIXED_INTEGER_PROGRAMMING, solver_name);
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_CPLEX)
|
||||
case KNAPSACK_MULTIDIMENSION_CPLEX_MIP_SOLVER:
|
||||
solver_ = std::make_unique<KnapsackMIPSolver>(
|
||||
MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING, solver_name);
|
||||
break;
|
||||
#endif
|
||||
case KNAPSACK_MULTIDIMENSION_CP_SAT_SOLVER:
|
||||
solver_ = std::make_unique<KnapsackCpSat>(solver_name);
|
||||
break;
|
||||
|
||||
@@ -130,14 +130,12 @@ class KnapsackSolver {
|
||||
*/
|
||||
KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER = 2,
|
||||
|
||||
#if defined(USE_CBC)
|
||||
/** CBC Based Solver
|
||||
*
|
||||
* This solver can deal with both large number of items and several
|
||||
* dimensions. This solver is based on Integer Programming solver CBC.
|
||||
*/
|
||||
KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER = 3,
|
||||
#endif // USE_CBC
|
||||
|
||||
/** Generic Solver.
|
||||
*
|
||||
@@ -146,32 +144,27 @@ class KnapsackSolver {
|
||||
*/
|
||||
KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER = 5,
|
||||
|
||||
#if defined(USE_SCIP)
|
||||
/** SCIP based solver
|
||||
*
|
||||
* This solver can deal with both large number of items and several
|
||||
* dimensions. This solver is based on Integer Programming solver SCIP.
|
||||
*/
|
||||
KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER = 6,
|
||||
#endif // USE_SCIP
|
||||
|
||||
#if defined(USE_XPRESS)
|
||||
/** XPRESS based solver
|
||||
*
|
||||
* This solver can deal with both large number of items and several
|
||||
* dimensions. This solver is based on Integer Programming solver XPRESS.
|
||||
*/
|
||||
KNAPSACK_MULTIDIMENSION_XPRESS_MIP_SOLVER = 7,
|
||||
#endif
|
||||
|
||||
#if defined(USE_CPLEX)
|
||||
/** CPLEX based solver
|
||||
*
|
||||
* This solver can deal with both large number of items and several
|
||||
* dimensions. This solver is based on Integer Programming solver CPLEX.
|
||||
*/
|
||||
KNAPSACK_MULTIDIMENSION_CPLEX_MIP_SOLVER = 8,
|
||||
#endif
|
||||
|
||||
/** Divide and Conquer approach for single dimension problems
|
||||
*
|
||||
* Limited to one dimension, this solver is based on a divide and conquer
|
||||
@@ -180,6 +173,7 @@ class KnapsackSolver {
|
||||
* space complexity is O(capacity + number_of_items).
|
||||
*/
|
||||
KNAPSACK_DIVIDE_AND_CONQUER_SOLVER = 9,
|
||||
|
||||
/** CP-SAT based solver
|
||||
*
|
||||
* This solver can deal with both large number of items and several
|
||||
|
||||
@@ -13,33 +13,11 @@
|
||||
|
||||
# Description: python wrapping of the libraries in ../
|
||||
|
||||
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
|
||||
load("@pip_deps//:requirements.bzl", "requirement")
|
||||
load("@pybind11_bazel//:build_defs.bzl", "pybind_extension")
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("@rules_python//python:py_test.bzl", "py_test")
|
||||
|
||||
# OSS solvers
|
||||
bool_flag(
|
||||
name = "with_cbc",
|
||||
build_setting_default = False,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "use_cbc",
|
||||
flag_values = {":with_cbc": "true"},
|
||||
)
|
||||
|
||||
bool_flag(
|
||||
name = "with_scip",
|
||||
build_setting_default = True,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "use_scip",
|
||||
flag_values = {":with_scip": "true"},
|
||||
)
|
||||
|
||||
# knapsack_solver
|
||||
cc_library(
|
||||
name = "knapsack_solver_doc",
|
||||
@@ -50,13 +28,6 @@ cc_library(
|
||||
pybind_extension(
|
||||
name = "knapsack_solver",
|
||||
srcs = ["knapsack_solver.cc"],
|
||||
copts = select({
|
||||
":use_cbc": ["-DUSE_CBC"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_scip": ["-DUSE_SCIP"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":knapsack_solver_doc",
|
||||
|
||||
@@ -67,19 +67,15 @@ PYBIND11_MODULE(knapsack_solver, m) {
|
||||
KnapsackSolver::SolverType::KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER,
|
||||
DOC(operations_research, KnapsackSolver, SolverType,
|
||||
KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER))
|
||||
#if defined(USE_CBC)
|
||||
.value("KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER",
|
||||
KnapsackSolver::SolverType::KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER,
|
||||
DOC(operations_research, KnapsackSolver, SolverType,
|
||||
KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER))
|
||||
#endif // USE_CBC
|
||||
#if defined(USE_SCIP)
|
||||
.value(
|
||||
"KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER",
|
||||
KnapsackSolver::SolverType::KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER,
|
||||
DOC(operations_research, KnapsackSolver, SolverType,
|
||||
KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER))
|
||||
#endif // USE_SCIP
|
||||
.value("KNAPSACK_DIVIDE_AND_CONQUER_SOLVER",
|
||||
KnapsackSolver::SolverType::KNAPSACK_DIVIDE_AND_CONQUER_SOLVER,
|
||||
DOC(operations_research, KnapsackSolver, SolverType,
|
||||
|
||||
@@ -73,6 +73,16 @@ config_setting(
|
||||
flag_values = {":with_glop": "true"},
|
||||
)
|
||||
|
||||
bool_flag(
|
||||
name = "with_gurobi",
|
||||
build_setting_default = True,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "use_gurobi",
|
||||
flag_values = {":with_gurobi": "true"},
|
||||
)
|
||||
|
||||
bool_flag(
|
||||
name = "with_glpk",
|
||||
build_setting_default = False,
|
||||
@@ -124,6 +134,16 @@ config_setting(
|
||||
flag_values = {":with_cplex": "true"},
|
||||
)
|
||||
|
||||
bool_flag(
|
||||
name = "with_xpress",
|
||||
build_setting_default = True,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "use_xpress",
|
||||
flag_values = {":with_xpress": "true"},
|
||||
)
|
||||
|
||||
# Linear solver proto, used for (efficient!) model storage.
|
||||
proto_library(
|
||||
name = "linear_solver_proto",
|
||||
@@ -150,13 +170,10 @@ py_proto_library(
|
||||
cc_library(
|
||||
name = "linear_solver",
|
||||
srcs = [
|
||||
"gurobi_interface.cc",
|
||||
"gurobi_util.cc",
|
||||
"linear_expr.cc",
|
||||
"linear_solver.cc",
|
||||
"linear_solver_callback.cc",
|
||||
"sat_interface.cc",
|
||||
"xpress_interface.cc",
|
||||
] + select({
|
||||
":use_bop": ["bop_interface.cc"],
|
||||
"//conditions:default": [],
|
||||
@@ -175,6 +192,12 @@ cc_library(
|
||||
}) + select({
|
||||
":use_glpk": ["glpk_interface.cc"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_gurobi": [
|
||||
"gurobi_interface.cc",
|
||||
"gurobi_util.cc",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_highs": ["highs_interface.cc"],
|
||||
"//conditions:default": [],
|
||||
@@ -190,15 +213,20 @@ cc_library(
|
||||
}) + select({
|
||||
":use_cplex": ["cplex_interface.cc"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_xpress": ["xpress_interface.cc"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
hdrs = [
|
||||
"gurobi_util.h",
|
||||
"linear_expr.h",
|
||||
"linear_solver.h",
|
||||
"linear_solver_callback.h",
|
||||
] + select({
|
||||
":use_glop": ["glop_utils.h"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_gurobi": ["gurobi_util.h"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_scip": [
|
||||
"scip_callback.h",
|
||||
@@ -206,34 +234,6 @@ cc_library(
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
copts = [] + select({
|
||||
":use_bop": ["-DUSE_BOP"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_cbc": ["-DUSE_CBC"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_clp": ["-DUSE_CLP"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_glop": ["-DUSE_GLOP"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_glpk": ["-DUSE_GLPK"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_highs": ["-DUSE_HIGHS"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_pdlp": ["-DUSE_PDLP"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_scip": ["-DUSE_SCIP"],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_cplex": ["-DUSE_CPLEX"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
deps = [
|
||||
":linear_solver_cc_proto",
|
||||
":model_exporter",
|
||||
@@ -246,15 +246,12 @@ cc_library(
|
||||
"//ortools/base:status_macros",
|
||||
"//ortools/base:stl_util",
|
||||
"//ortools/base:timer",
|
||||
"//ortools/linear_solver/proto_solver:gurobi_proto_solver",
|
||||
"//ortools/linear_solver/proto_solver:sat_proto_solver",
|
||||
"//ortools/port:file",
|
||||
"//ortools/port:proto_utils",
|
||||
"//ortools/sat:cp_model_cc_proto",
|
||||
"//ortools/sat:cp_model_solver",
|
||||
"//ortools/sat:lp_utils",
|
||||
"//ortools/third_party_solvers:gurobi_environment",
|
||||
"//ortools/third_party_solvers:xpress_environment",
|
||||
"//ortools/util:fp_utils",
|
||||
"//ortools/util:lazy_mutable_copy",
|
||||
"@abseil-cpp//absl/status",
|
||||
@@ -281,6 +278,12 @@ cc_library(
|
||||
"@glpk",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_gurobi": [
|
||||
"//ortools/linear_solver/proto_solver:gurobi_proto_solver",
|
||||
"//ortools/third_party_solvers:gurobi_environment",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_pdlp": [
|
||||
"//ortools/linear_solver/proto_solver:pdlp_proto_solver",
|
||||
@@ -302,7 +305,11 @@ cc_library(
|
||||
"@highs",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
":use_xpress": ["//ortools/third_party_solvers:xpress_environment"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
alwayslink = 1, # Important! Library is used via dependency injection.
|
||||
)
|
||||
|
||||
cc_library(
|
||||
|
||||
@@ -11,24 +11,73 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
file(GLOB _SRCS "*.h" "*.cc")
|
||||
list(REMOVE_ITEM _SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/solve.cc
|
||||
list(APPEND _SRCS
|
||||
linear_expr.cc
|
||||
linear_expr.h
|
||||
linear_solver_callback.cc
|
||||
linear_solver_callback.h
|
||||
linear_solver.cc
|
||||
linear_solver.h
|
||||
model_exporter_swig_helper.h
|
||||
model_exporter.cc
|
||||
model_exporter.h
|
||||
model_validator.cc
|
||||
model_validator.h
|
||||
solve_mp_model.cc
|
||||
solve_mp_model.h
|
||||
sat_interface.cc
|
||||
)
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/model_exporter_main\\.cc")
|
||||
list(FILTER _SRCS EXCLUDE REGEX ".*/.*_test.cc")
|
||||
|
||||
if(USE_BOP)
|
||||
list(APPEND _SRCS bop_interface.cc)
|
||||
endif()
|
||||
|
||||
if(USE_COINOR)
|
||||
list(APPEND _SRCS cbc_interface.cc clp_interface.cc)
|
||||
endif()
|
||||
|
||||
if(USE_CPLEX)
|
||||
list(APPEND _SRCS cplex_interface.cc)
|
||||
endif()
|
||||
|
||||
if(USE_GLOP)
|
||||
list(APPEND _SRCS glop_interface.cc glop_utils.cc glop_utils.h)
|
||||
endif()
|
||||
|
||||
if(USE_GUROBI)
|
||||
list(APPEND _SRCS gurobi_util.h gurobi_interface.cc gurobi_util.cc)
|
||||
endif()
|
||||
|
||||
if(USE_GLPK)
|
||||
list(APPEND _SRCS glpk_interface.cc)
|
||||
endif()
|
||||
|
||||
if(USE_HIGHS)
|
||||
list(APPEND _SRCS highs_interface.cc)
|
||||
endif()
|
||||
|
||||
if(USE_PDLP)
|
||||
list(APPEND _SRCS pdlp_interface.cc)
|
||||
endif()
|
||||
|
||||
if(USE_SCIP)
|
||||
list(APPEND _SRCS ${LPI_GLOP_SRC})
|
||||
list(APPEND _SRCS
|
||||
scip_callback.cc
|
||||
scip_callback.h
|
||||
scip_helper_macros.h
|
||||
scip_interface.cc
|
||||
${LPI_GLOP_SRC})
|
||||
endif()
|
||||
|
||||
if(USE_XPRESS)
|
||||
list(APPEND _SRCS xpress_interface.cc)
|
||||
endif()
|
||||
|
||||
set(NAME ${PROJECT_NAME}_linear_solver)
|
||||
|
||||
# Will be merge in libortools.so
|
||||
#add_library(${NAME} STATIC ${_SRCS})
|
||||
add_library(${NAME} OBJECT ${_SRCS})
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
set_target_properties(${NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
if(MSVC AND BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(${NAME} PUBLIC "OR_BUILD_DLL")
|
||||
target_compile_definitions(${NAME} PRIVATE "OR_EXPORT")
|
||||
@@ -50,7 +99,6 @@ target_link_libraries(${NAME} PRIVATE
|
||||
$<$<BOOL:${USE_PDLP}>:Eigen3::Eigen>
|
||||
$<$<BOOL:${USE_SCIP}>:SCIP::libscip>
|
||||
${PROJECT_NAMESPACE}::ortools_proto)
|
||||
#add_library(${PROJECT_NAMESPACE}::linear_solver ALIAS ${NAME})
|
||||
|
||||
# solve
|
||||
add_executable(solve)
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_BOP)
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -21,11 +19,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "google/protobuf/text_format.h"
|
||||
#include "ortools/base/commandlineflags.h"
|
||||
#include "ortools/base/file.h"
|
||||
#include "ortools/base/hash.h"
|
||||
#include "ortools/base/helpers.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/bop/bop_parameters.pb.h"
|
||||
#include "ortools/bop/integral_solver.h"
|
||||
@@ -387,10 +380,16 @@ void BopInterface::NonIncrementalChange() {
|
||||
sync_status_ = MUST_RELOAD;
|
||||
}
|
||||
|
||||
// Register BOP in the global linear solver factory.
|
||||
MPSolverInterface* BuildBopInterface(MPSolver* const solver) {
|
||||
return new BopInterface(solver);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterBop ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new BopInterface(solver); },
|
||||
MPSolver::BOP_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_BOP)
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_CBC)
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
@@ -23,8 +21,6 @@
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "ortools/base/commandlineflags.h"
|
||||
#include "ortools/base/hash.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/base/timer.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
@@ -529,9 +525,16 @@ void CBCInterface::SetLpAlgorithm(int value) {
|
||||
SetUnsupportedIntegerParam(MPSolverParameters::LP_ALGORITHM);
|
||||
}
|
||||
|
||||
MPSolverInterface* BuildCBCInterface(MPSolver* const solver) {
|
||||
return new CBCInterface(solver);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterCBC ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new CBCInterface(solver); },
|
||||
MPSolver::CBC_MIXED_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_CBC)
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_CLP) || defined(USE_CBC)
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -617,9 +615,16 @@ void CLPInterface::SetLpAlgorithm(int value) {
|
||||
}
|
||||
}
|
||||
|
||||
MPSolverInterface* BuildCLPInterface(MPSolver* const solver) {
|
||||
return new CLPInterface(solver);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterCLP ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new CLPInterface(solver); },
|
||||
MPSolver::CLP_LINEAR_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_CBC) || defined(USE_CLP)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2014 IBM Corporation
|
||||
// Copyright 2010-2025 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -12,8 +12,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
// Initial version of this code was written by Daniel Junglas (IBM)
|
||||
#if defined(USE_CPLEX)
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
@@ -1282,11 +1280,6 @@ MPSolver::ResultStatus CplexInterface::Solve(MPSolverParameters const& param) {
|
||||
sync_status_ = SOLUTION_SYNCHRONIZED;
|
||||
return result_status_;
|
||||
}
|
||||
|
||||
MPSolverInterface* BuildCplexInterface(bool mip, MPSolver* const solver) {
|
||||
return new CplexInterface(solver, mip);
|
||||
}
|
||||
|
||||
bool CplexInterface::SetSolverSpecificParametersAsString(
|
||||
const std::string& parameters) {
|
||||
if (parameters.empty()) return true;
|
||||
@@ -1329,5 +1322,24 @@ bool CplexInterface::SetSolverSpecificParametersAsString(
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterCplex ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new CplexInterface(solver, false); },
|
||||
MPSolver::CPLEX_LINEAR_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterCplexMip ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new CplexInterface(solver, true); },
|
||||
MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_CPLEX)
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_GLOP)
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -35,8 +33,6 @@
|
||||
#include "ortools/util/time_limit.h"
|
||||
namespace operations_research {
|
||||
|
||||
namespace {} // Anonymous namespace
|
||||
|
||||
class GLOPInterface : public MPSolverInterface {
|
||||
public:
|
||||
explicit GLOPInterface(MPSolver* solver);
|
||||
@@ -437,10 +433,16 @@ void GLOPInterface::NonIncrementalChange() {
|
||||
sync_status_ = MUST_RELOAD;
|
||||
}
|
||||
|
||||
// Register GLOP in the global linear solver factory.
|
||||
MPSolverInterface* BuildGLOPInterface(MPSolver* const solver) {
|
||||
return new GLOPInterface(solver);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterGlop ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new GLOPInterface(solver); },
|
||||
MPSolver::GLOP_LINEAR_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_GLOP)
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_GLPK)
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
@@ -957,9 +955,24 @@ void GLPKInterface::SetLpAlgorithm(int value) {
|
||||
}
|
||||
}
|
||||
|
||||
MPSolverInterface* BuildGLPKInterface(bool mip, MPSolver* const solver) {
|
||||
return new GLPKInterface(solver, mip);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterGLPKLP ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* solver) { return new GLPKInterface(solver, false); },
|
||||
MPSolver::GLPK_LINEAR_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterGLPKMIP ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* solver) { return new GLPKInterface(solver, true); },
|
||||
MPSolver::GLPK_MIXED_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_GLPK)
|
||||
|
||||
@@ -1407,12 +1407,28 @@ void GurobiInterface::Write(const std::string& filename) {
|
||||
}
|
||||
}
|
||||
|
||||
MPSolverInterface* BuildGurobiInterface(bool mip, MPSolver* const solver) {
|
||||
return new GurobiInterface(solver, mip);
|
||||
}
|
||||
|
||||
void GurobiInterface::SetCallback(MPCallback* mp_callback) {
|
||||
callback_ = mp_callback;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterGurobiLp ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* solver) { return new GurobiInterface(solver, false); },
|
||||
MPSolver::GUROBI_LINEAR_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterGurobiMip ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* solver) { return new GurobiInterface(solver, true); },
|
||||
MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_HIGHS)
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
@@ -288,10 +286,24 @@ void HighsInterface::NonIncrementalChange() {
|
||||
sync_status_ = MUST_RELOAD;
|
||||
}
|
||||
|
||||
// Register PDLP in the global linear solver factory.
|
||||
MPSolverInterface* BuildHighsInterface(bool mip, MPSolver* const solver) {
|
||||
return new HighsInterface(solver, mip);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterHighsLp ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* solver) { return new HighsInterface(solver, false); },
|
||||
MPSolver::HIGHS_LINEAR_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterHighsMip ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* solver) { return new HighsInterface(solver, true); },
|
||||
MPSolver::HIGHS_MIXED_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_HIGHS)
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "ortools/algorithms/knapsack_solver.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
#include "ortools/util/fp_utils.h"
|
||||
@@ -358,9 +357,16 @@ double KnapsackInterface::GetVariableValueFromSolution(
|
||||
: 0.0;
|
||||
}
|
||||
|
||||
// Register Knapsack solver in the global linear solver factory.
|
||||
MPSolverInterface* BuildKnapsackInterface(MPSolver* const solver) {
|
||||
return new KnapsackInterface(solver);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterKnapsack ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new KnapsackInterface(solver); },
|
||||
MPSolver::KNAPSACK_MIXED_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -374,100 +374,15 @@ bool MPSolver::SetSolverSpecificParametersAsString(
|
||||
|
||||
// ----- Solver -----
|
||||
|
||||
#if defined(USE_BOP)
|
||||
extern MPSolverInterface* BuildBopInterface(MPSolver* const solver);
|
||||
#endif
|
||||
#if defined(USE_CBC)
|
||||
extern MPSolverInterface* BuildCBCInterface(MPSolver* const solver);
|
||||
#endif
|
||||
#if defined(USE_CLP) || defined(USE_CBC)
|
||||
extern MPSolverInterface* BuildCLPInterface(MPSolver* const solver);
|
||||
#endif
|
||||
#if defined(USE_GLOP)
|
||||
extern MPSolverInterface* BuildGLOPInterface(MPSolver* const solver);
|
||||
#endif
|
||||
#if defined(USE_GLPK)
|
||||
extern MPSolverInterface* BuildGLPKInterface(bool mip, MPSolver* const solver);
|
||||
#endif
|
||||
#if defined(USE_HIGHS)
|
||||
extern MPSolverInterface* BuildHighsInterface(bool mip, MPSolver* const solver);
|
||||
#endif
|
||||
#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);
|
||||
#endif
|
||||
extern MPSolverInterface* BuildGurobiInterface(bool mip,
|
||||
MPSolver* const solver);
|
||||
#if defined(USE_CPLEX)
|
||||
extern MPSolverInterface* BuildCplexInterface(bool mip, MPSolver* const solver);
|
||||
#endif
|
||||
extern MPSolverInterface* BuildXpressInterface(bool mip,
|
||||
MPSolver* const solver);
|
||||
|
||||
namespace {
|
||||
MPSolverInterface* BuildSolverInterface(MPSolver* const solver) {
|
||||
DCHECK(solver != nullptr);
|
||||
switch (solver->ProblemType()) {
|
||||
#if defined(USE_BOP)
|
||||
case MPSolver::BOP_INTEGER_PROGRAMMING:
|
||||
return BuildBopInterface(solver);
|
||||
#endif
|
||||
#if defined(USE_CBC)
|
||||
case MPSolver::CBC_MIXED_INTEGER_PROGRAMMING:
|
||||
return BuildCBCInterface(solver);
|
||||
#endif
|
||||
#if defined(USE_CLP) || defined(USE_CBC)
|
||||
case MPSolver::CLP_LINEAR_PROGRAMMING:
|
||||
return BuildCLPInterface(solver);
|
||||
#endif
|
||||
#if defined(USE_GLOP)
|
||||
case MPSolver::GLOP_LINEAR_PROGRAMMING:
|
||||
return BuildGLOPInterface(solver);
|
||||
#endif
|
||||
#if defined(USE_GLPK)
|
||||
case MPSolver::GLPK_LINEAR_PROGRAMMING:
|
||||
return BuildGLPKInterface(false, solver);
|
||||
case MPSolver::GLPK_MIXED_INTEGER_PROGRAMMING:
|
||||
return BuildGLPKInterface(true, solver);
|
||||
#endif
|
||||
#if defined(USE_HIGHS)
|
||||
case MPSolver::HIGHS_LINEAR_PROGRAMMING:
|
||||
return BuildHighsInterface(false, solver);
|
||||
case MPSolver::HIGHS_MIXED_INTEGER_PROGRAMMING:
|
||||
return BuildHighsInterface(true, solver);
|
||||
#endif
|
||||
#if defined(USE_PDLP)
|
||||
case MPSolver::PDLP_LINEAR_PROGRAMMING:
|
||||
return BuildPdlpInterface(solver);
|
||||
#endif
|
||||
case MPSolver::SAT_INTEGER_PROGRAMMING:
|
||||
return BuildSatInterface(solver);
|
||||
#if defined(USE_SCIP)
|
||||
case MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING:
|
||||
return BuildSCIPInterface(solver);
|
||||
#endif
|
||||
case MPSolver::GUROBI_LINEAR_PROGRAMMING:
|
||||
return BuildGurobiInterface(false, solver);
|
||||
case MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING:
|
||||
return BuildGurobiInterface(true, solver);
|
||||
#if defined(USE_CPLEX)
|
||||
case MPSolver::CPLEX_LINEAR_PROGRAMMING:
|
||||
return BuildCplexInterface(false, solver);
|
||||
case MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING:
|
||||
return BuildCplexInterface(true, solver);
|
||||
#endif
|
||||
case MPSolver::XPRESS_MIXED_INTEGER_PROGRAMMING:
|
||||
return BuildXpressInterface(true, solver);
|
||||
case MPSolver::XPRESS_LINEAR_PROGRAMMING:
|
||||
return BuildXpressInterface(false, solver);
|
||||
default:
|
||||
// TODO(user): Revert to the best *available* interface.
|
||||
LOG(FATAL) << "Linear solver not recognized.";
|
||||
}
|
||||
return nullptr;
|
||||
MPSolverInterface* interface =
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Create(solver);
|
||||
QCHECK(interface != nullptr)
|
||||
<< "Unsupported problem type: '" << solver->ProblemType()
|
||||
<< "'. Did you forget to link the library for this solver?";
|
||||
return interface;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -502,53 +417,21 @@ extern bool XpressIsCorrectlyInstalled();
|
||||
|
||||
// static
|
||||
bool MPSolver::SupportsProblemType(OptimizationProblemType problem_type) {
|
||||
#ifdef USE_BOP
|
||||
if (problem_type == BOP_INTEGER_PROGRAMMING) return true;
|
||||
#endif
|
||||
#ifdef USE_CBC
|
||||
if (problem_type == CBC_MIXED_INTEGER_PROGRAMMING) return true;
|
||||
#endif
|
||||
#ifdef USE_CLP
|
||||
if (problem_type == CLP_LINEAR_PROGRAMMING) return true;
|
||||
#endif
|
||||
#ifdef USE_GLOP
|
||||
if (problem_type == GLOP_LINEAR_PROGRAMMING) return true;
|
||||
#endif
|
||||
#ifdef USE_GLPK
|
||||
if (problem_type == GLPK_LINEAR_PROGRAMMING ||
|
||||
problem_type == GLPK_MIXED_INTEGER_PROGRAMMING) {
|
||||
return true;
|
||||
if (!MPSolverInterfaceFactoryRepository::GetInstance()->Supports(
|
||||
problem_type)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_HIGHS
|
||||
if (problem_type == HIGHS_MIXED_INTEGER_PROGRAMMING ||
|
||||
problem_type == HIGHS_LINEAR_PROGRAMMING) {
|
||||
return true;
|
||||
switch (problem_type) {
|
||||
case GUROBI_LINEAR_PROGRAMMING:
|
||||
case GUROBI_MIXED_INTEGER_PROGRAMMING:
|
||||
return GurobiIsCorrectlyInstalled();
|
||||
case XPRESS_LINEAR_PROGRAMMING:
|
||||
case XPRESS_MIXED_INTEGER_PROGRAMMING:
|
||||
return XpressIsCorrectlyInstalled();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_PDLP
|
||||
if (problem_type == PDLP_LINEAR_PROGRAMMING) return true;
|
||||
#endif
|
||||
if (problem_type == GUROBI_LINEAR_PROGRAMMING ||
|
||||
problem_type == GUROBI_MIXED_INTEGER_PROGRAMMING) {
|
||||
return GurobiIsCorrectlyInstalled();
|
||||
}
|
||||
if (problem_type == SAT_INTEGER_PROGRAMMING) return true;
|
||||
#ifdef USE_SCIP
|
||||
if (problem_type == SCIP_MIXED_INTEGER_PROGRAMMING) return true;
|
||||
#endif
|
||||
#ifdef USE_CPLEX
|
||||
if (problem_type == CPLEX_LINEAR_PROGRAMMING ||
|
||||
problem_type == CPLEX_MIXED_INTEGER_PROGRAMMING) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
if (problem_type == XPRESS_MIXED_INTEGER_PROGRAMMING ||
|
||||
problem_type == XPRESS_LINEAR_PROGRAMMING) {
|
||||
return XpressIsCorrectlyInstalled();
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(user): post c++ 14, instead use
|
||||
@@ -740,7 +623,7 @@ class MPVariableNamesIterator {
|
||||
int index_ = 0;
|
||||
};
|
||||
|
||||
// Iterates over all the constraint and general_constaint names. See usage.
|
||||
// Iterates over all the constraint and general_constraint names. See usage.
|
||||
class MPConstraintNamesIterator {
|
||||
public:
|
||||
explicit MPConstraintNamesIterator(const MPModelProto& model)
|
||||
@@ -2339,4 +2222,68 @@ std::string MPSolver::GetMPModelRequestLoggingInfo(
|
||||
return out;
|
||||
}
|
||||
|
||||
MPSolverInterfaceFactoryRepository*
|
||||
MPSolverInterfaceFactoryRepository::GetInstance() {
|
||||
static auto* const kInstance = new MPSolverInterfaceFactoryRepository();
|
||||
return kInstance;
|
||||
}
|
||||
|
||||
// This can't be covered by unit test coverage framework, because the Singleton
|
||||
// destruction occurs after it finished collecting coverage.
|
||||
// COV_NF_START
|
||||
MPSolverInterfaceFactoryRepository::~MPSolverInterfaceFactoryRepository() {
|
||||
absl::MutexLock lock(mutex_);
|
||||
map_.clear();
|
||||
}
|
||||
// COV_NF_END
|
||||
|
||||
void MPSolverInterfaceFactoryRepository::Register(
|
||||
MPSolverInterfaceFactory factory,
|
||||
MPSolver::OptimizationProblemType problem_type) {
|
||||
absl::MutexLock lock(mutex_);
|
||||
map_[problem_type] = std::move(factory);
|
||||
}
|
||||
|
||||
bool MPSolverInterfaceFactoryRepository::Unregister(
|
||||
MPSolver::OptimizationProblemType problem_type) {
|
||||
absl::MutexLock lock(mutex_);
|
||||
return map_.erase(problem_type) == 1;
|
||||
}
|
||||
|
||||
MPSolverInterface* MPSolverInterfaceFactoryRepository::Create(
|
||||
MPSolver* solver) const {
|
||||
absl::MutexLock lock(mutex_);
|
||||
const MPSolverInterfaceFactory factory =
|
||||
gtl::FindWithDefault(map_, solver->ProblemType(), nullptr);
|
||||
if (!factory) {
|
||||
return nullptr;
|
||||
}
|
||||
return factory(solver);
|
||||
}
|
||||
|
||||
bool MPSolverInterfaceFactoryRepository::Supports(
|
||||
MPSolver::OptimizationProblemType problem_type) const {
|
||||
return map_.count(problem_type) > 0;
|
||||
}
|
||||
|
||||
std::vector<MPSolver::OptimizationProblemType>
|
||||
MPSolverInterfaceFactoryRepository::ListAllRegisteredProblemTypes() const {
|
||||
std::vector<MPSolver::OptimizationProblemType> out;
|
||||
for (auto it = map_.begin(); it != map_.end(); ++it) {
|
||||
out.push_back(it->first);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string MPSolverInterfaceFactoryRepository // NOLINT
|
||||
::PrettyPrintAllRegisteredProblemTypes() const {
|
||||
std::string out;
|
||||
for (auto it = map_.begin(); it != map_.end(); ++it) {
|
||||
out += ProtoEnumToString<MPModelRequest::SolverType>(
|
||||
static_cast<MPModelRequest::SolverType>(it->first)) +
|
||||
"\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -157,7 +157,6 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "ortools/base/base_export.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/linear_solver/linear_expr.h"
|
||||
@@ -1231,23 +1230,23 @@ class MPVariable {
|
||||
void SetBranchingPriority(int priority);
|
||||
|
||||
protected:
|
||||
friend class MPSolver;
|
||||
friend class MPSolverInterface;
|
||||
friend class BopInterface;
|
||||
friend class CBCInterface;
|
||||
friend class CLPInterface;
|
||||
friend class GLPKInterface;
|
||||
friend class SCIPInterface;
|
||||
friend class SLMInterface;
|
||||
friend class GurobiInterface;
|
||||
friend class CplexInterface;
|
||||
friend class XpressInterface;
|
||||
friend class GLOPInterface;
|
||||
friend class MPVariableSolutionValueTest;
|
||||
friend class BopInterface;
|
||||
friend class SatInterface;
|
||||
friend class PdlpInterface;
|
||||
friend class GLPKInterface;
|
||||
friend class GurobiInterface;
|
||||
friend class HighsInterface;
|
||||
friend class KnapsackInterface;
|
||||
friend class MPSolver;
|
||||
friend class MPSolverInterface;
|
||||
friend class MPVariableSolutionValueTest;
|
||||
friend class PdlpInterface;
|
||||
friend class SatInterface;
|
||||
friend class SCIPInterface;
|
||||
friend class SLMInterface;
|
||||
friend class XpressInterface;
|
||||
|
||||
// Constructor. A variable points to a single MPSolverInterface that
|
||||
// is specified in the constructor. A variable cannot belong to
|
||||
@@ -1929,6 +1928,72 @@ class MPSolverInterface {
|
||||
virtual void SetLpAlgorithm(int value) = 0;
|
||||
};
|
||||
|
||||
// Handy type name for callbacks that create a fresh MPSolverInterface tied
|
||||
// to the given MPSolver. The underlying callback should *always* be permanent.
|
||||
typedef std::function<MPSolverInterface*(MPSolver*)> MPSolverInterfaceFactory;
|
||||
|
||||
// This class must be instantiated only once, through GetInstance(). It is
|
||||
// thread-safe.
|
||||
//
|
||||
// - To register an existing MPSolverInterface in the global repository:
|
||||
//
|
||||
// MPSolverInterfaceFactory cbc_solver_interface_factory =
|
||||
// CreateCBCInterface;
|
||||
// MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
// cbc_solver_interface_factory, CBC_MIXED_INTEGER_PROGRAMMING);
|
||||
//
|
||||
// - To get the MPSolverInterfaceFactory associated to a given problem type:
|
||||
//
|
||||
// MPSolverInterface* my_solver_interface =
|
||||
// MPSolverInterfaceFactoryRepository::GetInstance()->Create(
|
||||
// CBC_MIXED_INTEGER_PROGRAMMING);
|
||||
// CHECK(my_solver_interface != NULL) << "CBC not supported.";
|
||||
//
|
||||
// The implementations of MPSolverInterface defined here (e.g. ScipInterface)
|
||||
// are registered at with the MPSolverInterfaceFactoryRepository Singleton
|
||||
// automatically at link time, as long as the cc file where they are defined
|
||||
// (e.g. scip_interface.cc) is included in your binary (i.e. you have a
|
||||
// transitive dependency on the build rule ":linear_solver_scip", which sets
|
||||
// alwayslink=1).
|
||||
class MPSolverInterfaceFactoryRepository {
|
||||
public:
|
||||
static MPSolverInterfaceFactoryRepository* GetInstance();
|
||||
|
||||
// Maps the given factory to the given problem type. If a factory was already
|
||||
// assigned to this problem type, it will be replaced.
|
||||
void Register(MPSolverInterfaceFactory factory,
|
||||
MPSolver::OptimizationProblemType problem_type);
|
||||
|
||||
// Invokes the factory associated to the given solver's problem type,
|
||||
// or return NULL if no factory was found for it.
|
||||
MPSolverInterface* Create(MPSolver* solver) const;
|
||||
|
||||
// Whether the implementation associated to the given problem type is
|
||||
// available.
|
||||
bool Supports(MPSolver::OptimizationProblemType problem_type) const;
|
||||
|
||||
// List all the problem types.
|
||||
std::vector<MPSolver::OptimizationProblemType> ListAllRegisteredProblemTypes()
|
||||
const;
|
||||
|
||||
// Returns a human-readable list of supported OptimizationProblemType.
|
||||
std::string PrettyPrintAllRegisteredProblemTypes() const;
|
||||
|
||||
// FOR TESTING ONLY.
|
||||
bool Unregister(MPSolver::OptimizationProblemType problem_type);
|
||||
|
||||
private:
|
||||
// The constructor / destructor are private to prevent this class from ever
|
||||
// being instantiated outside GetInstance().
|
||||
// TODO(user): consider adding the GLOP factory by default, and then expose
|
||||
// it via a CreateDefault() method.
|
||||
MPSolverInterfaceFactoryRepository() = default;
|
||||
~MPSolverInterfaceFactoryRepository();
|
||||
|
||||
mutable absl::Mutex mutex_;
|
||||
std::map<MPSolver::OptimizationProblemType, MPSolverInterfaceFactory> map_;
|
||||
};
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
#endif // ORTOOLS_LINEAR_SOLVER_LINEAR_SOLVER_H_
|
||||
|
||||
@@ -11,11 +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>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -24,7 +21,6 @@
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
#include "ortools/linear_solver/linear_solver.pb.h"
|
||||
@@ -310,10 +306,16 @@ void PdlpInterface::NonIncrementalChange() {
|
||||
sync_status_ = MUST_RELOAD;
|
||||
}
|
||||
|
||||
// Register PDLP in the global linear solver factory.
|
||||
MPSolverInterface* BuildPdlpInterface(MPSolver* const solver) {
|
||||
return new PdlpInterface(solver);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterPdlp ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new PdlpInterface(solver); },
|
||||
MPSolver::PDLP_LINEAR_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_PDLP)
|
||||
|
||||
@@ -11,33 +11,54 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
file(GLOB _SRCS "*.h" "*.cc")
|
||||
if(NOT USE_COINOR)
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/clp_proto_solver.")
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/cbc_proto_solver.")
|
||||
list(APPEND _SRCS
|
||||
preprocessor.cc
|
||||
preprocessor.h
|
||||
proto_utils.h
|
||||
sat_proto_solver.cc
|
||||
sat_proto_solver.h
|
||||
sat_solver_utils.cc
|
||||
sat_solver_utils.h
|
||||
)
|
||||
|
||||
if(USE_GLOP)
|
||||
list(APPEND _SRCS
|
||||
glop_proto_solver.cc
|
||||
glop_proto_solver.h
|
||||
)
|
||||
endif()
|
||||
if(NOT USE_GLPK)
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/glpk_proto_solver.")
|
||||
if(USE_GUROBI)
|
||||
list(APPEND _SRCS
|
||||
gurobi_proto_solver.cc
|
||||
gurobi_proto_solver.h
|
||||
)
|
||||
endif()
|
||||
if(NOT USE_HIGHS)
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/highs_proto_solver.")
|
||||
if(USE_HIGHS)
|
||||
list(APPEND _SRCS
|
||||
highs_proto_solver.cc
|
||||
highs_proto_solver.h
|
||||
)
|
||||
endif()
|
||||
if(NOT USE_PDLP)
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/pdlp_proto_solver.")
|
||||
if(USE_PDLP)
|
||||
list(APPEND _SRCS
|
||||
pdlp_proto_solver.cc
|
||||
pdlp_proto_solver.h
|
||||
)
|
||||
endif()
|
||||
if(NOT USE_SCIP)
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/scip_proto_solver.")
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/scip_params.")
|
||||
if(USE_SCIP)
|
||||
list(APPEND _SRCS
|
||||
scip_params.cc
|
||||
scip_params.h
|
||||
scip_proto_solver.cc
|
||||
scip_proto_solver.h
|
||||
)
|
||||
endif()
|
||||
|
||||
set(NAME ${PROJECT_NAME}_linear_solver_proto_solver)
|
||||
|
||||
# Will be merge in libortools.so
|
||||
#add_library(${NAME} STATIC ${_SRCS})
|
||||
add_library(${NAME} OBJECT ${_SRCS})
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
set_target_properties(${NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(${NAME} PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>)
|
||||
@@ -50,4 +71,3 @@ target_link_libraries(${NAME} PRIVATE
|
||||
$<$<BOOL:${USE_SCIP}>:SCIP::libscip>
|
||||
$<$<BOOL:${USE_HIGHS}>:highs::highs>
|
||||
${PROJECT_NAMESPACE}::ortools_proto)
|
||||
#add_library(${PROJECT_NAMESPACE}::linear_solver_proto_solver ALIAS ${NAME})
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_SCIP)
|
||||
|
||||
#include "ortools/linear_solver/proto_solver/scip_proto_solver.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -1011,5 +1009,3 @@ absl::StatusOr<MPSolutionResponse> ScipSolveProto(
|
||||
}
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
#endif // #if defined(USE_SCIP)
|
||||
|
||||
@@ -13,14 +13,12 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
#include "ortools/linear_solver/linear_solver.pb.h"
|
||||
@@ -271,9 +269,16 @@ void SatInterface::NonIncrementalChange() {
|
||||
sync_status_ = MUST_RELOAD;
|
||||
}
|
||||
|
||||
// Register Sat in the global linear solver factory.
|
||||
MPSolverInterface* BuildSatInterface(MPSolver* const solver) {
|
||||
return new SatInterface(solver);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterSat ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new SatInterface(solver); },
|
||||
MPSolver::SAT_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_SCIP)
|
||||
|
||||
#include "ortools/linear_solver/scip_callback.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -22,9 +20,9 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
#include "ortools/linear_solver/scip_helper_macros.h"
|
||||
#include "scip/cons_linear.h"
|
||||
#include "scip/def.h"
|
||||
@@ -459,4 +457,3 @@ void AddCallbackConstraintImpl(SCIP* scip, const std::string& handler_name,
|
||||
|
||||
} // namespace internal
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_SCIP)
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if defined(USE_SCIP)
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -1165,12 +1163,19 @@ void SCIPInterface::SetCallback(MPCallback* mp_callback) {
|
||||
callback_ = mp_callback;
|
||||
}
|
||||
|
||||
MPSolverInterface* BuildSCIPInterface(MPSolver* const solver) {
|
||||
return new SCIPInterface(solver);
|
||||
}
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterSCIP ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new SCIPInterface(solver); },
|
||||
MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_SCIP)
|
||||
|
||||
#undef RETURN_AND_STORE_IF_SCIP_ERROR
|
||||
#undef RETURN_IF_ALREADY_IN_ERROR_STATE
|
||||
|
||||
@@ -15,11 +15,8 @@ file(GLOB _SRCS "*.h" "*.cc")
|
||||
set(NAME ${PROJECT_NAME}_linear_solver_wrappers)
|
||||
|
||||
# Will be merge in libortools.so
|
||||
#add_library(${NAME} STATIC ${_SRCS})
|
||||
add_library(${NAME} OBJECT ${_SRCS})
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
set_target_properties(${NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(${NAME} PRIVATE
|
||||
${PROJECT_SOURCE_DIR}
|
||||
${PROJECT_BINARY_DIR})
|
||||
@@ -27,4 +24,3 @@ target_link_libraries(${NAME} PRIVATE
|
||||
absl::status
|
||||
$<$<BOOL:${USE_SCIP}>:SCIP::libscip>
|
||||
${PROJECT_NAMESPACE}::ortools_proto)
|
||||
#add_library(${PROJECT_NAMESPACE}::linear_solver_wrappers ALIAS ${NAME})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019-2023 RTE
|
||||
// Copyright 2010-2025 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -2098,10 +2098,6 @@ void XpressInterface::Write(const std::string& filename) {
|
||||
LOG(ERROR) << "Xpress: Failed to write MPS!";
|
||||
}
|
||||
}
|
||||
|
||||
MPSolverInterface* BuildXpressInterface(bool mip, MPSolver* const solver) {
|
||||
return new XpressInterface(solver, mip);
|
||||
}
|
||||
// TODO useless ?
|
||||
template <class Container>
|
||||
void splitMyString(const std::string& str, Container& cont, char delim = ' ') {
|
||||
@@ -2287,4 +2283,24 @@ double XpressMPCallbackContext::SuggestSolution(
|
||||
return NAN;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterXpress ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new XpressInterface(solver, false); },
|
||||
MPSolver::XPRESS_LINEAR_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
// See MpSolverInterfaceFactoryRepository for details.
|
||||
const void* const kRegisterXpressMip ABSL_ATTRIBUTE_UNUSED = [] {
|
||||
MPSolverInterfaceFactoryRepository::GetInstance()->Register(
|
||||
[](MPSolver* const solver) { return new XpressInterface(solver, true); },
|
||||
MPSolver::XPRESS_MIXED_INTEGER_PROGRAMMING);
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -15,19 +15,36 @@ if(NOT USE_PDLP)
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(GLOB _SRCS "*.h" "*.cc")
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/[^/]*_test\\.cc$")
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/gtest[^/]*$")
|
||||
list(FILTER _SRCS EXCLUDE REGEX "/test[^/]*$")
|
||||
list(APPEND _SRCS
|
||||
iteration_stats.cc
|
||||
iteration_stats.h
|
||||
primal_dual_hybrid_gradient.cc
|
||||
primal_dual_hybrid_gradient.h
|
||||
quadratic_program_io.cc
|
||||
quadratic_program_io.h
|
||||
quadratic_program.cc
|
||||
quadratic_program.h
|
||||
scheduler.cc
|
||||
scheduler.h
|
||||
sharded_optimization_utils.cc
|
||||
sharded_optimization_utils.h
|
||||
sharded_quadratic_program.cc
|
||||
sharded_quadratic_program.h
|
||||
sharder.cc
|
||||
sharder.h
|
||||
solvers_proto_validation.cc
|
||||
solvers_proto_validation.h
|
||||
termination.cc
|
||||
termination.h
|
||||
trust_region.cc
|
||||
trust_region.h
|
||||
)
|
||||
|
||||
set(NAME ${PROJECT_NAME}_pdlp)
|
||||
|
||||
# Will be merge in libortools.so
|
||||
#add_library(${NAME} STATIC ${_SRCS})
|
||||
add_library(${NAME} OBJECT ${_SRCS})
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
set_target_properties(${NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(${NAME} PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>)
|
||||
@@ -37,4 +54,3 @@ target_link_libraries(${NAME} PRIVATE
|
||||
absl::str_format
|
||||
Eigen3::Eigen
|
||||
${PROJECT_NAMESPACE}::ortools_proto)
|
||||
#add_library(${PROJECT_NAMESPACE}::pdlp ALIAS ${NAME})
|
||||
|
||||
Reference in New Issue
Block a user