Propagate nullability (#4959)

This commit is contained in:
Guillaume Chatelet
2025-12-18 22:38:22 +01:00
committed by Corentin Le Molgat
parent 5a867fd457
commit 40ff9caa88
30 changed files with 153 additions and 196 deletions

View File

@@ -210,6 +210,7 @@ cc_library(
"//ortools/math_opt:result_cc_proto",
"//ortools/util:solve_interrupter",
"@abseil-cpp//absl/base:core_headers",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/log",
"@abseil-cpp//absl/log:check",
"@abseil-cpp//absl/log:die_if_null",
@@ -455,6 +456,7 @@ cc_library(
"//ortools/math_opt:parameters_cc_proto",
"//ortools/math_opt:result_cc_proto",
"//ortools/util:solve_interrupter",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/status:statusor",
"@abseil-cpp//absl/strings",
"@abseil-cpp//absl/strings:string_view",

View File

@@ -19,6 +19,7 @@
#include <string>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/status/statusor.h"
#include "ortools/math_opt/callback.pb.h"
#include "ortools/math_opt/infeasible_subsystem.pb.h"
@@ -78,7 +79,7 @@ class BaseSolver {
// An optional interrupter that the solver can use to interrupt the solve
// early.
const SolveInterrupter* interrupter = nullptr;
const SolveInterrupter* absl_nullable interrupter = nullptr;
friend std::ostream& operator<<(std::ostream& out, const SolveArgs& args);
};
@@ -96,7 +97,7 @@ class BaseSolver {
// An optional interrupter that the solver can use to interrupt the solve
// early.
const SolveInterrupter* interrupter = nullptr;
const SolveInterrupter* absl_nullable interrupter = nullptr;
friend std::ostream& operator<<(std::ostream& out,
const ComputeInfeasibleSubsystemArgs& args);

View File

@@ -146,7 +146,7 @@ class SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* interrupter) = 0;
const SolveInterrupter* absl_nullable interrupter) = 0;
// Updates the model to solve and returns true, or returns false if this
// update is not supported.
@@ -173,9 +173,9 @@ class SolverInterface {
// When parameter `message_cb` is not null and the underlying solver does not
// supports message callbacks, it should ignore it.
virtual absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
MessageCallback message_cb,
const SolveInterrupter* interrupter) = 0;
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter) = 0;
};
class AllSolversRegistry {

View File

@@ -71,6 +71,8 @@
#include <memory>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/base/thread_annotations.h"
#include "absl/log/die_if_null.h"
#include "absl/status/statusor.h"
@@ -98,7 +100,7 @@ class SolverInterfaceMock : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration,
Callback cb, const SolveInterrupter* interrupter),
Callback cb, const SolveInterrupter* absl_nullable interrupter),
(override));
MOCK_METHOD(absl::StatusOr<bool>, Update,
@@ -107,7 +109,8 @@ class SolverInterfaceMock : public SolverInterface {
MOCK_METHOD(absl::StatusOr<ComputeInfeasibleSubsystemResultProto>,
ComputeInfeasibleSubsystem,
(const SolveParametersProto& parameters,
MessageCallback message_cb, const SolveInterrupter* interrupter),
MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter),
(override));
};
@@ -136,7 +139,7 @@ class DelegatingSolver : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* const interrupter) override {
const SolveInterrupter* absl_nullable const interrupter) override {
return solver_->Solve(parameters, model_parameters, std::move(message_cb),
callback_registration, std::move(cb), interrupter);
};
@@ -148,7 +151,7 @@ class DelegatingSolver : public SolverInterface {
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* const interrupter) override {
const SolveInterrupter* absl_nullable const interrupter) override {
return solver_->ComputeInfeasibleSubsystem(
parameters, std::move(message_cb), interrupter);
}

View File

