예제 #1
0
        /// <summary>
        /// Initializes and incrementally creates a minimal <see cref="IMinimalDAGNode{T}"/> from a sorted collection of sequences of values.
        /// </summary>
        /// <typeparam name="T">The type to be arranged as a <see cref="IMinimalDAG{T}"/></typeparam>
        /// <param name="sortedSequences">The ascending ordered sequences of <typeparamref name="T"/> to be minimized.</param>
        /// <param name="nodeFactory">Factory for <see cref="IMinimalDAGNode{T}"/> creation</param>
        public MinimalDAG(IEnumerable <IEnumerable <T> > sortedSequences, IMinimalDAGNodeFactory <T> nodeFactory)//, T sourceValue = default(T), T sinkValue = default(T))
        {
            _registrationBySuffix = new HashSet <IMinimalDAGNode <T> >();
            _dagNodeFactory       = nodeFactory ?? new MinimalDAGNodeFactory <T>();
            _nodes  = new Dictionary <Guid, IMinimalDAGNode <T> >();
            _source = _dagNodeFactory.CreateNode(default(T), Guid.NewGuid());
            _sink   = _dagNodeFactory.CreateNode(default(T), Guid.NewGuid());
            _source.Children.Add(_sink.ID);

            _registrationBySuffix.Add(_sink);
            _sink.IsSuffixRegistered = true;

            var LastSequence = new List <T>()
            {
                _sink.Value
            }.DefaultIfEmpty();                                                //lazy but simple fix

            foreach (IEnumerable <T> Sequence in sortedSequences)
            {
                AddNextOrderedSequence(Sequence, LastSequence);
                LastSequence = Sequence;
            }
            HandleExistingSuffixes(_source);
            BuildParentLinks();
            BuildNodesByValueDictionary();
        }
