linear_solver: backport from main

This commit is contained in:
Corentin Le Molgat
2025-11-05 12:03:57 +01:00
parent 809c2540a1
commit 2ff69ef797
5 changed files with 137 additions and 98 deletions

View File

@@ -18,6 +18,8 @@ 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
@@ -28,9 +30,7 @@ bool_flag(
config_setting(
name = "use_bop",
flag_values = {
":with_bop": "true",
},
flag_values = {":with_bop": "true"},
)
bool_flag(
@@ -40,9 +40,7 @@ bool_flag(
config_setting(
name = "use_cbc",
flag_values = {
":with_cbc": "true",
},
flag_values = {":with_cbc": "true"},
)
bool_flag(
@@ -52,9 +50,7 @@ bool_flag(
config_setting(
name = "use_clp",
flag_values = {
":with_clp": "true",
},
flag_values = {":with_clp": "true"},
)
bool_flag(
@@ -64,9 +60,7 @@ bool_flag(
config_setting(
name = "use_cp_sat",
flag_values = {
":with_cp_sat": "true",
},
flag_values = {":with_cp_sat": "true"},
)
bool_flag(
@@ -76,9 +70,7 @@ bool_flag(
config_setting(
name = "use_glop",
flag_values = {
":with_glop": "true",
},
flag_values = {":with_glop": "true"},
)
bool_flag(
@@ -88,9 +80,7 @@ bool_flag(
config_setting(
name = "use_glpk",
flag_values = {
":with_glpk": "true",
},
flag_values = {":with_glpk": "true"},
)
bool_flag(
@@ -100,9 +90,7 @@ bool_flag(
config_setting(
name = "use_highs",
flag_values = {
":with_highs": "true",
},
flag_values = {":with_highs": "true"},
)
bool_flag(
@@ -112,9 +100,7 @@ bool_flag(
config_setting(
name = "use_pdlp",
flag_values = {
":with_pdlp": "true",
},
flag_values = {":with_pdlp": "true"},
)
bool_flag(
@@ -124,9 +110,7 @@ bool_flag(
config_setting(
name = "use_scip",
flag_values = {
":with_scip": "true",
},
flag_values = {":with_scip": "true"},
)
# Prorietary solvers
@@ -137,11 +121,10 @@ bool_flag(
config_setting(
name = "use_cplex",
flag_values = {
":with_cplex": "true",
},
flag_values = {":with_cplex": "true"},
)
# Linear solver proto, used for (efficient!) model storage.
proto_library(
name = "linear_solver_proto",
srcs = ["linear_solver.proto"],
@@ -155,7 +138,6 @@ cc_proto_library(
py_proto_library(
name = "linear_solver_py_pb2",
visibility = ["//visibility:public"],
deps = [":linear_solver_proto"],
)
@@ -323,30 +305,6 @@ cc_library(
}),
)
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",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/container:flat_hash_set",
"@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_library(
name = "gurobi_util",
srcs = ["gurobi_util.cc"],
@@ -363,6 +321,78 @@ cc_library(
],
)
# 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"],
@@ -373,54 +403,14 @@ cc_library(
],
)
# 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:hash",
"//ortools/base:map_util",
"//ortools/base:status_macros",
"//ortools/util:fp_utils",
"@abseil-cpp//absl/container:flat_hash_set",
"@abseil-cpp//absl/status",
"@abseil-cpp//absl/status:statusor",
"@abseil-cpp//absl/strings",
"@abseil-cpp//absl/strings:str_format",
],
)
cc_binary(
name = "solve",
srcs = ["solve.cc"],
deps = [
":linear_solver",
":linear_solver_cc_proto",
"//ortools/base",
"//ortools/base:file",
"//ortools/lp_data:lp_parser",
"//ortools/lp_data:mps_reader",
"//ortools/lp_data:sol_reader",
"@abseil-cpp//absl/flags:flag",
"@abseil-cpp//absl/log:flags",
"@abseil-cpp//absl/status",
"@abseil-cpp//absl/status:statusor",
"@abseil-cpp//absl/time",
],
)
cc_library(
name = "solve_mp_model",
srcs = ["solve_mp_model.cc"],
hdrs = ["solve_mp_model.h"],
visibility = ["//visibility:public"],
deps = [
":linear_solver",
":linear_solver_cc_proto",
"//ortools/util:lazy_mutable_copy",
"//ortools/util:solve_interrupter",
],
)

View File

@@ -166,9 +166,11 @@
#include "ortools/port/proto_utils.h"
#include "ortools/util/lazy_mutable_copy.h"
#ifndef SWIG
OR_DLL ABSL_DECLARE_FLAG(bool, linear_solver_enable_verbose_output);
OR_DLL ABSL_DECLARE_FLAG(bool, log_verification_errors);
OR_DLL ABSL_DECLARE_FLAG(bool, verify_solution);
#endif
namespace operations_research {
@@ -1470,7 +1472,11 @@ class MPConstraint {
* instead. We need to figure out how to deal with the subtleties of
* the default values.
*/
class OR_DLL MPSolverParameters {
class
#ifndef SWIG
OR_DLL
#endif
MPSolverParameters {
public:
/// Enumeration of parameters that take continuous values.
enum DoubleParam {

View File

@@ -513,7 +513,6 @@ PYBIND11_MODULE(model_builder_helper, m) {
"__isub__",
[](std::shared_ptr<SumArray> expr,
std::shared_ptr<LinearExpr> other) -> std::shared_ptr<LinearExpr> {
expr->AddInPlace(other->Neg());
return expr->AddInPlace(other->Neg());
},
py::arg("other").none(false), "Returns `self` - `other`.")

View File

@@ -372,6 +372,27 @@ ENDATA
s += model.new_bool_var("")
model.add(s == 10)
def test_complex_iadd(self):
model = mb.Model()
delta_down_0 = model.new_var(
name="delta_down_0", lb=0, ub=float("inf"), is_integer=False
)
ac_flow_0_10 = model.new_var(
name="ac_flow_0_10", lb=0, ub=float("inf"), is_integer=False
)
ac_flow_0_11 = model.new_var(
name="ac_flow_0_11", lb=0, ub=float("inf"), is_integer=False
)
expr1 = -0.333333 * delta_down_0
expr1 += ac_flow_0_10
expr1 += ac_flow_0_11
expr2 = -0.333333 * delta_down_0
expr2 = expr2 + ac_flow_0_10
expr2 = expr2 + ac_flow_0_11
self.assertEqual(str(mbh.FlatExpr(expr1)), str(mbh.FlatExpr(expr2)))
def test_large_isub(self):
model = mb.Model()
s = 0
@@ -379,6 +400,27 @@ ENDATA
s -= model.new_bool_var("")
model.add(s == 10)
def test_complex_sub(self):
model = mb.Model()
delta_down_0 = model.new_var(
name="delta_down_0", lb=0, ub=float("inf"), is_integer=False
)
ac_flow_0_10 = model.new_var(
name="ac_flow_0_10", lb=0, ub=float("inf"), is_integer=False
)
ac_flow_0_11 = model.new_var(
name="ac_flow_0_11", lb=0, ub=float("inf"), is_integer=False
)
expr1 = -0.333333 * delta_down_0
expr1 -= ac_flow_0_10
expr1 -= ac_flow_0_11
expr2 = -0.333333 * delta_down_0
expr2 = expr2 - ac_flow_0_10
expr2 = expr2 - ac_flow_0_11
self.assertEqual(str(mbh.FlatExpr(expr1)), str(mbh.FlatExpr(expr2)))
def test_variables(self):
model = mb.Model()
x = model.new_int_var(0.0, 4.0, "x")

View File

@@ -17,6 +17,8 @@ load("@rules_java//java:java_binary.bzl", "java_binary")
load("@rules_python//python:py_test.bzl", "py_test")
load("//bazel:run_binary_test.bzl", "run_binary_test")
package(default_visibility = ["//visibility:public"])
# Linear Solver
cc_test(