Skip to content

Commit

Permalink
export math_opt/ from google3
Browse files Browse the repository at this point in the history
  • Loading branch information
Mizux committed Jul 30, 2024
1 parent 286089e commit 6dc3177
Show file tree
Hide file tree
Showing 95 changed files with 3,396 additions and 603 deletions.
21 changes: 20 additions & 1 deletion ortools/math_opt/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ cc_library(
srcs = ["solver.cc"],
hdrs = ["solver.h"],
deps = [
":base_solver",
":concurrent_calls_guard",
":math_opt_proto_utils",
":model_summary",
Expand All @@ -126,7 +127,6 @@ cc_library(
"//ortools/math_opt/validators:result_validator",
"//ortools/math_opt/validators:solve_parameters_validator",
"//ortools/port:proto_utils",
"//ortools/util:solve_interrupter",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
Expand Down Expand Up @@ -230,3 +230,22 @@ cc_library(
"@com_google_protobuf//:protobuf",
],
)

cc_library(
name = "base_solver",
srcs = ["base_solver.cc"],
hdrs = ["base_solver.h"],
deps = [
"//ortools/math_opt:callback_cc_proto",
"//ortools/math_opt:infeasible_subsystem_cc_proto",
"//ortools/math_opt:model_cc_proto",
"//ortools/math_opt:model_parameters_cc_proto",
"//ortools/math_opt:model_update_cc_proto",
"//ortools/math_opt:parameters_cc_proto",
"//ortools/math_opt:result_cc_proto",
"//ortools/util:solve_interrupter",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:string_view",
],
)
51 changes: 51 additions & 0 deletions ortools/math_opt/core/base_solver.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2010-2024 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.

#include "ortools/math_opt/core/base_solver.h"

#include <ostream>

#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"

namespace operations_research::math_opt {
namespace {

// Returns a string describing if the input pointer-like type is == nullptr.
template <typename Ptr>
absl::string_view IsNullString(const Ptr& ptr) {
return ptr == nullptr ? "<null>" : "<not null>";
}

} // namespace

std::ostream& operator<<(std::ostream& out, const BaseSolver::SolveArgs& args) {
out << "{ parameters: <" << absl::StrCat(args.parameters)
<< ">, model_parameters: <" << absl::StrCat(args.model_parameters)
<< ">, message_callback: " << IsNullString(args.message_callback)
<< ", callback_registration: <"
<< absl::StrCat(args.callback_registration)
<< ">, user_cb: " << IsNullString(args.user_cb)
<< ", interrupter: " << args.interrupter << " }";
return out;
}

std::ostream& operator<<(
std::ostream& out, const BaseSolver::ComputeInfeasibleSubsystemArgs& args) {
out << "{ parameters: <" << absl::StrCat(args.parameters)
<< ">, message_callback: " << IsNullString(args.message_callback)
<< ", interrupter: " << args.interrupter << " }";
return out;
}

} // namespace operations_research::math_opt
129 changes: 129 additions & 0 deletions ortools/math_opt/core/base_solver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Copyright 2010-2024 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.

#ifndef OR_TOOLS_MATH_OPT_CORE_BASE_SOLVER_H_
#define OR_TOOLS_MATH_OPT_CORE_BASE_SOLVER_H_

#include <functional>
#include <ostream>
#include <string>
#include <vector>

#include "absl/status/statusor.h"
#include "ortools/math_opt/callback.pb.h"
#include "ortools/math_opt/infeasible_subsystem.pb.h"
#include "ortools/math_opt/model.pb.h"
#include "ortools/math_opt/model_parameters.pb.h"
#include "ortools/math_opt/model_update.pb.h"
#include "ortools/math_opt/parameters.pb.h"
#include "ortools/math_opt/result.pb.h"
#include "ortools/util/solve_interrupter.h"

namespace operations_research::math_opt {

// The API of solvers (in-process, sub-process and streaming RPC ones).
//
// Thread-safety: methods Solve() and Update() must not be called concurrently;
// they should immediately return with an error status if this happens.
//
// TODO: b/350984134 - Rename `Solver` into `InProcessSolver` and then rename
// `BaseSolver` into `Solver`.
class BaseSolver {
public:
// Callback function for messages callback sent by the solver.
//
// Each message represents a single output line from the solver, and each
// message does not contain any '\n' character in it.
//
// Thread-safety: a callback may be called concurrently from multiple
// threads. The users is expected to use proper synchronization primitives to
// deal with that.
using MessageCallback = std::function<void(const std::vector<std::string>&)>;

// Callback function type for MIP/LP callbacks.
using Callback = std::function<CallbackResultProto(const CallbackDataProto&)>;

// Arguments used when calling Solve() to solve the problem.
struct SolveArgs {
SolveParametersProto parameters;
ModelSolveParametersProto model_parameters;

// An optional callback for messages emitted by the solver.
//
// When set it enables the solver messages and ignores the `enable_output`
// in solve parameters; messages are redirected to the callback and not
// printed on stdout/stderr/logs anymore.
MessageCallback message_callback = nullptr;

CallbackRegistrationProto callback_registration;
Callback user_cb = nullptr;

// An optional interrupter that the solver can use to interrupt the solve
// early.
const SolveInterrupter* interrupter = nullptr;

friend std::ostream& operator<<(std::ostream& out, const SolveArgs& args);
};

// Arguments used when calling ComputeInfeasibleSubsystem().
struct ComputeInfeasibleSubsystemArgs {
SolveParametersProto parameters;

// An optional callback for messages emitted by the solver.
//
// When set it enables the solver messages and ignores the `enable_output`
// in solve parameters; messages are redirected to the callback and not
// printed on stdout/stderr/logs anymore.
MessageCallback message_callback = nullptr;

// An optional interrupter that the solver can use to interrupt the solve
// early.
const SolveInterrupter* interrupter = nullptr;

friend std::ostream& operator<<(std::ostream& out,
const ComputeInfeasibleSubsystemArgs& args);
};

BaseSolver() = default;
BaseSolver(const BaseSolver&) = delete;
BaseSolver& operator=(const BaseSolver&) = delete;
virtual ~BaseSolver() = default;

// Solves the current model (including all updates).
virtual absl::StatusOr<SolveResultProto> Solve(
const SolveArgs& arguments) = 0;

// Computes an infeasible subsystem of `model` (including all updates).
virtual absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(
const ComputeInfeasibleSubsystemArgs& arguments) = 0;

// Updates the model to solve and returns true, or returns false if this
// update is not supported by the underlying solver.
//
// The model_update is passed by value. Non in-process implementations will
// move it in-place in the messages used to communicate with the other
// process. Thus if possible, the caller should std::move() this proto to this
// function.
//
// A status error will be returned if the model_update is invalid or the
// underlying solver has an internal error.
//
// When this function returns false, the BaseSolver object is in a failed
// state.
virtual absl::StatusOr<bool> Update(ModelUpdateProto model_update) = 0;
};

} // namespace operations_research::math_opt

#endif // OR_TOOLS_MATH_OPT_CORE_BASE_SOLVER_H_
2 changes: 1 addition & 1 deletion ortools/math_opt/core/solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ absl::StatusOr<SolveResultProto> Solver::Solve(const SolveArgs& arguments) {
return result;
}

absl::StatusOr<bool> Solver::Update(const ModelUpdateProto& model_update) {
absl::StatusOr<bool> Solver::Update(const ModelUpdateProto model_update) {
ASSIGN_OR_RETURN(const auto guard,
ConcurrentCallsGuard::TryAcquire(concurrent_calls_tracker_));

Expand Down
96 changes: 18 additions & 78 deletions ortools/math_opt/core/solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
#ifndef OR_TOOLS_MATH_OPT_CORE_SOLVER_H_
#define OR_TOOLS_MATH_OPT_CORE_SOLVER_H_

#include <functional>
#include <memory>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "ortools/math_opt/callback.pb.h"
#include "ortools/math_opt/core/base_solver.h"
#include "ortools/math_opt/core/concurrent_calls_guard.h"
#include "ortools/math_opt/core/model_summary.h"
#include "ortools/math_opt/core/solver_interface.h"
Expand All @@ -29,10 +29,8 @@
#include "ortools/math_opt/model_update.pb.h"
#include "ortools/math_opt/parameters.pb.h"
#include "ortools/math_opt/result.pb.h"
#include "ortools/util/solve_interrupter.h"

namespace operations_research {
namespace math_opt {
namespace operations_research::math_opt {

// A solver for a given model and solver implementation.
//
Expand Down Expand Up @@ -65,102 +63,45 @@ namespace math_opt {
// CHECK_OK(second_solution.status());
// // Use the second_solution of the updated problem here.
//
class Solver {
class Solver : public BaseSolver {
public:
using InitArgs = SolverInterface::InitArgs;

// Callback function for messages callback sent by the solver.
//
// Each message represents a single output line from the solver, and each
// message does not contain any '\n' character in it.
//
// Thread-safety: a callback may be called concurrently from multiple
// threads. The users is expected to use proper synchronization primitives to
// deal with that.
using MessageCallback = SolverInterface::MessageCallback;

// Callback function type for MIP/LP callbacks.
using Callback = std::function<CallbackResultProto(const CallbackDataProto&)>;

// Arguments used when calling Solve() to solve the problem.
struct SolveArgs {
SolveParametersProto parameters;
ModelSolveParametersProto model_parameters;

// An optional callback for messages emitted by the solver.
//
// When set it enables the solver messages and ignores the `enable_output`
// in solve parameters; messages are redirected to the callback and not
// printed on stdout/stderr/logs anymore.
MessageCallback message_callback = nullptr;

CallbackRegistrationProto callback_registration;
Callback user_cb = nullptr;

// An optional interrupter that the solver can use to interrupt the solve
// early.
const SolveInterrupter* interrupter = nullptr;
};

// Arguments used when calling ComputeInfeasibleSubsystem().
struct ComputeInfeasibleSubsystemArgs {
SolveParametersProto parameters;

// An optional callback for messages emitted by the solver.
//
// When set it enables the solver messages and ignores the `enable_output`
// in solve parameters; messages are redirected to the callback and not
// printed on stdout/stderr/logs anymore.
MessageCallback message_callback = nullptr;

// An optional interrupter that the solver can use to interrupt the solve
// early.
const SolveInterrupter* interrupter = nullptr;
};

// A shortcut for calling Solver::New() and then Solver::Solve().
static absl::StatusOr<SolveResultProto> NonIncrementalSolve(
const ModelProto& model, SolverTypeProto solver_type,
const InitArgs& init_args, const SolveArgs& solve_args);

// A shortcut for calling Solver::New() and then
// Solver()::ComputeInfeasibleSubsystem()
static absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
NonIncrementalComputeInfeasibleSubsystem(
const ModelProto& model, SolverTypeProto solver_type,
const InitArgs& init_args,
const ComputeInfeasibleSubsystemArgs& compute_infeasible_subsystem_args);

// Builds a solver of the given type with the provided model and
// initialization parameters.
static absl::StatusOr<std::unique_ptr<Solver>> New(
SolverTypeProto solver_type, const ModelProto& model,
const InitArgs& arguments);

Solver(const Solver&) = delete;
Solver& operator=(const Solver&) = delete;
~Solver() override;

~Solver();
absl::StatusOr<SolveResultProto> Solve(const SolveArgs& arguments) override;

// Solves the current model (included all updates).
absl::StatusOr<SolveResultProto> Solve(const SolveArgs& arguments);

// Updates the model to solve and returns true, or returns false if this
// update is not supported by the underlying solver.
//
// A status error will be returned if the model_update is invalid or the
// underlying solver has an internal error.
// See BaseSolver::Update.
//
// When this function returns false, the Solver object is in a failed
// state. In that case the underlying SolverInterface implementation has been
// destroyed (this enables the caller to instantiate a new Solver without
// destroying the previous one first even if they use Gurobi with a single-use
// license).
absl::StatusOr<bool> Update(const ModelUpdateProto& model_update);
absl::StatusOr<bool> Update(ModelUpdateProto model_update) override;

// Computes an infeasible subsystem of `model`.
absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
ComputeInfeasibleSubsystem(const ComputeInfeasibleSubsystemArgs& arguments);

// A shortcut for calling Solver::New() and then
// Solver()::ComputeInfeasibleSubsystem()
static absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
NonIncrementalComputeInfeasibleSubsystem(
const ModelProto& model, SolverTypeProto solver_type,
const InitArgs& init_args,
const ComputeInfeasibleSubsystemArgs& compute_infeasible_subsystem_args);
ComputeInfeasibleSubsystem(
const ComputeInfeasibleSubsystemArgs& arguments) override;

private:
Solver(std::unique_ptr<SolverInterface> underlying_solver,
Expand Down Expand Up @@ -191,7 +132,6 @@ absl::Status ValidateInitArgs(const Solver::InitArgs& init_args,
SolverTypeProto solver_type);

} // namespace internal
} // namespace math_opt
} // namespace operations_research
} // namespace operations_research::math_opt

#endif // OR_TOOLS_MATH_OPT_CORE_SOLVER_H_
Loading

0 comments on commit 6dc3177

Please sign in to comment.