Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
CpSolver.cs
Go to the documentation of this file.
1// Copyright 2010-2025 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
14using System;
15using System.Collections.Generic;
16using System.Runtime.CompilerServices;
17
18namespace Google.OrTools.Sat
19{
29public sealed class CpSolver : IDisposable
30{
31 private LogCallback? _log_callback;
32 private BestBoundCallback? _best_bound_callback;
33 private SolveWrapper? _solve_wrapper;
34 private Queue<Term> _terms;
35 private bool _disposed = false;
36
37 public double ObjectiveValue => Response!.ObjectiveValue;
38
39 public double BestObjectiveBound => Response!.BestObjectiveBound;
40
41 public string? StringParameters { get; set; }
42
43 public CpSolverResponse? Response { get; private set; }
44
45 public CpSolverStatus Solve(CpModel model, SolutionCallback? cb = null)
46 {
47 // Setup search.
48 CreateSolveWrapper();
49 if (StringParameters is not null)
50 {
51 _solve_wrapper!.SetStringParameters(StringParameters);
52 }
53
54 if (_log_callback is not null)
55 {
56 _solve_wrapper!.AddLogCallbackFromClass(_log_callback);
57 }
58
59 if (_best_bound_callback is not null)
60 {
61 _solve_wrapper!.AddBestBoundCallbackFromClass(_best_bound_callback);
62 }
63
64 if (cb is not null)
65 {
66 _solve_wrapper!.AddSolutionCallback(cb);
67 }
68
69 Response = _solve_wrapper!.Solve(model.Model);
70
71 // Cleanup search.
72 if (cb is not null)
73 {
74 _solve_wrapper.ClearSolutionCallback(cb);
75 }
76
77 ReleaseSolveWrapper();
78
79 return Response.Status;
80 }
81
83 [MethodImpl(MethodImplOptions.Synchronized)]
84 public void StopSearch() => _solve_wrapper?.StopSearch();
85
87
89 {
90 _log_callback?.Dispose();
91 _log_callback = new LogCallbackDelegate(del);
92 }
93
94 public void ClearLogCallback()
95 {
96 _log_callback?.Dispose();
97 _log_callback = null;
98 }
99
101 {
102 _best_bound_callback?.Dispose();
103 _best_bound_callback = new BestBoundCallbackDelegate(del);
104 }
105
107 {
108 _best_bound_callback?.Dispose();
109 _best_bound_callback = null;
110 }
111
112 public long Value(IntVar intVar)
113 {
114 var index = intVar.GetIndex();
115 var value = index >= 0 ? Response!.Solution[index] : -Response!.Solution[-index - 1];
116 return value;
117 }
118
119 public long Value(LinearExpr e)
120 {
121 long constant = 0;
122 long coefficient = 1;
123 var expr = e;
124 if (_terms is null)
125 {
126 _terms = new Queue<Term>();
127 }
128 else
129 {
130 _terms.Clear();
131 }
132
133 do
134 {
135 switch (expr)
136 {
137 case LinearExprBuilder a:
138 constant += coefficient * a.Offset;
139 if (coefficient == 1)
140 {
141 foreach (var sub in a.Terms)
142 {
143 _terms.Enqueue(sub);
144 }
145 }
146 else
147 {
148 foreach (var sub in a.Terms)
149 {
150 _terms.Enqueue(new Term(sub.expr, sub.coefficient * coefficient));
151 }
152 }
153
154 break;
155 case IntVar intVar:
156 var index = intVar.GetIndex();
157 var value = index >= 0 ? Response!.Solution[index] : -Response!.Solution[-index - 1];
158 constant += coefficient * value;
159 break;
160 case NotBoolVar:
161 throw new ArgumentException("Cannot evaluate a literal in an integer expression.");
162 default:
163 throw new ArgumentException("Cannot evaluate '" + expr + "' in an integer expression");
164 }
165
166 if (!_terms.TryDequeue(out var term))
167 {
168 break;
169 }
170
171 expr = term.expr;
172 coefficient = term.coefficient;
173 } while (true);
174
175 return constant;
176 }
177
178 public bool BooleanValue(ILiteral literal)
179 {
180 if (literal is BoolVar || literal is NotBoolVar)
181 {
182 var index = literal.GetIndex();
183 if (index >= 0)
184 {
185 return Response!.Solution[index] != 0;
186 }
187 else
188 {
189 return Response!.Solution[-index - 1] == 0;
190 }
191 }
192 else
193 {
194 throw new ArgumentException("Cannot evaluate '" + literal.ToString() + "' as a boolean literal");
195 }
196 }
197
198 public long NumBranches() => Response!.NumBranches;
199
200 public long NumConflicts() => Response!.NumConflicts;
201
202 public double WallTime() => Response!.WallTime;
203
204 public IList<int> SufficientAssumptionsForInfeasibility() => Response!.SufficientAssumptionsForInfeasibility;
205
206 public string SolutionInfo() => Response!.SolutionInfo;
207
208 public void Dispose()
209 {
210 if (_disposed)
211 {
212 return;
213 }
214
215 _best_bound_callback?.Dispose();
216 _log_callback?.Dispose();
217 ReleaseSolveWrapper();
218 _disposed = true;
219 }
220
221 [MethodImpl(MethodImplOptions.Synchronized)]
222 private void CreateSolveWrapper()
223 {
224 _solve_wrapper?.Dispose();
225 _solve_wrapper = new SolveWrapper();
226 }
227
228 [MethodImpl(MethodImplOptions.Synchronized)]
229 private void ReleaseSolveWrapper()
230 {
231 _solve_wrapper?.Dispose();
232 _solve_wrapper = null;
233 }
234}
235
236class LogCallbackDelegate : LogCallback
237{
238 private readonly StringToVoidDelegate _delegate_;
239
240 public LogCallbackDelegate(StringToVoidDelegate del) => _delegate_ = del;
241
242 public override void NewMessage(string message) => _delegate_(message);
243}
244
245class BestBoundCallbackDelegate : BestBoundCallback
246{
247 private readonly DoubleToVoidDelegate _delegate;
248
249 public BestBoundCallbackDelegate(DoubleToVoidDelegate del) => _delegate = del;
250
251 public override void NewBestBound(double bound) => _delegate(bound);
252}
253
254} // namespace Google.OrTools.Sat
override void NewBestBound(double bound)
BestBoundCallbackDelegate(DoubleToVoidDelegate del)
Holds a Boolean variable.
Wrapper class around the cp_model proto.
Definition CpModel.cs:24
CpModelProto Model
Getters.
Definition CpModel.cs:41
static string SolverResponseStats(Google.OrTools.Sat.CpSolverResponse response)
The response returned by a solver trying to solve a CpModelProto.
Wrapper around the SAT solver.
Definition CpSolver.cs:30
long Value(IntVar intVar)
Definition CpSolver.cs:112
void SetBestBoundCallback(DoubleToVoidDelegate del)
Definition CpSolver.cs:100
IList< int > SufficientAssumptionsForInfeasibility()
void StopSearch()
Stops the search asynchronously.
CpSolverResponse? Response
Definition CpSolver.cs:43
CpSolverStatus Solve(CpModel model, SolutionCallback? cb=null)
Definition CpSolver.cs:45
bool BooleanValue(ILiteral literal)
Definition CpSolver.cs:178
long Value(LinearExpr e)
Definition CpSolver.cs:119
void SetLogCallback(StringToVoidDelegate del)
Definition CpSolver.cs:88
Holds a integer variable with a discrete domain.
A builder class for linear expressions.
Holds a linear expression: sum (ai * xi) + b.
LogCallbackDelegate(StringToVoidDelegate del)
override void NewMessage(string message)
Holds a Boolean variable or its negation.
int GetIndex()
Returns the logical index of the literal.
CpSolverStatus
The status returned by a solver trying to solve a CpModelProto.
delegate void DoubleToVoidDelegate(double bound)
Used to wrap best bound callbacks (std.function<void(double>)
delegate void StringToVoidDelegate(string message)
Used to wrap log callbacks (std.function<void(const std.string&>)
Holds a term (expression * coefficient)