25 private readonly Func<LotSizingSolutionVerificationService>
26 _verificationServiceFactory;
47 Func<LotSizingSolutionVerificationService>
48 verificationServiceFactory)
50 _verificationServiceFactory =
51 verificationServiceFactory ??
52 throw new ArgumentNullException(
53 nameof(verificationServiceFactory));
66 IEnumerable<SolutionVerificationBatchCandidate> candidates,
68 CancellationToken cancellationToken =
default)
88 public async Task<SolutionVerificationBatchResult>
VerifyAsync(
89 IEnumerable<SolutionVerificationBatchCandidate> candidates,
91 IProgress<SolutionVerificationBatchProgress>? progress,
92 CancellationToken cancellationToken =
default)
94 ArgumentNullException.ThrowIfNull(candidates);
101 cancellationToken.ThrowIfCancellationRequested();
104 MaterializeAndValidateCandidates(candidates);
108 totalCandidateCount: materializedCandidates.Length,
109 completedCandidateCount: 0,
112 if (materializedCandidates.Length == 0)
125 materializedCandidates.Length];
127 int completedCandidateCount =
130 var parallelOptions =
135 MaxDegreeOfParallelism =
136 options.MaxDegreeOfParallelism
139 await Parallel.ForEachAsync(
142 materializedCandidates.Length),
144 async (index, token) =>
147 materializedCandidates[index];
150 await VerifyCandidateAsync(
155 .ConfigureAwait(
false);
161 Interlocked.Increment(
162 ref completedCandidateCount);
166 materializedCandidates.Length,
170 .ConfigureAwait(
false);
172 cancellationToken.ThrowIfCancellationRequested();
175 BuildCheckSummary(results);
180 Array.AsReadOnly(results),
186 private static void ReportProgress(
187 IProgress<SolutionVerificationBatchProgress>? progress,
188 int totalCandidateCount,
189 int completedCandidateCount,
195 TotalCandidateCount =
197 CompletedCandidateCount =
198 completedCandidateCount,
199 LastCompletedCandidateIndex =
200 lastItem?.
Index ?? -1,
201 LastCompletedCandidateKey =
203 LastExecutionSucceeded =
205 LastCandidateIsValid =
212 private async Task<SolutionVerificationBatchItemResult>
213 VerifyCandidateAsync(
215 SolutionVerificationBatchCandidate candidate,
217 CancellationToken cancellationToken)
221 cancellationToken.ThrowIfCancellationRequested();
224 _verificationServiceFactory() ??
225 throw new InvalidOperationException(
226 "The verification-service factory returned null.");
229 CloneVerificationOptions(
230 verificationOptions);
233 candidate.Kind
switch
235 SolutionVerificationBatchCandidateKind.StandaloneSolution =>
238 candidate.Solution ??
239 throw new InvalidOperationException(
240 "The standalone batch candidate has no solution."),
243 .ConfigureAwait(
false),
245 SolutionVerificationBatchCandidateKind.KnownResult =>
248 candidate.KnownResult ??
249 throw new InvalidOperationException(
250 "The known-result batch candidate has no known result."),
253 .ConfigureAwait(
false),
256 throw new InvalidOperationException(
257 "The batch candidate kind is not supported.")
260 cancellationToken.ThrowIfCancellationRequested();
262 return new SolutionVerificationBatchItemResult
267 candidate.CandidateKey,
269 candidate.CandidateName,
281 catch (OperationCanceledException)
282 when (cancellationToken.IsCancellationRequested)
286 catch (Exception exception)
288 return new SolutionVerificationBatchItemResult
293 candidate.CandidateKey,
295 candidate.CandidateName,
300 FailureExceptionType =
301 exception.GetType().FullName ??
302 exception.GetType().Name,
309 private static SolutionVerificationBatchCandidate[]
310 MaterializeAndValidateCandidates(
311 IEnumerable<SolutionVerificationBatchCandidate> candidates)
313 SolutionVerificationBatchCandidate[] materialized =
314 candidates.ToArray();
317 index < materialized.Length;
320 if (materialized[index] is
null)
322 throw new ArgumentException(
323 $
"The candidate at index {index} is null.",
328 string? duplicateKey =
332 candidate.CandidateKey,
333 StringComparer.Ordinal)
338 .OrderBy(key => key, StringComparer.Ordinal)
341 if (duplicateKey is not
null)
343 throw new ArgumentException(
344 $
"The candidate key '{duplicateKey}' occurs more than once. " +
345 "Batch candidate keys must be unique.",
352 private static SolutionVerificationOptions CloneVerificationOptions(
353 SolutionVerificationOptions source)
355 return new SolutionVerificationOptions
357 ApplyToSolutionEvaluation =
359 UpdateKnownResultFeasibility =
361 PromoteFullyVerifiedKnownResult =
373 private static SolutionCheckOptions CloneCheckOptions(
374 SolutionCheckOptions source)
376 return new SolutionCheckOptions
380 FeasibilityTolerance =
384 IntegralityTolerance =
386 ObjectiveAbsoluteTolerance =
388 ObjectiveRelativeTolerance =
390 ReportedObjectiveValueOverride =
392 IgnoreDisabledConstraints =
394 ContinueAfterStructuralErrors =
395 source.ContinueAfterStructuralErrors
399 private static SolutionCheckBatchSummary BuildCheckSummary(
400 IReadOnlyList<SolutionVerificationBatchItemResult> results)
403 new SolutionCheckBatchAggregator();
406 SolutionVerificationBatchItemResult item
409 if (!item.ExecutionSucceeded ||
410 item.VerificationResult is
null)
417 item.VerificationResult.CheckResult,
421 return aggregator.BuildSummary();