bazel: rework config_setting in linear_solver (#3812)

This commit is contained in:
Corentin Le Molgat
2023-06-05 18:26:23 +02:00
parent 6299064f79
commit 06754051f2
2 changed files with 321 additions and 199 deletions

View File

@@ -14,52 +14,108 @@
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_proto_library")
load("@rules_proto//proto:defs.bzl", "proto_library")
load("@rules_python//python:proto.bzl", "py_proto_library")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
package(default_visibility = ["//visibility:public"])
exports_files(["model_exporter_swig_helper.h"])
# OSS solvers
bool_flag(name = "with_bop", build_setting_default = True)
config_setting(
name = "with_glpk",
values = {"define": "USE_GLPK="},
name = "use_bop",
flag_values = {
":with_bop": "true",
},
)
bool_flag(name = "with_cbc", build_setting_default = False)
config_setting(
name = "with_cplex",
values = {"define": "USE_CPLEX="},
name = "use_cbc",
flag_values = {
":with_cbc": "true",
},
)
bool_flag(name = "with_clp", build_setting_default = False)
config_setting(
name = "with_xpress",
values = {"define": "USE_XPRESS="},
name = "use_clp",
flag_values = {
":with_clp": "true",
},
)
bool_flag(name = "with_glop", build_setting_default = True)
config_setting(
name = "with_cbc",
values = {"define": "USE_CBC="},
name = "use_glop",
flag_values = {
":with_glop": "true",
},
)
bool_flag(name = "with_glpk", build_setting_default = False)
config_setting(
name = "with_clp",
values = {"define": "USE_CLP="},
name = "use_glpk",
flag_values = {
":with_glpk": "true",
},
)
bool_flag(name = "with_highs", build_setting_default = True)
config_setting(
name = "use_highs",
flag_values = {
":with_highs": "true",
},
)
bool_flag(name = "with_pdlp", build_setting_default = True)
config_setting(
name = "use_pdlp",
flag_values = {
":with_pdlp": "true",
},
)
bool_flag(name = "with_scip", build_setting_default = True)
config_setting(
name = "use_scip",
flag_values = {
":with_scip": "true",
},
)
# Prorietary solvers
bool_flag(name = "with_cplex", build_setting_default = False)
config_setting(
name = "use_cplex",
flag_values = {
":with_cplex": "true",
},
)
bool_flag(name = "with_xpress", build_setting_default = False)
config_setting(
name = "use_xpress",
values = {"define": "USE_XPRESS="},
)
proto_library(
name = "linear_solver_proto",
srcs = ["linear_solver.proto"],
deps = ["//ortools/util:optional_boolean_proto"],
name = "linear_solver_proto",
srcs = ["linear_solver.proto"],
deps = ["//ortools/util:optional_boolean_proto"],
)
cc_proto_library(
name = "linear_solver_cc_proto",
deps = [":linear_solver_proto"],
name = "linear_solver_cc_proto",
deps = [":linear_solver_proto"],
)
py_proto_library(
name = "linear_solver_py_pb2",
visibility = ["//visibility:public"],
deps = [":linear_solver_proto"],
name = "linear_solver_py_pb2",
visibility = ["//visibility:public"],
deps = [":linear_solver_proto"],
)
# You can include the interfaces to different solvers by invoking '--define'
@@ -69,180 +125,228 @@ py_proto_library(
# '--define USE_GLPK=' (or add it to your bazel.rc file). This will download,
# build and link to GLPK.
cc_library(
name = "linear_solver",
srcs = [
"bop_interface.cc",
"glop_interface.cc",
"glop_utils.cc",
"gurobi_interface.cc",
"highs_interface.cc",
"linear_expr.cc",
"linear_solver.cc",
"linear_solver_callback.cc",
"lpi_glop.cpp",
"pdlp_interface.cc",
"sat_interface.cc",
"scip_callback.cc",
"scip_interface.cc",
] + select({
":with_cbc": ["cbc_interface.cc"],
"//conditions:default": [],
}) + select({
":with_clp": ["clp_interface.cc"],
"//conditions:default": [],
}) + select({
":with_cplex": ["cplex_interface.cc"],
"//conditions:default": [],
}) + select({
":with_xpress": ["xpress_interface.cc"],
"//conditions:default": [],
}) + select({
":with_glpk": ["glpk_interface.cc"],
"//conditions:default": [],
}),
hdrs = [
"glop_interface.cc",
"glop_utils.h",
"linear_expr.h",
"linear_solver.h",
"linear_solver_callback.h",
"scip_callback.h",
"scip_helper_macros.h",
name = "linear_solver",
srcs = [
"gurobi_interface.cc",
"linear_expr.cc",
"linear_solver.cc",
"linear_solver_callback.cc",
"lpi_glop.cpp",
"sat_interface.cc",
] + select({
":use_bop": ["bop_interface.cc"],
"//conditions:default": [],
}) + select({
":use_cbc": ["cbc_interface.cc"],
"//conditions:default": [],
}) + select({
":use_clp": ["clp_interface.cc"],
"//conditions:default": [],
}) + select({
":use_glop": ["glop_interface.cc", "glop_utils.cc"],
"//conditions:default": [],
}) + select({
":use_glpk": ["glpk_interface.cc"],
"//conditions:default": [],
}) + select({
":use_highs": ["highs_interface.cc"],
"//conditions:default": [],
}) + select({
":use_pdlp": ["pdlp_interface.cc"],
"//conditions:default": [],
}) + select({
":use_scip": ["scip_interface.cc", "scip_callback.cc"],
"//conditions:default": [],
}) + select({
":use_cplex": ["cplex_interface.cc"],
"//conditions:default": [],
}) + select({
":use_xpress": ["xpress_interface.cc"],
"//conditions:default": [],
}),
hdrs = [
"linear_expr.h",
"linear_solver.h",
"linear_solver_callback.h",
"scip_callback.h",
"scip_helper_macros.h",
] + select({
":use_glop": ["glop_utils.h"],
"//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": [],
}) + select({
":use_xpress": ["-DUSE_XPRESS"],
"//conditions:default": [],
}),
deps = [
":linear_solver_cc_proto",
":model_exporter",
":model_validator",
"//ortools/base",
"//ortools/base:accurate_sum",
"//ortools/base:dynamic_library",
"//ortools/base:hash",
"//ortools/base:map_util",
"//ortools/base:status_macros",
"//ortools/base:stl_util",
"//ortools/base:timer",
"//ortools/gurobi:environment",
"//ortools/linear_solver/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/util:fp_utils",
"//ortools/util:lazy_mutable_copy",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/types:optional",
] + select({
":use_bop": [
"//ortools/bop:bop_parameters_cc_proto",
"//ortools/bop:integral_solver",
],
copts = [
"-DUSE_PDLP",
"-DUSE_SCIP",
"-DUSE_HIGHS",
] + select({
":with_glpk": ["-DUSE_GLPK"],
"//conditions:default": [],
}),
deps = [
":linear_solver_cc_proto",
":model_exporter",
":model_validator",
":scip_with_glop",
"//ortools/base",
"//ortools/base:accurate_sum",
"//ortools/base:dynamic_library",
"//ortools/base:hash",
"//ortools/base:map_util",
"//ortools/base:status_macros",
"//ortools/base:stl_util",
"//ortools/base:timer",
"//ortools/bop:bop_parameters_cc_proto",
"//ortools/bop:integral_solver",
"//ortools/glop:lp_solver",
"//ortools/glop:parameters_cc_proto",
"//ortools/gscip:legacy_scip_params",
"//ortools/gurobi:environment",
"//ortools/linear_solver/proto_solver",
"//ortools/pdlp:primal_dual_hybrid_gradient",
"//ortools/pdlp:solve_log_cc_proto",
"//ortools/pdlp:solvers_cc_proto",
"//ortools/port:file",
"//ortools/port:proto_utils",
"//ortools/sat:cp_model_cc_proto",
"//ortools/sat:cp_model_solver",
"//ortools/sat:lp_utils",
"//ortools/util:fp_utils",
"//ortools/util:lazy_mutable_copy",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/types:optional",
] + select({
":with_glpk": [
"//ortools/glpk:glpk_env_deleter",
"@glpk",
],
"//conditions:default": [],
}),
"//conditions:default": [],
}) + select({
":use_glop": [
"//ortools/glop:lp_solver",
"//ortools/glop:parameters_cc_proto",
],
"//conditions:default": [],
}) + select({
":use_glpk": [
"//ortools/glpk:glpk_env_deleter",
"@glpk",
],
"//conditions:default": [],
}) + select({
":use_pdlp": [
"//ortools/pdlp:primal_dual_hybrid_gradient",
"//ortools/pdlp:solve_log_cc_proto",
"//ortools/pdlp:solvers_cc_proto",
],
"//conditions:default": [],
}) + select({
":use_scip": [
":scip_with_glop",
"//ortools/gscip:legacy_scip_params",
],
"//conditions:default": [],
}),
)
cc_library(
name = "model_validator",
srcs = ["model_validator.cc"],
hdrs = ["model_validator.h"],
visibility = ["//visibility:public"],
deps = [
":linear_solver_cc_proto",
"//ortools/base",
"//ortools/base:accurate_sum",
"//ortools/base:map_util",
"//ortools/port:file",
"//ortools/port:proto_utils",
"//ortools/util:fp_utils",
"//ortools/util:lazy_mutable_copy",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/types:optional",
],
name = "model_validator",
srcs = ["model_validator.cc"],
hdrs = ["model_validator.h"],
visibility = ["//visibility:public"],
deps = [
":linear_solver_cc_proto",
"//ortools/base",
"//ortools/base:accurate_sum",
"//ortools/base:map_util",
"//ortools/port:file",
"//ortools/port:proto_utils",
"//ortools/util:fp_utils",
"//ortools/util:lazy_mutable_copy",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/types:optional",
],
)
copy_file(
name = "lpi_glop",
src = "@scip//:src/lpi/lpi_glop.cpp",
out = "lpi_glop.cpp",
name = "lpi_glop",
src = "@scip//:src/lpi/lpi_glop.cpp",
out = "lpi_glop.cpp",
)
cc_library(
name = "scip_with_glop",
srcs = ["lpi_glop.cpp"],
deps = [
"//ortools/glop:lp_solver",
"@scip//:libscip",
],
name = "scip_with_glop",
srcs = ["lpi_glop.cpp"],
deps = [
"//ortools/glop:lp_solver",
"@scip//:libscip",
],
)
cc_library(
name = "scip_helper_macros",
hdrs = ["scip_helper_macros.h"],
deps = [
"//ortools/base:status_macros",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings:str_format",
],
name = "scip_helper_macros",
hdrs = ["scip_helper_macros.h"],
deps = [
"//ortools/base:status_macros",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings:str_format",
],
)
# Model exporter that can write MPS and LP file formats from an MPModelProto.
cc_library(
name = "model_exporter",
srcs = ["model_exporter.cc"],
hdrs = ["model_exporter.h"],
deps = [
":linear_solver_cc_proto",
"//ortools/base",
"//ortools/base:hash",
"//ortools/base:map_util",
"//ortools/util:fp_utils",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
],
name = "model_exporter",
srcs = ["model_exporter.cc"],
hdrs = ["model_exporter.h"],
deps = [
":linear_solver_cc_proto",
"//ortools/base",
"//ortools/base:hash",
"//ortools/base:map_util",
"//ortools/util:fp_utils",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
],
)
cc_binary(
name = "solve",
srcs = ["solve.cc"],
defines = ["USE_LP_PARSER"],
deps = [
":linear_solver",
":linear_solver_cc_proto",
"//ortools/base",
"//ortools/lp_data:lp_parser",
"//ortools/lp_data:model_reader",
"//ortools/lp_data:mps_reader",
"//ortools/lp_data:sol_reader",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/time",
],
name = "solve",
srcs = ["solve.cc"],
defines = ["USE_LP_PARSER"],
deps = [
":linear_solver",
":linear_solver_cc_proto",
"//ortools/base",
"//ortools/lp_data:lp_parser",
"//ortools/lp_data:model_reader",
"//ortools/lp_data:mps_reader",
"//ortools/lp_data:sol_reader",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/time",
],
)

View File

@@ -364,21 +364,27 @@ bool MPSolver::SetSolverSpecificParametersAsString(
// ----- Solver -----
#if defined(USE_CLP) || defined(USE_CBC)
extern MPSolverInterface* BuildCLPInterface(MPSolver* const 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
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);
@@ -397,22 +403,22 @@ namespace {
MPSolverInterface* BuildSolverInterface(MPSolver* const solver) {
DCHECK(solver != nullptr);
switch (solver->ProblemType()) {
#if defined(USE_BOP)
case MPSolver::BOP_INTEGER_PROGRAMMING:
return BuildBopInterface(solver);
case MPSolver::GLOP_LINEAR_PROGRAMMING:
return BuildGLOPInterface(solver);
case MPSolver::PDLP_LINEAR_PROGRAMMING:
return BuildPdlpInterface(solver);
case MPSolver::SAT_INTEGER_PROGRAMMING:
return BuildSatInterface(solver);
#if defined(USE_CLP) || defined(USE_CBC)
case MPSolver::CLP_LINEAR_PROGRAMMING:
return BuildCLPInterface(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);
@@ -425,6 +431,12 @@ MPSolverInterface* BuildSolverInterface(MPSolver* const 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);
@@ -483,9 +495,18 @@ extern bool GurobiIsCorrectlyInstalled();
// 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) {
@@ -498,32 +519,29 @@ bool MPSolver::SupportsProblemType(OptimizationProblemType problem_type) {
return true;
}
#endif
if (problem_type == BOP_INTEGER_PROGRAMMING) return true;
if (problem_type == SAT_INTEGER_PROGRAMMING) return true;
if (problem_type == GLOP_LINEAR_PROGRAMMING) return true;
#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_CBC
if (problem_type == CBC_MIXED_INTEGER_PROGRAMMING) return true;
#endif
#ifdef USE_XPRESS
if (problem_type == XPRESS_MIXED_INTEGER_PROGRAMMING ||
problem_type == XPRESS_LINEAR_PROGRAMMING) {
return true;
}
#endif
#ifdef USE_CPLEX
if (problem_type == CPLEX_LINEAR_PROGRAMMING ||
problem_type == CPLEX_MIXED_INTEGER_PROGRAMMING) {
return true;
}
#endif
#ifdef USE_XPRESS
if (problem_type == XPRESS_MIXED_INTEGER_PROGRAMMING ||
problem_type == XPRESS_LINEAR_PROGRAMMING) {
return true;
}
#endif
return false;
}