예제 #2
0
        /// <summary>
        /// Compares the most recently added <see cref="IMinimalDAGNode{T}"/> (and children) to the existing nodes,
        /// merging any matches.
        /// </summary>
        /// <param name="parent"></param>
        private void HandleExistingSuffixes(IMinimalDAGNode <T> parent)
        {
            var NewestChild = GetLastChild(parent);

            if (NewestChild != default(IMinimalDAGNode <T>))
            {
                if (!NewestChild.IsSuffixRegistered)
                {
                    if (NewestChild.Children.Count > 0)
                    {
                        HandleExistingSuffixes(NewestChild);
                    }
                    else
                    {
                        NewestChild.Children.Add(_sink.ID);
                    }

                    IMinimalDAGNode <T> EquivalentNode;

                    if (_registrationBySuffix.TryGetValue(NewestChild, out EquivalentNode))
                    {
                        parent.Children.Remove(NewestChild.ID);

                        _nodes.Remove(NewestChild.ID);
                        parent.Children.Add(EquivalentNode.ID);
                    }
                    else
                    {
                        _registrationBySuffix.Add(NewestChild);
                        NewestChild.IsSuffixRegistered = true;
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Returns the last (ie most recently added) child <see cref="IMinimalDAGNode{T}"/> linked to the selected node.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private IMinimalDAGNode <T> GetLastChild(IMinimalDAGNode <T> node)
        {
            IMinimalDAGNode <T> ReturnValue = null;

            _nodes.TryGetValue(node.Children.Last(), out ReturnValue);
            return(ReturnValue);
            //return Nodes[node.GetChildIDs().Last()];
        }
 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;
 }
 internal SequenceSearchState(IMinimalDAGNode <T> currentNode, IEnumerable <T> valuePool, int index, int wildCardCount = 0,
                              Dictionary <int, T> usedValues = null, List <int> wildCardIndices = null)
 {
     WildCardIndices = wildCardIndices ?? new List <int>();
     CurrentNode     = currentNode;
     ValuePool       = valuePool;
     Index           = index;
     UsedValues      = (usedValues == null)?  new Dictionary <int, T>(): new Dictionary <int, T>(usedValues);//new List<T>();
     WildCardCount   = wildCardCount;
 }
예제 #6
0
 public MinimalDAG(IMinimalDAGNode <T> _source, IMinimalDAGNode <T> _sink, IMinimalDAGNodeFactory <T> _dagNodeFactory,
                   Dictionary <Guid, IMinimalDAGNode <T> > _nodes, Dictionary <T, List <Guid> > _nodeIDsByValue, HashSet <Guid> _nodeIDsWithNullValue)
 {
     this._sink                 = _sink;
     this._source               = _source;
     this._nodeIDsByValue       = _nodeIDsByValue;
     this._nodes                = _nodes;
     this._dagNodeFactory       = _dagNodeFactory;
     this._nodeIDsWithNullValue = _nodeIDsWithNullValue;
 }
예제 #7
0
        /// <summary>
        /// Returns a boolean representing whether <paramref name="possibleBoundaryNode"/> is a sink or source <see cref="IMinimalDAGNode{T}"/>.
        /// </summary>
        /// <param name="possibleBoundaryNode"></param>
        /// <returns></returns>
        public bool IsDAGBoundary(IMinimalDAGNode <T> possibleBoundaryNode)
        {
            var ID = possibleBoundaryNode.ID;

            if (ID == _sink.ID || ID == _source.ID)
            {
                return(true);
            }
            return(false);
        }
예제 #8
0
        /// <summary>
        /// Adds a sequence of child <see cref="IMinimalDAGNode{T}"/> nodes to the selected <see cref="IMinimalDAGNode{T}"/>
        /// - the addition of a new sequence of values to the DAG.
        /// </summary>
        /// <param name="currentNode">The parent node to add the sequence to.</param>
        /// <param name="currentSuffix">A new sequence of nodes.</param>
        private void AddSuffix(IMinimalDAGNode <T> currentNode, IEnumerable <T> currentSuffix)
        {
            var CurrentNode = currentNode;

            foreach (var value in currentSuffix)
            {
                var NewNode = _dagNodeFactory.CreateNode(value, Guid.NewGuid());
                RecordNode(NewNode);
                CurrentNode.Children.Add(NewNode.ID);
                CurrentNode = NewNode;
            }
            CurrentNode.Children.Add(_sink.ID);
        }
예제 #9
0
        /// <summary>
        /// Returns the <see cref="IMinimalDAGNode{T}"/> children of <paramref name="node"/>
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public IEnumerable <IMinimalDAGNode <T> > GetChildren(IMinimalDAGNode <T> node)
        {
            IMinimalDAGNode <T> value;

            foreach (var ID in node.Children)
            {
                if (_nodes.TryGetValue(ID, out value))
                {
                    yield return(value);
                }
                else if (ID == _sink.ID)
                {
                    yield return(_sink);
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Returns the <see cref="IMinimalDAGNode{T}"/> parents of <paramref name="node"/>
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public IEnumerable <IMinimalDAGNode <T> > GetParents(IMinimalDAGNode <T> node)
        {
            IMinimalDAGNode <T> value;

            foreach (var ID in node.Parents)
            {
                if (_nodes.TryGetValue(ID, out value))
                {
                    yield return(value);
                }
                else if (ID == _source.ID)
                {
                    yield return(_source);
                }
            }
            //yield return _nodes[ID];
        }
        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();
            }
        }
예제 #12
0
        /// <summary>
        /// Traverses the graph from a specified node, returning all sequences with that parent.
        /// </summary>
        /// <param name="root">The starting point of the sequence search.</param>
        /// <param name="partial">The current sequence/s being traversed</param>
        /// <returns></returns>
        private List <List <T> > GetSequences(IMinimalDAGNode <T> root, List <T> partial)
        {
            List <List <T> > Values = new List <List <T> >();

            if (root.ID.Equals(_sink.ID))
            {
                Values.Add(partial);
                return(Values);
            }
            List <T> Sequence = new List <T>(partial)
            {
                root.Value
            };

            foreach (var Child in GetChildren(root))
            {
                foreach (var Subsequence in GetSequences(Child, Sequence))
                {
                    Values.Add(Subsequence);
                }
            }
            return(Values);
        }
예제 #13
0
 /// <summary>
 /// Records a <see cref="IMinimalDAGNode{T}"/> into the register of nodes.
 /// </summary>
 /// <param name="toRecord"></param>
 private void RecordNode(IMinimalDAGNode <T> toRecord)
 {
     _nodes[toRecord.ID] = toRecord;
 }