@@ -517,6 +517,7 @@ cc_library(
"//ortools/math_opt:model_cc_proto",
"//ortools/math_opt:model_update_cc_proto",
"//ortools/math_opt/storage:model_storage",
"@abseil-cpp//absl/log:die_if_null",
"@abseil-cpp//absl/status",
"@abseil-cpp//absl/status:statusor",
"@abseil-cpp//absl/strings",
@@ -531,6 +532,7 @@ cc_library(
"//ortools/base:logging",
"//ortools/base:source_location",
"@abseil-cpp//absl/base:core_headers",
"@abseil-cpp//absl/log:die_if_null",
"@abseil-cpp//absl/strings",
"@abseil-cpp//absl/synchronization",
"@abseil-cpp//absl/types:span",
@@ -559,6 +561,7 @@ cc_library(
"//ortools/base:status_macros",
"//ortools/math_opt/storage:model_storage",
"//ortools/util:solve_interrupter",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/container:flat_hash_set",
"@abseil-cpp//absl/status",
],

View File

@@ -14,6 +14,7 @@
#ifndef ORTOOLS_MATH_OPT_CPP_COMPUTE_INFEASIBLE_SUBSYSTEM_ARGUMENTS_H_
#define ORTOOLS_MATH_OPT_CPP_COMPUTE_INFEASIBLE_SUBSYSTEM_ARGUMENTS_H_
#include "absl/base/nullability.h"
#include "ortools/math_opt/cpp/message_callback.h" // IWYU pragma: export
#include "ortools/math_opt/cpp/parameters.h" // IWYU pragma: export
#include "ortools/util/solve_interrupter.h" // IWYU pragma: export
@@ -59,7 +60,7 @@ struct ComputeInfeasibleSubsystemArguments {
// ComputeInfeasibleSubsystem(model, SolverType::kGurobi,
// { .interrupter = interrupter.get() });
//
const SolveInterrupter* interrupter = nullptr;
const SolveInterrupter* absl_nullable interrupter = nullptr;
};
} // namespace operations_research::math_opt

View File

@@ -20,6 +20,7 @@
#include <vector>
#include "absl/base/thread_annotations.h"
#include "absl/log/die_if_null.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/types/span.h"

View File

@@ -24,17 +24,12 @@
namespace operations_research::math_opt {
absl::Status SolveArguments::CheckModelStorageAndCallback(
absl::Status SolveArguments::CheckModelStorage(
const ModelStorageCPtr expected_storage) const {
RETURN_IF_ERROR(model_parameters.CheckModelStorage(expected_storage))
<< "invalid model_parameters";
RETURN_IF_ERROR(callback_registration.CheckModelStorage(expected_storage))
<< "invalid callback_registration";
if (callback == nullptr && !callback_registration.events.empty()) {
return absl::InvalidArgumentError(
"no callback was provided to run, but callback events were registered");
}
return absl::OkStatus();
}

View File

@@ -17,6 +17,7 @@
#ifndef ORTOOLS_MATH_OPT_CPP_SOLVE_ARGUMENTS_H_
#define ORTOOLS_MATH_OPT_CPP_SOLVE_ARGUMENTS_H_
#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "ortools/math_opt/cpp/callback.h" // IWYU pragma: export
#include "ortools/math_opt/cpp/message_callback.h" // IWYU pragma: export
@@ -82,13 +83,11 @@ struct SolveArguments {
// Solve(model, SolverType::kGlop,
// { .interrupter = interrupter.get() });
//
const SolveInterrupter* interrupter = nullptr;
const SolveInterrupter* absl_nullable interrupter = nullptr;
// Returns a failure if the referenced variables and constraints don't belong
// to the input expected_storage (which must not be nullptr). Also returns a
// failure if callback events are registered but no callback is provided.
absl::Status CheckModelStorageAndCallback(
ModelStorageCPtr expected_storage) const;
// to the input expected_storage (which must not be nullptr).
absl::Status CheckModelStorage(ModelStorageCPtr expected_storage) const;
};
} // namespace operations_research::math_opt

View File

@@ -27,7 +27,7 @@ namespace {
using ::testing::HasSubstr;
using ::testing::status::StatusIs;
TEST(CheckModelStorageAndCallbackTest, CorrectModelAndCallback) {
TEST(CheckModelStorageTest, CorrectModelAndCallback) {
Model model;
const Variable x = model.AddVariable("x");
@@ -41,10 +41,10 @@ TEST(CheckModelStorageAndCallbackTest, CorrectModelAndCallback) {
.callback = [](const CallbackData&) { return CallbackResult{}; },
};
EXPECT_OK(args.CheckModelStorageAndCallback(model.storage()));
EXPECT_OK(args.CheckModelStorage(model.storage()));
}
TEST(CheckModelStorageAndCallbackTest, WrongModelInModelParameters) {
TEST(CheckModelStorageTest, WrongModelInModelParameters) {
Model model;
const Variable x = model.AddVariable("x");
@@ -53,12 +53,12 @@ TEST(CheckModelStorageAndCallbackTest, WrongModelInModelParameters) {
};
Model other_model;
EXPECT_THAT(args.CheckModelStorageAndCallback(other_model.storage()),
EXPECT_THAT(args.CheckModelStorage(other_model.storage()),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("model_parameters")));
}
TEST(CheckModelStorageAndCallbackTest, WrongModelInCallbackRegistration) {
TEST(CheckModelStorageTest, WrongModelInCallbackRegistration) {
Model model;
const Variable x = model.AddVariable("x");
@@ -72,26 +72,11 @@ TEST(CheckModelStorageAndCallbackTest, WrongModelInCallbackRegistration) {
};
Model other_model;
EXPECT_THAT(args.CheckModelStorageAndCallback(other_model.storage()),
EXPECT_THAT(args.CheckModelStorage(other_model.storage()),
StatusIs(absl::StatusCode::kInvalidArgument,
AllOf(HasSubstr("callback_registration"),
HasSubstr("mip_solution_filter"))));
}
TEST(CheckModelStorageAndCallbackTest, NoCallbackWithRegisteredEvents) {
Model model;
const SolveArguments args = {
.callback_registration =
{
.events = {CallbackEvent::kMipSolution},
},
};
EXPECT_THAT(
args.CheckModelStorageAndCallback(model.storage()),
StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("no callback")));
}
} // namespace
} // namespace operations_research::math_opt

View File

@@ -17,6 +17,7 @@
#include <optional>
#include <utility>
#include "absl/base/nullability.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/check.h"
#include "absl/memory/memory.h"
@@ -44,7 +45,7 @@ absl::StatusOr<SolveResult> CallSolve(BaseSolver& solver,
const ModelStorageCPtr expected_storage,
const SolveArguments& arguments,
SolveInterrupter& local_canceller) {
RETURN_IF_ERROR(arguments.CheckModelStorageAndCallback(expected_storage));
RETURN_IF_ERROR(arguments.CheckModelStorage(expected_storage));
BaseSolver::Callback cb = nullptr;
absl::Mutex mutex;
@@ -124,7 +125,8 @@ absl::StatusOr<ComputeInfeasibleSubsystemResult> CallComputeInfeasibleSubsystem(
absl::StatusOr<SolveResult> SolveImpl(
const BaseSolverFactory solver_factory, const Model& model,
const SolverType solver_type, const SolveArguments& solve_args,
const SolveInterrupter* const user_canceller, const bool remove_names) {
const SolveInterrupter* absl_nullable const user_canceller,
const bool remove_names) {
SolveInterrupter local_canceller;
const ScopedSolveInterrupterCallback user_canceller_cb(
user_canceller, [&]() { local_canceller.Interrupt(); });
@@ -139,7 +141,8 @@ absl::StatusOr<ComputeInfeasibleSubsystemResult> ComputeInfeasibleSubsystemImpl(
const BaseSolverFactory solver_factory, const Model& model,
const SolverType solver_type,
const ComputeInfeasibleSubsystemArguments& compute_args,
const SolveInterrupter* const user_canceller, const bool remove_names) {
const SolveInterrupter* absl_nullable const user_canceller,
const bool remove_names) {
SolveInterrupter local_canceller;
const ScopedSolveInterrupterCallback user_canceller_cb(
user_canceller, [&]() { local_canceller.Interrupt(); });
@@ -152,10 +155,11 @@ absl::StatusOr<ComputeInfeasibleSubsystemResult> ComputeInfeasibleSubsystemImpl(
}
absl::StatusOr<std::unique_ptr<IncrementalSolverImpl>>
IncrementalSolverImpl::New(BaseSolverFactory solver_factory, Model* const model,
const SolverType solver_type,
const SolveInterrupter* const user_canceller,
const bool remove_names) {
IncrementalSolverImpl::New(
BaseSolverFactory solver_factory, Model* const model,
const SolverType solver_type,
const SolveInterrupter* absl_nullable const user_canceller,
const bool remove_names) {
if (model == nullptr) {
return absl::InvalidArgumentError("input model can't be null");
}

View File

@@ -16,6 +16,7 @@
#include <memory>
#include "absl/base/nullability.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/statusor.h"
#include "ortools/math_opt/core/base_solver.h"
@@ -55,12 +56,10 @@ using BaseSolverFactory =
// Solves the input model.
//
// The `user_canceller` parameter is optional.
absl::StatusOr<SolveResult> SolveImpl(BaseSolverFactory solver_factory,
const Model& model,
SolverType solver_type,
const SolveArguments& solve_args,
const SolveInterrupter* user_canceller,
bool remove_names);
absl::StatusOr<SolveResult> SolveImpl(
BaseSolverFactory solver_factory, const Model& model,
SolverType solver_type, const SolveArguments& solve_args,
const SolveInterrupter* absl_nullable user_canceller, bool remove_names);
// ComputeInfeasibleSubsystems the input model in a subprocess.
//
@@ -69,7 +68,7 @@ absl::StatusOr<ComputeInfeasibleSubsystemResult> ComputeInfeasibleSubsystemImpl(
BaseSolverFactory solver_factory, const Model& model,
SolverType solver_type,
const ComputeInfeasibleSubsystemArguments& compute_args,
const SolveInterrupter* user_canceller, bool remove_names);
const SolveInterrupter* absl_nullable user_canceller, bool remove_names);
// Incremental solve of a model.
class IncrementalSolverImpl : public IncrementalSolver {
@@ -79,7 +78,7 @@ class IncrementalSolverImpl : public IncrementalSolver {
// The `user_canceller` parameter is optional.
static absl::StatusOr<std::unique_ptr<IncrementalSolverImpl>> New(
BaseSolverFactory solver_factory, Model* model, SolverType solver_type,
const SolveInterrupter* user_canceller, bool remove_names);
const SolveInterrupter* absl_nullable user_canceller, bool remove_names);
absl::StatusOr<UpdateResult> Update() override;

View File

@@ -484,32 +484,6 @@ TEST(SolveImplTest, FailingSolve) {
StatusIs(absl::StatusCode::kInternal, "solve failed"));
}
TEST(SolveImplTest, NullCallback) {
BasicLp basic_lp;
SolveArguments args;
args.parameters.enable_output = true;
args.model_parameters =
ModelSolveParameters::OnlySomePrimalVariables({basic_lp.a});
args.callback_registration.add_lazy_constraints = true;
args.callback_registration.events.insert(CallbackEvent::kMipSolution);
BaseSolverFactoryMock factory_mock;
BaseSolverMock solver;
EXPECT_CALL(factory_mock, Call(SOLVER_TYPE_GLOP,
EquivToProto(basic_lp.model.ExportModel()), _))
.WillOnce(
Return(ByMove(std::make_unique<DelegatingBaseSolver>(&solver))));
EXPECT_THAT(
SolveImpl(factory_mock.AsStdFunction(), basic_lp.model, SolverType::kGlop,
args, /*user_canceller=*/nullptr, /*remove_names=*/false),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("no callback was provided")));
}
TEST(SolveImplTest, WrongModelInModelParameters) {
BasicLp basic_lp;
BasicLp other_basic_lp;
@@ -1593,40 +1567,6 @@ TEST(IncrementalSolverImplTest, UpdateAndSolveWithFailingSolverUpdate) {
HasSubstr("update failed"))));
}
TEST(IncrementalSolverImplTest, NullCallback) {
BasicLp basic_lp;
SolveArguments args;
args.parameters.enable_output = true;
args.model_parameters =
ModelSolveParameters::OnlySomePrimalVariables({basic_lp.a});
args.callback_registration.add_lazy_constraints = true;
args.callback_registration.events.insert(CallbackEvent::kMipSolution);
BaseSolverFactoryMock factory_mock;
BaseSolverMock solver_interface;
EXPECT_CALL(factory_mock, Call(SOLVER_TYPE_GLOP,
EquivToProto(basic_lp.model.ExportModel()), _))
.WillOnce(Return(
ByMove(std::make_unique<DelegatingBaseSolver>(&solver_interface))));
ASSERT_OK_AND_ASSIGN(
std::unique_ptr<IncrementalSolver> solver,
IncrementalSolverImpl::New(
factory_mock.AsStdFunction(), &basic_lp.model, SolverType::kGlop,
/*user_canceller=*/nullptr, /*remove_names=*/false));
Mock::VerifyAndClearExpectations(&factory_mock);
Mock::VerifyAndClearExpectations(&solver_interface);
EXPECT_THAT(solver->SolveWithoutUpdate(args),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("no callback was provided")));
}
TEST(IncrementalSolverImplTest, WrongModelInModelParameters) {
BasicLp basic_lp;
BasicLp other_basic_lp;

View File

@@ -19,6 +19,7 @@
#include <optional>
#include <string>
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
@@ -53,7 +54,6 @@ using ::testing::HasSubstr;
using ::testing::InSequence;
using ::testing::Mock;
using ::testing::Ne;
using ::testing::Optional;
using ::testing::Pair;
using ::testing::Return;
using ::testing::UnorderedElementsAre;
@@ -184,7 +184,7 @@ TEST(SolveTest, SuccessfulSolveWithCallback) {
[&](const SolveParametersProto&, const ModelSolveParametersProto&,
const MessageCallback message_cb, const CallbackRegistrationProto&,
SolverInterface::Callback cb,
const SolveInterrupter* const interrupter)
const SolveInterrupter* absl_nullable const interrupter)
-> absl::StatusOr<SolveResultProto> {
CallbackDataProto cb_data;
cb_data.set_event(CALLBACK_EVENT_MIP_SOLUTION);
@@ -345,10 +345,10 @@ TEST(SolveTest, NullCallback) {
EXPECT_CALL(factory_mock, Call(EquivToProto(basic_lp.model.ExportModel()), _))
.WillOnce(Return(ByMove(std::make_unique<DelegatingSolver>(&solver))));
EXPECT_THAT(Solve(basic_lp.model,
EnumFromProto(registration.solver_type()).value(), args),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("no callback was provided")));
EXPECT_THAT(
Solve(basic_lp.model, EnumFromProto(registration.solver_type()).value(),
args),
StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("no callback")));
}
TEST(SolveTest, WrongModelInModelParameters) {
@@ -416,7 +416,7 @@ TEST(SolveTest, WrongModelInCallbackResult) {
[&](const SolveParametersProto&, const ModelSolveParametersProto&,
const MessageCallback message_cb, const CallbackRegistrationProto&,
SolverInterface::Callback cb,
const SolveInterrupter* const interrupter)
const SolveInterrupter* absl_nullable const interrupter)
-> absl::StatusOr<SolveResultProto> {
CallbackDataProto cb_data;
cb_data.set_event(CALLBACK_EVENT_MIP_SOLUTION);
@@ -961,7 +961,7 @@ TEST(IncrementalSolverTest, SuccessfulSolveWithCallback) {
[&](const SolveParametersProto&, const ModelSolveParametersProto&,
const MessageCallback message_cb, const CallbackRegistrationProto&,
SolverInterface::Callback cb,
const SolveInterrupter* const interrupter)
const SolveInterrupter* absl_nullable const interrupter)
-> absl::StatusOr<SolveResultProto> {
CallbackDataProto cb_data;
cb_data.set_event(CALLBACK_EVENT_MIP_SOLUTION);
@@ -1137,7 +1137,7 @@ TEST(IncrementalSolverTest, UpdateAndSolve) {
[&](const SolveParametersProto&, const ModelSolveParametersProto&,
const MessageCallback message_cb, const CallbackRegistrationProto&,
SolverInterface::Callback cb,
const SolveInterrupter* const interrupter)
const SolveInterrupter* absl_nullable const interrupter)
-> absl::StatusOr<SolveResultProto> {
CallbackDataProto cb_data;
cb_data.set_event(CALLBACK_EVENT_MIP_SOLUTION);
@@ -1306,9 +1306,9 @@ TEST(IncrementalSolverTest, NullCallback) {
Mock::VerifyAndClearExpectations(&factory_mock);
Mock::VerifyAndClearExpectations(&solver_interface);
EXPECT_THAT(solver->SolveWithoutUpdate(args),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("no callback was provided")));
EXPECT_THAT(
solver->SolveWithoutUpdate(args),
StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("no callback")));
}
TEST(IncrementalSolverTest, WrongModelInModelParameters) {
@@ -1395,7 +1395,7 @@ TEST(IncrementalSolverTest, WrongModelInCallbackResult) {
[&](const SolveParametersProto&, const ModelSolveParametersProto&,
const MessageCallback message_cb, const CallbackRegistrationProto&,
SolverInterface::Callback cb,
const SolveInterrupter* const interrupter)
const SolveInterrupter* absl_nullable const interrupter)
-> absl::StatusOr<SolveResultProto> {
CallbackDataProto cb_data;
cb_data.set_event(CALLBACK_EVENT_MIP_SOLUTION);

View File

@@ -16,6 +16,7 @@
#include <memory>
#include <optional>
#include "absl/log/die_if_null.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "ortools/base/logging.h"

View File

@@ -54,6 +54,7 @@ cc_library(
"//ortools/math_opt/validators:callback_validator",
"//ortools/port:proto_utils",
"//ortools/util:solve_interrupter",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/cleanup",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/container:flat_hash_set",
@@ -141,12 +142,12 @@ cc_library(
"//ortools/util:solve_interrupter",
"//ortools/util:testing_utils",
"@abseil-cpp//absl/algorithm:container",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/container:flat_hash_set",
"@abseil-cpp//absl/log",
"@abseil-cpp//absl/log:check",
"@abseil-cpp//absl/memory",
"@abseil-cpp//absl/meta:type_traits",
"@abseil-cpp//absl/status",
"@abseil-cpp//absl/status:statusor",
"@abseil-cpp//absl/strings",
@@ -193,6 +194,7 @@ cc_library(
"//ortools/util:solve_interrupter",
"//ortools/util:strong_integers",
"//ortools/util:time_limit",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/cleanup",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/log",
@@ -387,6 +389,7 @@ cc_library(
"//ortools/pdlp:solvers_cc_proto",
"//ortools/port:proto_utils",
"//ortools/util:solve_interrupter",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/log",
"@abseil-cpp//absl/memory",
"@abseil-cpp//absl/status",
@@ -469,6 +472,7 @@ cc_library(
"//ortools/third_party_solvers/glpk:glpk_env_deleter",
"//ortools/third_party_solvers/glpk:glpk_formatters",
"//ortools/util:solve_interrupter",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/cleanup",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/log",
@@ -568,6 +572,7 @@ cc_library(
"//ortools/util:solve_interrupter",
"//ortools/util:status_macros",
"@abseil-cpp//absl/algorithm:container",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/cleanup",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/log:check",
@@ -706,6 +711,7 @@ cc_library(
"//ortools/port:proto_utils",
"//ortools/third_party_solvers:xpress_environment",
"//ortools/util:solve_interrupter",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/log:check",
"@abseil-cpp//absl/memory",
"@abseil-cpp//absl/status",

View File

@@ -503,7 +503,7 @@ absl::StatusOr<SolveResultProto> CpSatSolver::Solve(
const ModelSolveParametersProto& model_parameters,
const MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, const Callback cb,
const SolveInterrupter* const interrupter) {
const SolveInterrupter* absl_nullable interrupter) {
RETURN_IF_ERROR(ModelSolveParametersAreSupported(
model_parameters, kCpSatSupportedStructures, "CP-SAT"));
const absl::Time start = absl::Now();
@@ -675,7 +675,7 @@ InvertedBounds CpSatSolver::ListInvertedBounds() const {
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
CpSatSolver::ComputeInfeasibleSubsystem(const SolveParametersProto&,
MessageCallback,
const SolveInterrupter*) {
const SolveInterrupter* absl_nullable) {
return absl::UnimplementedError(
"CPSAT does not provide a method to compute an infeasible subsystem");
}

View File

@@ -18,6 +18,7 @@
#include <memory>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/status/statusor.h"
#include "absl/types/span.h"
#include "ortools/linear_solver/linear_solver.pb.h"
@@ -46,12 +47,12 @@ class CpSatSolver : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* interrupter) override;
const SolveInterrupter* absl_nullable interrupter) override;
absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
MessageCallback message_cb,
const SolveInterrupter* interrupter) override;
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter) override;
private:
CpSatSolver(MPModelProto cp_sat_model, std::vector<int64_t> variable_ids,

View File

@@ -21,6 +21,7 @@
#include <string>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/cleanup/cleanup.h"
#include "absl/container/flat_hash_map.h"
#include "absl/log/check.h"
@@ -87,7 +88,8 @@ absl::string_view SafeName(const LinearConstraintsProto& linear_constraints,
}
absl::StatusOr<TerminationProto> BuildTermination(
const glop::ProblemStatus status, const SolveInterrupter* const interrupter,
const glop::ProblemStatus status,
const SolveInterrupter* absl_nullable const interrupter,
const bool is_maximize, const double objective_value) {
switch (status) {
case glop::ProblemStatus::OPTIMAL:
@@ -730,7 +732,7 @@ absl::Status GlopSolver::FillSolveStats(const absl::Duration solve_time,
absl::StatusOr<SolveResultProto> GlopSolver::MakeSolveResult(
const glop::ProblemStatus status,
const ModelSolveParametersProto& model_parameters,
const SolveInterrupter* const interrupter,
const SolveInterrupter* absl_nullable const interrupter,
const absl::Duration solve_time) {
SolveResultProto solve_result;
ASSIGN_OR_RETURN(*solve_result.mutable_termination(),
@@ -765,7 +767,7 @@ absl::StatusOr<SolveResultProto> GlopSolver::Solve(
const ModelSolveParametersProto& model_parameters,
const MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, const Callback,
const SolveInterrupter* const interrupter) {
const SolveInterrupter* absl_nullable const interrupter) {
RETURN_IF_ERROR(ModelSolveParametersAreSupported(
model_parameters, kGlopSupportedStructures, "Glop"));
RETURN_IF_ERROR(CheckRegisteredCallbackEvents(callback_registration,
@@ -886,7 +888,7 @@ absl::StatusOr<bool> GlopSolver::Update(const ModelUpdateProto& model_update) {
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
GlopSolver::ComputeInfeasibleSubsystem(const SolveParametersProto&,
MessageCallback,
const SolveInterrupter*) {
const SolveInterrupter* absl_nullable) {
return absl::UnimplementedError(
"GLOP does not implement a method to compute an infeasible subsystem");
}

View File

@@ -18,6 +18,7 @@
#include <memory>
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
@@ -53,12 +54,12 @@ class GlopSolver : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* interrupter) override;
const SolveInterrupter* absl_nullable interrupter) override;
absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
MessageCallback message_cb,
const SolveInterrupter* interrupter) override;
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter) override;
// Returns the merged parameters and a list of warnings from any parameter
// settings that are invalid for this solver.
@@ -93,7 +94,8 @@ class GlopSolver : public SolverInterface {
absl::StatusOr<SolveResultProto> MakeSolveResult(
glop::ProblemStatus status,
const ModelSolveParametersProto& model_parameters,
const SolveInterrupter* interrupter, absl::Duration solve_time);
const SolveInterrupter* absl_nullable interrupter,
absl::Duration solve_time);
absl::Status FillSolveStats(absl::Duration solve_time,
SolveStatsProto& solve_stats);

View File

@@ -27,6 +27,7 @@
#include <utility>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/cleanup/cleanup.h"
#include "absl/container/flat_hash_map.h"
#include "absl/log/check.h"
@@ -490,7 +491,8 @@ absl::Status SetLPParameters(const SolveParametersProto& parameters,
class MipCallbackData {
public:
explicit MipCallbackData(const SolveInterrupter* const interrupter)
explicit MipCallbackData(
const SolveInterrupter* absl_nullable const interrupter)
: interrupter_(interrupter) {}
void Callback(glp_tree* const tree) {
@@ -540,7 +542,7 @@ class MipCallbackData {
private:
// Optional interrupter.
const SolveInterrupter* const interrupter_;
const SolveInterrupter* absl_nullable const interrupter_;
// Set to true if glp_ios_terminate() has been called due to the interrupter.
std::atomic<bool> interrupted_by_interrupter_ = false;
@@ -1059,7 +1061,8 @@ absl::StatusOr<SolveResultProto> GlpkSolver::Solve(
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration,
const Callback /*cb*/, const SolveInterrupter* const interrupter) {
const Callback /*cb*/,
const SolveInterrupter* absl_nullable const interrupter) {
RETURN_IF_ERROR(ModelSolveParametersAreSupported(
model_parameters, kGlpkSupportedStructures, "GLPK"));
RETURN_IF_ERROR(CheckCurrentThread());
@@ -1808,7 +1811,7 @@ std::optional<SolveResultProto> GlpkSolver::EmptyIntegerBoundsResult() {
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
GlpkSolver::ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* const interrupter) {
const SolveInterrupter* absl_nullable const interrupter) {
return absl::UnimplementedError(
"GLPK does not provide a method to compute an infeasible subsystem");
}

View File

@@ -20,6 +20,7 @@
#include <thread>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
@@ -55,12 +56,12 @@ class GlpkSolver : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* interrupter) override;
const SolveInterrupter* absl_nullable interrupter) override;
absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
MessageCallback message_cb,
const SolveInterrupter* interrupter) override;
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter) override;
private:
// The columns of the GPLK problem.

View File

@@ -23,6 +23,7 @@
#include <utility>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/cleanup/cleanup.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
@@ -1013,7 +1014,7 @@ absl::StatusOr<SolveResultProto> GScipSolver::Solve(
const ModelSolveParametersProto& model_parameters,
const MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* const interrupter) {
const SolveInterrupter* absl_nullable const interrupter) {
RETURN_IF_ERROR(ModelSolveParametersAreSupported(
model_parameters, kGscipSupportedStructures, "SCIP"));
const absl::Time start = absl::Now();
@@ -1353,7 +1354,7 @@ absl::StatusOr<bool> GScipSolver::Update(const ModelUpdateProto& model_update) {
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
GScipSolver::ComputeInfeasibleSubsystem(const SolveParametersProto&,
MessageCallback,
const SolveInterrupter*) {
const SolveInterrupter* absl_nullable) {
return absl::UnimplementedError(
"SCIP does not provide a method to compute an infeasible subsystem");
}

View File

@@ -20,6 +20,7 @@
#include <utility>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
@@ -58,12 +59,12 @@ class GScipSolver : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* interrupter) override;
const SolveInterrupter* absl_nullable interrupter) override;
absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
MessageCallback message_cb,
const SolveInterrupter* interrupter) override;
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter) override;
// Returns the merged parameters and a list of warnings for unsupported
// parameters.

View File

@@ -26,6 +26,7 @@
#include <vector>
#include "absl/algorithm/container.h"
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/check.h"
@@ -2145,8 +2146,8 @@ absl::Status GurobiSolver::ChangeCoefficients(
}
absl::Status GurobiSolver::UpdateDoubleListAttribute(
const SparseDoubleVectorProto& update, const char* attribute_name,
const IdHashMap& id_hash_map) {
const SparseDoubleVectorProto& update,
const char* absl_nonnull attribute_name, const IdHashMap& id_hash_map) {
if (update.ids_size() == 0) {
return absl::OkStatus();
}
@@ -2159,8 +2160,8 @@ absl::Status GurobiSolver::UpdateDoubleListAttribute(
}
absl::Status GurobiSolver::UpdateInt32ListAttribute(
const SparseInt32VectorProto& update, const char* attribute_name,
const IdHashMap& id_hash_map) {
const SparseInt32VectorProto& update,
const char* absl_nonnull attribute_name, const IdHashMap& id_hash_map) {
if (update.ids_size() == 0) {
return absl::OkStatus();
}
@@ -2782,11 +2783,10 @@ absl::StatusOr<std::unique_ptr<GurobiSolver>> GurobiSolver::New(
}
absl::StatusOr<std::unique_ptr<GurobiSolver::GurobiCallbackData>>
GurobiSolver::RegisterCallback(const CallbackRegistrationProto& registration,
const Callback cb,
const MessageCallback message_cb,
const absl::Time start,
SolveInterrupter* const local_interrupter) {
GurobiSolver::RegisterCallback(
const CallbackRegistrationProto& registration, const Callback cb,
const MessageCallback message_cb, const absl::Time start,
SolveInterrupter* absl_nullable const local_interrupter) {
const absl::flat_hash_set<CallbackEventProto> events = EventSet(registration);
// Note that IS_MIP does not necessarily mean the problem has integer
@@ -2971,7 +2971,7 @@ absl::StatusOr<SolveResultProto> GurobiSolver::Solve(
const ModelSolveParametersProto& model_parameters,
const MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, const Callback cb,
const SolveInterrupter* const interrupter) {
const SolveInterrupter* absl_nullable const interrupter) {
RETURN_IF_ERROR(ModelSolveParametersAreSupported(
model_parameters, kGurobiSupportedStructures, "Gurobi"));
const absl::Time start = absl::Now();
@@ -3102,7 +3102,7 @@ absl::StatusOr<SolveResultProto> GurobiSolver::Solve(
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
GurobiSolver::ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* const interrupter) {
const SolveInterrupter* absl_nullable const interrupter) {
const absl::Time start = absl::Now();
// Need to run GRBupdatemodel before:

View File

@@ -21,6 +21,7 @@
#include <utility>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
@@ -60,17 +61,18 @@ class GurobiSolver : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* interrupter) override;
const SolveInterrupter* absl_nullable interrupter) override;
absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
MessageCallback message_cb,
const SolveInterrupter* interrupter) override;
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter) override;
private:
struct GurobiCallbackData {
explicit GurobiCallbackData(GurobiCallbackInput callback_input,
SolveInterrupter* const local_interrupter)
explicit GurobiCallbackData(
GurobiCallbackInput callback_input,
SolveInterrupter* absl_nullable const local_interrupter)
: callback_input(std::move(callback_input)),
local_interrupter(local_interrupter) {}
const GurobiCallbackInput callback_input;
@@ -83,7 +85,7 @@ class GurobiSolver : public SolverInterface {
//
// It is optional; it is not null when either we have a LP/MIP callback or a
// user interrupter. But it can be null if we only have a message callback.
SolveInterrupter* const local_interrupter;
SolveInterrupter* absl_nullable const local_interrupter;
MessageCallbackData message_callback_data;
@@ -305,11 +307,11 @@ class GurobiSolver : public SolverInterface {
const SparseDoubleMatrixProto& terms);
absl::Status LoadModel(const ModelProto& input_model);
absl::Status UpdateDoubleListAttribute(const SparseDoubleVectorProto& update,
const char* attribute_name,
const IdHashMap& id_hash_map);
absl::Status UpdateDoubleListAttribute(
const SparseDoubleVectorProto& update,
const char* absl_nonnull attribute_name, const IdHashMap& id_hash_map);
absl::Status UpdateInt32ListAttribute(const SparseInt32VectorProto& update,
const char* attribute_name,
const char* absl_nonnull attribute_name,
const IdHashMap& id_hash_map);
struct DeletedIndices {
@@ -354,7 +356,7 @@ class GurobiSolver : public SolverInterface {
absl::StatusOr<std::unique_ptr<GurobiCallbackData>> RegisterCallback(
const CallbackRegistrationProto& registration, Callback cb,
MessageCallback message_cb, absl::Time start,
SolveInterrupter* local_interrupter);
SolveInterrupter* absl_nullable local_interrupter);
// Returns the ids of variables and linear constraints with inverted bounds.
absl::StatusOr<InvertedBounds> ListInvertedBounds() const;

View File

@@ -31,6 +31,7 @@
#include "Highs.h"
#include "absl/algorithm/container.h"
#include "absl/base/nullability.h"
#include "absl/cleanup/cleanup.h"
#include "absl/container/flat_hash_map.h"
#include "absl/log/check.h"
@@ -912,7 +913,7 @@ absl::StatusOr<SolveResultProto> HighsSolver::Solve(
const SolveParametersProto& parameters,
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb, const CallbackRegistrationProto&, Callback,
const SolveInterrupter* const) {
const SolveInterrupter* absl_nullable const) {
RETURN_IF_ERROR(ModelSolveParametersAreSupported(
model_parameters, kHighsSupportedStructures, "Highs"));
const absl::Time start = absl::Now();
@@ -1031,7 +1032,7 @@ absl::StatusOr<bool> HighsSolver::Update(const ModelUpdateProto&) {
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
HighsSolver::ComputeInfeasibleSubsystem(const SolveParametersProto&,
MessageCallback,
const SolveInterrupter*) {
const SolveInterrupter* absl_nullable) {
return absl::UnimplementedError(
"HiGHS does not provide a method to compute an infeasible subsystem");
}

View File

@@ -22,6 +22,7 @@
#include <vector>
#include "Highs.h"
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
@@ -51,12 +52,12 @@ class HighsSolver : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* interrupter) override;
const SolveInterrupter* absl_nullable interrupter) override;
absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
MessageCallback message_cb,
const SolveInterrupter* interrupter) override;
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter) override;
private:
struct SolutionClaims {

View File

@@ -24,6 +24,7 @@
#include <utility>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
@@ -336,7 +337,7 @@ absl::StatusOr<SolveResultProto> PdlpSolver::Solve(
const ModelSolveParametersProto& model_parameters,
const MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, const Callback,
const SolveInterrupter* const interrupter) {
const SolveInterrupter* absl_nullable const interrupter) {
RETURN_IF_ERROR(ModelSolveParametersAreSupported(
model_parameters, kPdlpSupportedStructures, "PDLP"));
RETURN_IF_ERROR(CheckRegisteredCallbackEvents(callback_registration,
@@ -381,7 +382,7 @@ absl::StatusOr<bool> PdlpSolver::Update(const ModelUpdateProto&) {
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
PdlpSolver::ComputeInfeasibleSubsystem(const SolveParametersProto&,
MessageCallback,
const SolveInterrupter*) {
const SolveInterrupter* absl_nullable) {
return absl::UnimplementedError(
"PDLP does not provide a method to compute an infeasible subsystem");
}

View File

@@ -16,6 +16,7 @@
#include <memory>
#include "absl/base/nullability.h"
#include "absl/status/statusor.h"
#include "ortools/math_opt/callback.pb.h"
#include "ortools/math_opt/core/solver_interface.h"
@@ -43,12 +44,12 @@ class PdlpSolver : public SolverInterface {
const ModelSolveParametersProto& model_parameters,
MessageCallback message_cb,
const CallbackRegistrationProto& callback_registration, Callback cb,
const SolveInterrupter* interrupter) override;
const SolveInterrupter* absl_nullable interrupter) override;
absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
MessageCallback message_cb,
const SolveInterrupter* interrupter) override;
ComputeInfeasibleSubsystem(
const SolveParametersProto& parameters, MessageCallback message_cb,
const SolveInterrupter* absl_nullable interrupter) override;
// Returns the merged parameters and a list of warnings.
static absl::StatusOr<pdlp::PrimalDualHybridGradientParams> MergeParameters(