/// <summary> /// Runs a search. /// </summary> /// <param name="startState">The state that the search will start from</param> /// <param name="maxDepth">The search will be terminated after maxDepth</param> /// <param name="cancellationToken">Used to cancel the search</param> public SearchResult Search(IDeterministicState startState, int maxDepth, CancellationToken cancellationToken) { if (StateDefinesDepth && CacheMode != CacheMode.NoCache && CacheKeyType != CacheKeyType.StateOnly) { throw new MinMaxSearchException($"If {nameof(StateDefinesDepth)} the cache key should be of type {CacheKeyType.StateOnly}"); } if (!startState.GetNeighbors().Any()) { throw new NoNeighborsException("start state has no neighbors " + startState); } if (maxDepth < 1) { throw new ArgumentException($"{nameof(maxDepth)} must be at least 1. Was {maxDepth}"); } if (SkipEvaluationForFirstNodeSingleNeighbor && startState.GetNeighbors().Count() == 1) { return(new SearchResult(0, startState, true, true, false)); } var searchContext = new SearchContext(maxDepth, 0, cancellationToken); var searchWorker = new SearchWorker(CreateSearchOptions(), GetThreadManager(maxDepth), cacheManagerFactory()); var stopwatch = new Stopwatch(); stopwatch.Start(); var result = searchWorker.Evaluate(startState, searchContext); stopwatch.Stop(); result.StateSequence.Reverse(); result.StateSequence.RemoveAt(0); // Removing the top node will make the result "nicer" return(new SearchResult(result, stopwatch.Elapsed, maxDepth, !cancellationToken.IsCancellationRequested)); }
private Task <SearchResult> Evaluate(IDeterministicState startState, SearchContext searchContext, IDictionary <IState, double> storedStates, IState state) { var taskResult = storedStates != null && storedStates.ContainsKey(state) ? Task.FromResult(new SearchResult(storedStates[state], state)) : threadManager.Invoke(() => { var actualStartState = startState is ProbablisticStateWrapper wrapper ? (IState)wrapper.InnerState : startState; return(searchWorker.Evaluate(state, searchContext.CloneAndAddState(actualStartState))); }, searchContext.CurrentDepth); return(taskResult); }