604 lines
17 KiB
Python
604 lines
17 KiB
Python
# 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
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# 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.
|
|
|
|
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
|
|
load("@protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
|
load("@protobuf//bazel:proto_library.bzl", "proto_library")
|
|
load("@protobuf//bazel:py_proto_library.bzl", "py_proto_library")
|
|
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
|
|
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
|
|
|
# For all the linear_solver_interface_tests rules.
|
|
|
|
package(default_visibility = ["//visibility:public"])
|
|
|
|
# OSS solvers
|
|
bool_flag(
|
|
name = "with_bop",
|
|
build_setting_default = True,
|
|
)
|
|
|
|
config_setting(
|
|
name = "use_bop",
|
|
flag_values = {":with_bop": "true"},
|
|
)
|
|
|
|
bool_flag(
|
|
name = "with_cbc",
|
|
build_setting_default = False,
|
|
)
|
|
|
|
config_setting(
|
|
name = "use_cbc",
|
|
flag_values = {":with_cbc": "true"},
|
|
)
|
|
|
|
bool_flag(
|
|
name = "with_clp",
|
|
build_setting_default = False,
|
|
)
|
|
|
|
config_setting(
|
|
name = "use_clp",
|
|
flag_values = {":with_clp": "true"},
|
|
)
|
|
|
|
bool_flag(
|
|
name = "with_cp_sat",
|
|
build_setting_default = True,
|
|
)
|
|
|
|
config_setting(
|
|
name = "use_cp_sat",
|
|
flag_values = {":with_cp_sat": "true"},
|
|
)
|
|
|
|
bool_flag(
|
|
name = "with_glop",
|
|
build_setting_default = True,
|
|
)
|
|
|
|
config_setting(
|
|
name = "use_glop",
|
|
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,
|
|
)
|
|
|
|
config_setting(
|
|
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 = 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",
|
|
srcs = ["linear_solver.proto"],
|
|
deps = ["//ortools/util:optional_boolean_proto"],
|
|
)
|
|
|
|
cc_proto_library(
|
|
name = "linear_solver_cc_proto",
|
|
deps = [":linear_solver_proto"],
|
|
)
|
|
|
|
py_proto_library(
|
|
name = "linear_solver_py_pb2",
|
|
deps = [":linear_solver_proto"],
|
|
)
|
|
|
|
# You can include the interfaces to different solvers by invoking '--define'
|
|
# flags. By default GLOP, BOP, SCIP, GUROBI, and CP-SAT interface are included.
|
|
#
|
|
# For instance, if you want to use the GLPK solver, build with
|
|
# '--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 = [
|
|
"sat_interface.cc",
|
|
] + select({
|
|
":use_cplex": ["cplex_interface.cc"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_xpress": ["xpress_interface.cc"],
|
|
"//conditions:default": [],
|
|
}),
|
|
deps = [
|
|
":linear_solver_base",
|
|
":linear_solver_cc_proto",
|
|
"//ortools/base",
|
|
"//ortools/linear_solver/proto_solver:proto_utils",
|
|
"//ortools/linear_solver/proto_solver:sat_proto_solver",
|
|
"//ortools/port:proto_utils",
|
|
"//ortools/sat:cp_model_cc_proto",
|
|
"//ortools/sat:cp_model_solver",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/status",
|
|
] + select({
|
|
":use_bop": [":linear_solver_bop"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_cbc": [":linear_solver_cbc"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_clp": [":linear_solver_clp"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_glop": [":linear_solver_glop"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_glpk": [":linear_solver_glpk"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_gurobi": [":linear_solver_gurobi"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_pdlp": [":linear_solver_pdlp"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_scip": [":linear_solver_scip"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_highs": [":linear_solver_highs"],
|
|
"//conditions:default": [],
|
|
}) + select({
|
|
":use_xpress": ["//ortools/third_party_solvers:xpress_environment"],
|
|
"//conditions:default": [],
|
|
}),
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
# Recommended target to do linear programming (LP).
|
|
cc_library(
|
|
name = "linear_solver_glop",
|
|
srcs = ["glop_interface.cc"],
|
|
deps = [
|
|
":glop_utils",
|
|
":linear_solver_base",
|
|
"//ortools/base",
|
|
"//ortools/glop:lp_solver",
|
|
"//ortools/glop:parameters_cc_proto",
|
|
"//ortools/linear_solver/proto_solver:glop_proto_solver",
|
|
"//ortools/lp_data",
|
|
"//ortools/lp_data:base",
|
|
"//ortools/port:proto_utils",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"//ortools/util:time_limit",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/log:check",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
# Most problems are solved faster by GLOP (and with better numerical accuracy
|
|
# and better behavior on ill-conditioned problems); but we still provide
|
|
# some free third-party solvers. CLP is usually the best among those.
|
|
# GUROBI is the best, even better than GLOP, but it has a restricted license.
|
|
cc_library(
|
|
name = "linear_solver_clp",
|
|
srcs = ["clp_interface.cc"],
|
|
target_compatible_with = select({
|
|
":use_clp": [],
|
|
"//conditions:default": ["@platforms//:incompatible"],
|
|
}),
|
|
deps = [
|
|
":linear_solver_base",
|
|
"//ortools/base",
|
|
"//ortools/base:timer",
|
|
"//third_party/cbc:clp",
|
|
"//third_party/cbc:coinutils",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
cc_library(
|
|
name = "scip_callback",
|
|
srcs = ["scip_callback.cc"],
|
|
hdrs = ["scip_callback.h"],
|
|
deps = [
|
|
":linear_solver_base",
|
|
":scip_helper_macros",
|
|
"//ortools/base",
|
|
"@abseil-cpp//absl/types:span",
|
|
"@scip",
|
|
],
|
|
)
|
|
|
|
# Recommended target for mixed integer programming.
|
|
#
|
|
# NOTE: You can change the default underlying LP engine (Soplex) to GLOP or CLP
|
|
# by setting a define when you build your end target:
|
|
# blaze build -c opt --define scip_lp_solver=glop my/build:target.
|
|
# blaze build -c opt --define scip_lp_solver=clp my/build:target.
|
|
cc_library(
|
|
name = "linear_solver_scip",
|
|
srcs = ["scip_interface.cc"],
|
|
deps = [
|
|
":linear_solver_base",
|
|
":linear_solver_cc_proto",
|
|
":scip_callback",
|
|
":scip_helper_macros",
|
|
"//ortools/base",
|
|
"//ortools/base:sysinfo",
|
|
"//ortools/base:timer",
|
|
"//ortools/linear_solver/proto_solver:proto_utils",
|
|
"//ortools/linear_solver/proto_solver:scip_params",
|
|
"//ortools/linear_solver/proto_solver:scip_proto_solver",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/cleanup",
|
|
"@abseil-cpp//absl/flags:flag",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
"@abseil-cpp//absl/synchronization",
|
|
"@abseil-cpp//absl/time",
|
|
"@scip",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
# Use with caution. For example, it is not thread-safe.
|
|
cc_library(
|
|
name = "linear_solver_glpk",
|
|
srcs = ["glpk_interface.cc"],
|
|
deps = [
|
|
":linear_solver_base",
|
|
"//ortools/base",
|
|
"//ortools/base:timer",
|
|
"//ortools/third_party_solvers/glpk:glpk_env_deleter",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
"@glpk",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
# Use with caution. For example, it has yielded erroneous solutions
|
|
# in the past (contact or-core-team@ for details).
|
|
cc_library(
|
|
name = "linear_solver_cbc",
|
|
srcs = ["cbc_interface.cc"],
|
|
target_compatible_with = select({
|
|
":use_cbc": [],
|
|
"//conditions:default": ["@platforms//:incompatible"],
|
|
}),
|
|
deps = [
|
|
":linear_solver_base",
|
|
"//ortools/base",
|
|
"//ortools/base:timer",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
cc_library(
|
|
name = "linear_solver_gurobi",
|
|
srcs = ["gurobi_interface.cc"],
|
|
deps = [
|
|
":gurobi_util",
|
|
":linear_solver_base",
|
|
"//ortools/base",
|
|
"//ortools/base:status_macros",
|
|
"//ortools/base:timer",
|
|
"//ortools/linear_solver/proto_solver:gurobi_proto_solver",
|
|
"//ortools/linear_solver/proto_solver:proto_utils",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"//ortools/util:time_limit",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/container:flat_hash_map",
|
|
"@abseil-cpp//absl/container:flat_hash_set",
|
|
"@abseil-cpp//absl/flags:flag",
|
|
"@abseil-cpp//absl/log:check",
|
|
"@abseil-cpp//absl/log:die_if_null",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
"@abseil-cpp//absl/synchronization",
|
|
"@abseil-cpp//absl/time",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
cc_library(
|
|
name = "gurobi_util",
|
|
srcs = ["gurobi_util.cc"],
|
|
hdrs = ["gurobi_util.h"],
|
|
deps = [
|
|
"//ortools/base:status_macros",
|
|
"//ortools/third_party_solvers:gurobi_environment",
|
|
"@abseil-cpp//absl/flags:flag",
|
|
"@abseil-cpp//absl/log",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/status:statusor",
|
|
"@abseil-cpp//absl/strings",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
],
|
|
)
|
|
|
|
# Experimental. Boolean optimization problem solver.
|
|
# This works best on MIP problem where all the variables are Boolean integers.
|
|
cc_library(
|
|
name = "linear_solver_bop",
|
|
srcs = ["bop_interface.cc"],
|
|
deps = [
|
|
":linear_solver_base",
|
|
"//ortools/base",
|
|
"//ortools/bop:bop_parameters_cc_proto",
|
|
"//ortools/bop:integral_solver",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
cc_library(
|
|
name = "linear_solver_pdlp",
|
|
srcs = ["pdlp_interface.cc"],
|
|
deps = [
|
|
":linear_solver_base",
|
|
":linear_solver_cc_proto",
|
|
"//ortools/base",
|
|
"//ortools/linear_solver/proto_solver:pdlp_proto_solver",
|
|
"//ortools/linear_solver/proto_solver:proto_utils",
|
|
"//ortools/pdlp:solve_log_cc_proto",
|
|
"//ortools/pdlp:solvers_cc_proto",
|
|
"//ortools/port:proto_utils",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/status:statusor",
|
|
"@abseil-cpp//absl/strings",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
# Highs solver;
|
|
cc_library(
|
|
name = "linear_solver_highs",
|
|
srcs = ["highs_interface.cc"],
|
|
deps = [
|
|
":linear_solver_base",
|
|
":linear_solver_cc_proto",
|
|
"//ortools/base",
|
|
"//ortools/linear_solver/proto_solver:highs_proto_solver",
|
|
"//ortools/linear_solver/proto_solver:proto_utils",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/log:check",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/status:statusor",
|
|
"@abseil-cpp//absl/strings",
|
|
],
|
|
alwayslink = 1, # Important! Library is used via dependency injection.
|
|
)
|
|
|
|
cc_library(
|
|
name = "linear_solver_base",
|
|
srcs = [
|
|
"linear_expr.cc",
|
|
"linear_solver.cc",
|
|
"linear_solver_callback.cc",
|
|
],
|
|
hdrs = [
|
|
"linear_expr.h",
|
|
"linear_solver.h",
|
|
"linear_solver_callback.h",
|
|
],
|
|
deps = [
|
|
":linear_solver_cc_proto",
|
|
":model_exporter",
|
|
":model_validator",
|
|
"//ortools/base",
|
|
"//ortools/base:accurate_sum",
|
|
"//ortools/base:base_export",
|
|
"//ortools/base:map_util",
|
|
"//ortools/base:numbers",
|
|
"//ortools/base:stl_util",
|
|
"//ortools/base:threadpool",
|
|
"//ortools/glop:parameters_cc_proto",
|
|
"//ortools/port:file", # Needed by go/lp-specific-params. Don't remove!
|
|
"//ortools/port:proto_utils",
|
|
"//ortools/util:fp_utils",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"//ortools/util:testing_utils",
|
|
"//ortools/util:time_limit",
|
|
"@abseil-cpp//absl/base:core_headers",
|
|
"@abseil-cpp//absl/container:flat_hash_map",
|
|
"@abseil-cpp//absl/container:flat_hash_set",
|
|
"@abseil-cpp//absl/flags:flag",
|
|
"@abseil-cpp//absl/log",
|
|
"@abseil-cpp//absl/log:check",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/status:statusor",
|
|
"@abseil-cpp//absl/strings",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
"@abseil-cpp//absl/synchronization",
|
|
"@abseil-cpp//absl/time",
|
|
"@protobuf",
|
|
],
|
|
)
|
|
|
|
cc_library(
|
|
name = "glop_utils",
|
|
srcs = ["glop_utils.cc"],
|
|
hdrs = ["glop_utils.h"],
|
|
deps = [
|
|
":linear_solver_base",
|
|
"//ortools/lp_data:base",
|
|
"@abseil-cpp//absl/log",
|
|
],
|
|
)
|
|
|
|
# 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:file",
|
|
"//ortools/base:status_macros",
|
|
"@abseil-cpp//absl/container:flat_hash_set",
|
|
"@abseil-cpp//absl/flags:flag",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/status:statusor",
|
|
"@abseil-cpp//absl/strings",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
"@abseil-cpp//absl/types:span",
|
|
],
|
|
)
|
|
|
|
cc_library(
|
|
name = "model_validator",
|
|
srcs = ["model_validator.cc"],
|
|
hdrs = ["model_validator.h"],
|
|
deps = [
|
|
":linear_solver_cc_proto",
|
|
"//ortools/base:accurate_sum",
|
|
"//ortools/base:map_util",
|
|
"//ortools/port:file",
|
|
"//ortools/port:proto_utils",
|
|
"//ortools/util:fp_utils",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"@abseil-cpp//absl/container:flat_hash_map",
|
|
"@abseil-cpp//absl/container:flat_hash_set",
|
|
"@abseil-cpp//absl/flags:flag",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/status:statusor",
|
|
"@abseil-cpp//absl/strings",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
"@abseil-cpp//absl/types:optional",
|
|
],
|
|
)
|
|
|
|
cc_binary(
|
|
name = "solve",
|
|
srcs = ["solve.cc"],
|
|
deps = [
|
|
":linear_solver",
|
|
":linear_solver_cc_proto",
|
|
":model_exporter",
|
|
"//ortools/base",
|
|
"//ortools/base:file",
|
|
"//ortools/base:recordio",
|
|
"//ortools/lp_data:lp_parser",
|
|
"//ortools/lp_data:mps_reader",
|
|
"//ortools/lp_data:sol_reader",
|
|
"//ortools/sat:cp_model_cc_proto",
|
|
"//ortools/sat:cp_model_solver",
|
|
"//ortools/util:file_util",
|
|
"//ortools/util:sigint",
|
|
"@abseil-cpp//absl/flags:flag",
|
|
"@abseil-cpp//absl/log:flags",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/status:statusor",
|
|
"@abseil-cpp//absl/strings",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
"@abseil-cpp//absl/time",
|
|
],
|
|
)
|
|
|
|
# Benchmarks.
|
|
|
|
cc_library(
|
|
name = "scip_helper_macros",
|
|
hdrs = ["scip_helper_macros.h"],
|
|
deps = [
|
|
"//ortools/base:status_macros",
|
|
"@abseil-cpp//absl/status",
|
|
"@abseil-cpp//absl/strings:str_format",
|
|
],
|
|
)
|
|
|
|
cc_library(
|
|
name = "solve_mp_model",
|
|
srcs = ["solve_mp_model.cc"],
|
|
hdrs = ["solve_mp_model.h"],
|
|
deps = [
|
|
":linear_solver",
|
|
":linear_solver_cc_proto",
|
|
"//ortools/util:lazy_mutable_copy",
|
|
"//ortools/util:solve_interrupter",
|
|
"@abseil-cpp//absl/base:nullability",
|
|
],
|
|
)
|