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