Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
incremental_solver.h
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// IWYU pragma: private, include "ortools/math_opt/cpp/math_opt.h"
15// IWYU pragma: friend "ortools/math_opt/cpp/.*"
16
17#ifndef OR_TOOLS_MATH_OPT_CPP_INCREMENTAL_SOLVER_H_
18#define OR_TOOLS_MATH_OPT_CPP_INCREMENTAL_SOLVER_H_
19
20#include "absl/status/statusor.h"
23#include "ortools/math_opt/cpp/parameters.h" // IWYU pragma: export
24#include "ortools/math_opt/cpp/solve_arguments.h" // IWYU pragma: export
25#include "ortools/math_opt/cpp/solve_result.h" // IWYU pragma: export
26#include "ortools/math_opt/cpp/update_result.h" // IWYU pragma: export
27
29
30// Interface for incrementally solving of a model.
31//
32// This is a feature for advance users. Most users should only use the
33// non-incremental Solve(), SubprocessSolve(),... functions.
34//
35// Here incremental means that the we try to reuse the existing underlying
36// solver internals between each solve. There is no guarantee though that the
37// solver supports all possible model changes. Hence there is not guarantee that
38// performances will be improved when using this class; this is solver
39// dependent. Typically LPs have more to gain from incremental solve than
40// MIPs. In both cases, even if the solver supports the model changes,
41// incremental solve may actually be slower.
42//
43// Implementation of this interface are returned by factories that can be found
44// next to non-incremental solve functions. See NewIncrementalSolver() in
45// solve.h and NewSubprocessIncrementalSolver() in subprocess_solve.h for
46// example.
47//
48// Those factories function instantiates the solver, setup it from the current
49// state of the Model and register on it to listen to changes. Calling Solve()
50// will update the underlying solver with latest model changes and solve this
51// model.
52//
53// Usage:
54// Model model = ...;
55// ASSIGN_OR_RETURN(
56// const std::unique_ptr<IncrementalSolver> incremental_solve,
57// NewIncrementalSolver(&model, SolverType::kXxx));
58//
59// ASSIGN_OR_RETURN(const SolveResult result1, incremental_solve->Solve());
60//
61// model.AddVariable(...);
62// ...
63//
64// ASSIGN_OR_RETURN(const SolveResult result2, incremental_solve->Solve());
65//
66// ...
67//
68// Lifecycle: The IncrementalSolver is only keeping a std::weak_ref on Model's
69// internal data and thus it returns an error if Update() or Solve() are called
70// after the Model has been destroyed. It is fine to destroy the
71// IncrementalSolver after the associated Model though.
72//
73// Thread-safety: The New(), Solve() and Update() methods must not be called
74// while modifying the Model() (adding variables...). The user is expected to
75// use proper synchronization primitives to serialize changes to the model and
76// the use of this object. Note though that it is safe to call methods from
77// different IncrementalSolver instances on the same Model concurrently. Same
78// for calling factories of IncrementalSolver. The destructor is thread-safe and
79// can be called even during a modification of the Model.
80//
81// There is no problem calling SolveWithoutUpdate() concurrently on different
82// instances of IncrementalSolver or while the model is being modified (unless
83// of course the underlying solver itself is not thread-safe and can only be
84// called from a single-thread).
85//
86// Note that Solve(), Update() and SolveWithoutUpdate() are not reentrant so
87// they should not be called concurrently on the same instance of
88// IncrementalSolver.
89//
90// Some solvers may add more restrictions regarding threading. Please see
91// SolverType::kXxx documentation for details.
93 public:
94 IncrementalSolver() = default;
97 virtual ~IncrementalSolver() = default;
98
99 // Updates the underlying solver with latest model changes and runs the solve.
100 //
101 // A Status error will be returned if inputs are invalid or there is an
102 // unexpected failure in an underlying solver or for some internal math_opt
103 // errors. Otherwise, check SolveResult::termination.reason to see if an
104 // optimal solution was found.
105 //
106 // Memory model: the returned SolveResult owns its own memory (for solutions,
107 // solve stats, etc.), EXPECT for a pointer back to the model. As a result:
108 // * Keep the model alive to access SolveResult,
109 // * Avoid unnecessarily copying SolveResult,
110 // * The result is generally accessible after mutating this, but some care
111 // is needed if variables or linear constraints are added or deleted.
112 //
113 // See callback.h for documentation on arguments.callback and
114 // arguments.callback_registration.
115 virtual absl::StatusOr<SolveResult> Solve(
116 const SolveArguments& arguments) = 0;
117 absl::StatusOr<SolveResult> Solve() { return Solve({}); }
118
119 // Updates the underlying solver with latest model changes and runs the
120 // computation.
121 //
122 // Same as Solve() but compute the infeasible subsystem.
123 virtual absl::StatusOr<ComputeInfeasibleSubsystemResult>
125 const ComputeInfeasibleSubsystemArguments& arguments) = 0;
126 absl::StatusOr<ComputeInfeasibleSubsystemResult>
130
131 // Updates the model to solve.
132 //
133 // This is an advanced API, most users should use Solve() above that does the
134 // update and before calling the solver. Calling this function is only useful
135 // for users that want to access to update data or users that need to use
136 // SolveWithoutUpdate() (which should not be common).
137 //
138 // The returned value indicates if the update was possible or if the solver
139 // had to be recreated from scratch (which may happen when the solver does not
140 // support this specific update or any update at all). It also contains the
141 // attempted update data.
142 //
143 // A status error will be returned if the underlying solver has an internal
144 // error.
145 virtual absl::StatusOr<UpdateResult> Update() = 0;
146
147 // Same as Solve() but does not update the underlying solver with the latest
148 // changes to the model.
149 //
150 // This is an advanced API, most users should use Solve().
151 virtual absl::StatusOr<SolveResult> SolveWithoutUpdate(
152 const SolveArguments& arguments) const = 0;
153 absl::StatusOr<SolveResult> SolveWithoutUpdate() const {
154 return SolveWithoutUpdate({});
155 }
156
157 // Same as ComputeInfeasibleSubsystem() but does not update the underlying
158 // solver with the latest changes to the model.
159 //
160 // This is an advanced API, most users should use
161 // ComputeInfeasibleSubsystem().
162 virtual absl::StatusOr<ComputeInfeasibleSubsystemResult>
164 const ComputeInfeasibleSubsystemArguments& arguments) const = 0;
165 absl::StatusOr<ComputeInfeasibleSubsystemResult>
169
170 // Returns the underlying solver used.
171 virtual SolverType solver_type() const = 0;
172};
173
174} // namespace operations_research::math_opt
175
176#endif // OR_TOOLS_MATH_OPT_CPP_INCREMENTAL_SOLVER_H_
virtual absl::StatusOr< SolveResult > SolveWithoutUpdate(const SolveArguments &arguments) const =0
absl::StatusOr< SolveResult > SolveWithoutUpdate() const
virtual absl::StatusOr< SolveResult > Solve(const SolveArguments &arguments)=0
absl::StatusOr< ComputeInfeasibleSubsystemResult > ComputeInfeasibleSubsystemWithoutUpdate() const
virtual absl::StatusOr< UpdateResult > Update()=0
virtual absl::StatusOr< ComputeInfeasibleSubsystemResult > ComputeInfeasibleSubsystemWithoutUpdate(const ComputeInfeasibleSubsystemArguments &arguments) const =0
IncrementalSolver(const IncrementalSolver &)=delete
absl::StatusOr< ComputeInfeasibleSubsystemResult > ComputeInfeasibleSubsystem()
virtual SolverType solver_type() const =0
Returns the underlying solver used.
virtual absl::StatusOr< ComputeInfeasibleSubsystemResult > ComputeInfeasibleSubsystem(const ComputeInfeasibleSubsystemArguments &arguments)=0
IncrementalSolver & operator=(const IncrementalSolver &)=delete
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
SolverType
The solvers supported by MathOpt.
Definition parameters.h:42
Arguments passed to ComputeInfeasibleSubsystem() to control the solver.