public SolverState(Nonogram nonogram, TimeSpan?timeout, bool useMultipleCores, CancellationTokenSource cancellationTokenSource) { Nonogram = nonogram ?? throw new ArgumentNullException(nameof(nonogram)); _cancellationTokenSource = cancellationTokenSource ?? throw new ArgumentNullException(nameof(cancellationTokenSource)); CancellationToken = _cancellationTokenSource.Token; Timeout = timeout; UseMultipleCores = useMultipleCores; Stopwatch = new Stopwatch(); Tiles = new TilesCollection(nonogram.RowCount, nonogram.ColumnCount); }
/// <summary> /// Try to solve the given <see cref="Nonogram"/>. /// </summary> /// <param name="nonogram">The <see cref="Nonogram"/> to solve.</param> /// <param name="timeout">If given, we'll abort our search for a solution if it takes too long.</param> /// <param name="cancellationTokenSource"> /// If you want to control cancellation yourself, pass in a <see cref="CancellationTokenSource"/>. /// Note that if you also set a <paramref name="timeout"/>, the Solver will call <see cref="CancellationTokenSource.Cancel"/> if the timeout expires. /// </param> /// <param name="useMultipleCores">If set to true, we try to parallelize solving the <see cref="Nonogram"/>, otherwise we only use 1 CPU core.</param> /// <returns>A <see cref="Solution"/> to the <see cref="Nonogram"/>, although it may not be a successful one.</returns> public static Solution Solve(Nonogram nonogram, TimeSpan?timeout = null, CancellationTokenSource cancellationTokenSource = null, bool useMultipleCores = true) { bool disposeCts = cancellationTokenSource == null; try { cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource(); var state = new SolverState(nonogram, timeout, useMultipleCores, cancellationTokenSource); if (!state.PopulatePermutations()) { return(state.CreateSolution(SolveResult.Cancelled)); } var stepResult = ProcessStepResult.KeepGoing; while (stepResult == ProcessStepResult.KeepGoing) { state.Stopwatch.Restart(); stepResult = Step(state.RowPermutations, state.ColumnPermutations, state.CancellationToken); state.StepCount++; if (stepResult == ProcessStepResult.Unsolvable) { return(state.CreateSolution(SolveResult.Unsolvable)); } state.Stopwatch.Stop(); state.UpdateElapsed(); if (state.HasHitTimeout || state.CancellationToken.IsCancellationRequested) { state.CancelToken(); return(state.CreateSolution(SolveResult.Cancelled)); } } return(state.CreateSolution(SolveResult.Success)); } finally { if (disposeCts && cancellationTokenSource != null) { cancellationTokenSource.Dispose(); } } }