internal SequenceSearchState(SequenceSearchState <T> other, IMinimalDAGNode <T> nextNode, int stepDirection) { Index = other.Index + stepDirection; CurrentNode = nextNode; //PreviousNode = other.CurrentNode; ValuePool = new List <T>(other.ValuePool); //.ToList(); UsedValues = new Dictionary <int, T>(other.UsedValues); // { Index, CurrentNode.GetValue() }; this.WildCardIndices = new List <int>(other.WildCardIndices); this.WildCardCount = other.WildCardCount; }
/// <summary> /// Performs the actual DFS search, finding all <see cref="SequenceSearchState{T}"/> that match the <see cref="Pattern{char}"/> /// </summary> /// <param name="searchState"></param> /// <param name="nextRelativeSelector"></param> /// <param name="sequenceBoundaries"></param> /// <param name="stepDirection"></param> /// <returns></returns> private IEnumerable <SequenceSearchState <char> > DepthFirstSequenceSearch(SequenceSearchState <char> searchState, Func <IMinimalDAGNode <char>, IEnumerable <IMinimalDAGNode <char> > > nextRelativeSelector, HashSet <int> sequenceBoundaries, int stepDirection, Pattern <char> pattern) { Stack <SequenceSearchState <char> > ToCheck = new Stack <SequenceSearchState <char> >(); ToCheck.Push(searchState); //NB: recursive searches with yield return build a new iterator for every method call. //A recursive solution would therefore have performance impact (as well as risking stackoverflow in some very deep pattern). while (ToCheck.Count > 0) { var CurrentState = ToCheck.Pop(); var Relatives = nextRelativeSelector(CurrentState.CurrentNode); int NextIndex = CurrentState.Index + stepDirection; if (IsOutOfBounds(NextIndex, pattern)) { if (IsBoundaryCollision(CurrentState, nextRelativeSelector, sequenceBoundaries, pattern)) { yield return(CurrentState); } } else { bool IsEnd = false; List <IMinimalDAGNode <char> > OtherRelatives = new List <IMinimalDAGNode <char> >(); foreach (var Relative in Relatives) { if (_dawg.IsDAGBoundary(Relative)) { IsEnd = true; } else { OtherRelatives.Add(Relative); } } if (IsEnd && IsIndexValidBoundary(CurrentState.Index, sequenceBoundaries)) { yield return(CurrentState); } var NextStates = GetNextStates(CurrentState, OtherRelatives, NextIndex, stepDirection, pattern); foreach (var nextState in NextStates) { ToCheck.Push(nextState); } } } }
/// <summary> /// Searches the <see cref="IMinimalDAG{T}"/> from a starting point in a single direction, returning sequences /// that match the valid <see cref="Pattern{T}"/> /// </summary> /// <param name="searchState"></param> /// <param name="nextRelativeSelector"></param> /// <param name="sequenceBoundaries"></param> /// <param name="stepDirection"></param> /// <returns></returns> private IEnumerable <SequenceSearchState <char> > SequenceSearch(SequenceSearchState <char> searchState, Func <IMinimalDAGNode <char>, IEnumerable <IMinimalDAGNode <char> > > nextRelativeSelector, HashSet <int> sequenceBoundaries, int stepDirection, Pattern <char> pattern) { if (IsBoundaryCollision(searchState, nextRelativeSelector, sequenceBoundaries, pattern)) { yield return(searchState); } else { foreach (var sequence in DepthFirstSequenceSearch(searchState, nextRelativeSelector, sequenceBoundaries, stepDirection, pattern)) { yield return(sequence); } } }
/// <summary> /// Checks for a collision with an edge of the search space. In the event of a collision, returns all valid affixes terminating /// at that point, then breaks. /// </summary> /// <param name="searchState"></param> /// <param name="nextRelativeSelector"></param> /// <param name="sequenceBoundaries"></param> /// <returns></returns> private bool IsBoundaryCollision(SequenceSearchState <char> searchState, Func <IMinimalDAGNode <char>, IEnumerable <IMinimalDAGNode <char> > > nextRelativeSelector, HashSet <int> sequenceBoundaries, Pattern <char> pattern) { if (searchState.Index == 0 || searchState.Index == pattern.SearchSpace.Length - 1) //if we're at the edge of the searchspace { if (sequenceBoundaries.Contains(searchState.Index)) //and the edge of the searchspace is a valid boundary (we're heading out of bounds) { foreach (var Relative in nextRelativeSelector(searchState.CurrentNode)) { if (_dawg.IsDAGBoundary(Relative)) { return(true); } } } } return(false); }
internal SequenceSearchState(SequenceSearchState <T> other, IMinimalDAGNode <T> nextNode, int stepDirection, T UsedValue, bool wildCard) { this.WildCardIndices = new List <int>(other.WildCardIndices); Index = other.Index + stepDirection; CurrentNode = nextNode; UsedValues = new Dictionary <int, T>(other.UsedValues); //doesn't make sense: //if(!UsedValues.ContainsKey(Index)) UsedValues.Add(Index, UsedValue); // PreviousNode = other.CurrentNode; if (wildCard) { WildCardCount = other.WildCardCount - 1; ValuePool = new List <T>(other.ValuePool); WildCardIndices.Add(Index); } else { WildCardCount = other.WildCardCount; ValuePool = other.ValuePool.ExceptFirst(UsedValue).ToList(); } }
/// <summary> /// From the current state, find all the next states that are valid. /// </summary> /// <param name="currentState"></param> /// <param name="relatives"></param> /// <param name="nextLocation"></param> /// <param name="stepDirection"></param> /// <returns></returns> private List <SequenceSearchState <char> > GetNextStates(SequenceSearchState <char> currentState, List <IMinimalDAGNode <char> > relatives, int nextLocation, int stepDirection, Pattern <char> pattern) { List <SequenceSearchState <char> > NextStates = new List <SequenceSearchState <char> >(); char concrete; if (pattern.TryGetConcreteValue(nextLocation, out concrete)) { foreach (var relative in relatives.Where(x => concrete.Equals(x.Value))) { NextStates.Add(new SequenceSearchState <char>(currentState, relative, stepDirection)); } } else { var ValidValues = pattern.SearchSpace[nextLocation]; var ValidNext = relatives; if (ValidValues != null)// && !ValidValues.Contains(pattern.EmptyValue)) { ValidNext = relatives.Where(x => ValidValues.Contains(x.Value)).ToList(); } foreach (var next in ValidNext) { if (currentState.ValuePool.Contains(next.Value)) { NextStates.Add(new SequenceSearchState <char>(currentState, next, stepDirection, next.Value, false)); } if (currentState.WildCardCount > 0) { NextStates.Add(new SequenceSearchState <char>(currentState, next, stepDirection, next.Value, true)); } } } return(NextStates); }