Example #1
0
        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);
        }
Example #2
0
        /// <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();
                }
            }
        }