Files
ortools-clone/ortools/linear_solver/BUILD.bazel
2026-01-07 15:50:08 +01:00

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",
],
)