/// <summary>
        /// Method for positionate graph via DFS pass
        /// </summary>
        /// <param name="graph">Graph to positionate</param>
        /// <param name="vertex">Vertex to positionate</param>
        /// <param name="width">sreen width</param>
        /// <param name="height">screen height</param>
        private void PositionateDFS(ISentenceGraph graph, IDrawable vertex, int width, int height)
        {
            // positionate all edges of vertex
            foreach (var edge in graph[vertex])
            {
                // skip absolute edges for now
                if (edge is IAbsolutePositionateEdge && edge.Right == null)
                {
                    continue;
                }

                // Positionate dfs
                if (edge.Right != null && !edge.Right.IsPositioned)
                {
                    this.PositionateDFS(graph, edge.Right, width, height);
                }

                // Assign new free position to the right vertex
                if (edge.Right != null && !edge.Right.IsPositioned && !edge.Left.IsPositioned)
                {
                    edge.Right.Position = this.PositionHelper.GetEmptyPosition(edge.Right);
                }

                // Edge positioning itself
                edge.Positionate(width, height);
            }
        }
Beispiel #2
0
        private IProcessable ProcessElement(Noun noun, ISentenceGraph graph)
        {
            // if noun is subject, process this
            if (this.DependencyHelper.IsSubject(noun.DependencyType))
            {
                if (this.DrawableAdposition != null)
                {
                    noun.Process(this.DrawableAdposition, graph);
                    this.DrawableAdposition = null;
                }

                return(noun.Process(this, graph));
            }

            // if noun is object, save it as part of this verb, else save it for future
            if (this.DependencyHelper.IsObject(noun.DependencyType) && this.Object == null)
            {
                this.Object = noun;
            }
            else
            {
                this.DependingDrawables.Add(noun);
            }

            return(this);
        }
Beispiel #3
0
        private IProcessable ProcessElement(NounSet nounSet, ISentenceGraph graph)
        {
            // Check if it is subject
            if (this.DependencyHelper.IsSubject(nounSet.DependencyType))
            {
                if (this.DrawableAdposition != null)
                {
                    nounSet.Process(this.DrawableAdposition, graph);
                    this.DrawableAdposition = null;
                }

                return(nounSet.Process(this, graph));
            }

            // Check if it is object
            if (this.DependencyHelper.IsObject(nounSet.DependencyType) && this.Object == null)
            {
                this.Object = nounSet;
            }
            else
            {
                this.DependingDrawables.Add(nounSet);
            }

            return(this);
        }
Beispiel #4
0
        protected override IProcessable ProcessElement(IProcessable element, ISentenceGraph graph)
        {
            switch (element)
            {
            case Adjective adj: return(this.ProcessElement(adj, graph));

            case Noun noun: return(this.ProcessElement(noun, graph));

            case NounSet nounSet: return(this.ProcessElement(nounSet, graph));

            case Adposition adp: return(this.ProcessElement(adp, graph));

            case Numeral num: return(this.ProcessElement(num, graph));

            case Verb verb: return(this.ProcessElement(verb, graph));

            case Adverb adv: return(this.ProcessElement(adv, graph));

            case Coordination cor: return(this.ProcessCoordination(cor));

            default: break;
            }

            return(this);
        }
Beispiel #5
0
        public override IProcessable FinalizeProcessing(ISentenceGraph graph)
        {
            if (this.Image != null)
            {
                return(this);
            }

            this.GetImage();

            // If this is plural finalize wih noun set
            IPositionateEdge newEdge;

            if (this.IsPlural)
            {
                var finalizingElement = new NounSet(this.ElementFactory, this.EdgeFactory, this, NumberOfInstances);
                newEdge = this.EdgeFactory.Create(finalizingElement, this.Adpositions.SelectMany(a => a.GetAdpositions()).Select(a => a.ToString()).ToList());
                return(finalizingElement);
            }

            // Try to create new absolute edge
            newEdge = this.EdgeFactory.Create(this, this.Adpositions.SelectMany(a => a.GetAdpositions()).Select(a => a.ToString()).ToList());
            if (newEdge != null)
            {
                graph.AddEdge(newEdge);
                this.Adpositions.Clear();
            }

            // Scaling from accumulated scale
            this.Width  = (int)(this.Width * this.Scale);
            this.Height = (int)(this.Height * this.Scale);

            return(this);
        }
Beispiel #6
0
        private IProcessable ProcessElement(Numeral num, ISentenceGraph graph)
        {
            num.DependencyType    = this.DependencyType;
            this.DependingNumeral = num;

            return(this);
        }
Beispiel #7
0
        private IProcessable ProcessElement(NounSet nounSet, ISentenceGraph graph)
        {
            // If noun set is in coordination relation
            if (this.DependencyTypeHelper.IsConjuction(nounSet.DependencyType) &&
                this.CoordinationTypeHelper.IsMergingCoordination(this.CoordinationType))
            {
                // Try create edge between elements
                IPositionateEdge newEdge = this.EdgeFactory.Create(
                    this,
                    nounSet,
                    new List <string>(),
                    nounSet.Adpositions.SelectMany(a => a.GetAdpositions()).Select(a => a.ToString()).ToList(),
                    this.DependencyTypeHelper.IsSubject(nounSet.DependencyType)
                    );

                if (newEdge != null)
                {
                    nounSet.Adpositions.Clear();
                    graph.AddEdge(newEdge);
                    nounSet.FinalizeProcessing(graph);
                    return(this);
                }

                // If no edge exists merge them
                this.GetAllNouns();
                this.Nouns.AddRange(nounSet.GetAllNouns());
                nounSet.Nouns.Clear();
                graph.ReplaceVertex(this, nounSet);
                return(this);
            }

            // Part of this noun
            if (this.DependencyTypeHelper.IsCompound(nounSet.DependencyType) || this.DependencyTypeHelper.IsNounPhrase(nounSet.DependencyType) || this.DependencyTypeHelper.IsName(nounSet.DependencyType))
            {
                this.Nouns.ForEach(n => n.Process(nounSet, graph));
                graph.ReplaceVertex(this, nounSet);

                return(this);
            }

            // Return noun set if this is negated
            if (this.IsNegated && this.DependencyTypeHelper.IsObject(this.DependencyType))
            {
                return(nounSet);
            }

            // Processing relationship between noun set and this
            this.DrawableHelper.ProcessEdge(graph, this.EdgeFactory, this, nounSet, this.Adpositions, nounSet.Adpositions, this.DependencyTypeHelper.IsSubject(nounSet.DependencyType), () =>
            {
                // Add to extensions
                nounSet.DependencyType = "compound";
                this.Nouns.ForEach(n => n.Process(nounSet, graph));
            });

            // Finalize processed noun
            nounSet.FinalizeProcessing(graph);

            return(this);
        }
Beispiel #8
0
        private IProcessable ProcessElement(Verb verb, ISentenceGraph graph)
        {
            // Skip copula
            if (this.DependencyTypeHelper.IsCopula(verb.DependencyType))
            {
                return(this);
            }

            IProcessable processElement = this;

            // Process all depending drawables of the verb
            if (verb.DependingDrawables.Count != 0)
            {
                verb.DependingDrawables.ForEach(dd => processElement = processElement.Process(dd, graph));
                verb.DependingDrawables.Clear();
            }

            // Process all related actions
            verb.RelatedActions.ForEach(ra => processElement.Process(ra, graph));
            verb.RelatedActions.Clear();

            // Process non used adposition
            if (verb.DrawableAdposition != null)
            {
                processElement.Process(verb.DrawableAdposition, graph);
                verb.DrawableAdposition = null;
            }

            // Replace verb object in the graph
            if (verb.Object != null)
            {
                if (verb.Object is NounSet)
                {
                    ((NounSet)verb.Object).Nouns.ForEach(n =>
                    {
                        if (graph.Vertices.Contains(n))
                        {
                            graph.ReplaceVertex((IDrawable)processElement, n);
                        }
                    });
                }

                if (graph.Vertices.Contains((IDrawable)verb.Object))
                {
                    graph.ReplaceVertex((IDrawable)processElement, (IDrawable)verb.Object);
                }
            }

            // Process only non negated verbs
            if (!verb.IsNegated && processElement == this)
            {
                foreach (var noun in this.Nouns)
                {
                    noun.Process(verb, graph);
                }
            }

            return(processElement);
        }
Beispiel #9
0
        private IProcessable ProcessElement(Noun noun, ISentenceGraph graph)
        {
            // Process merging coordination type
            if (this.DependencyHelper.IsConjuction(noun.DependencyType) && this.CoordinationTypeHelper.IsMergingCoordination(this.CoordinationType))
            {
                // Try to create edge between elements
                IPositionateEdge newEdge = this.EdgeFactory.Create(
                    this,
                    noun,
                    new List <string>(),
                    noun.Adpositions.SelectMany(a => a.GetAdpositions()).Select(a => a.ToString()).ToList(),
                    this.DependencyHelper.IsSubject(noun.DependencyType)
                    );

                if (newEdge != null)
                {
                    noun.Adpositions.Clear();
                    graph.AddEdge(newEdge);
                    noun.FinalizeProcessing(graph);
                    return(this);
                }

                // If no edge was found create new noun set
                return(this.ElementFactory.Create(this, noun, graph));
            }

            // Part of noun phrase
            if (this.DependencyHelper.IsCompound(noun.DependencyType) || this.DependencyHelper.IsNounPhrase(noun.DependencyType) || this.DependencyHelper.IsName(noun.DependencyType))
            {
                this.Extensions.Add(noun);
                graph.ReplaceVertex(this, noun);

                return(this);
            }

            // Skip possessive relation
            if (this.DependencyHelper.IsPossesive(noun.DependencyType))
            {
                return(this);
            }

            // Return depending drawable if this is negated
            if (this.IsNegated && this.DependencyHelper.IsObject(this.DependencyType))
            {
                return(noun);
            }

            // Processing relationship between noun set and this
            this.DrawableHelper.ProcessEdge(graph, this.EdgeFactory, this, noun, this.Adpositions, noun.Adpositions, this.DependencyHelper.IsSubject(noun.DependencyType), () =>
            {
                // Add to extensions
                this.Extensions.Add(noun);
            });

            // Finalize processed noun
            noun.FinalizeProcessing(graph);

            return(this);
        }
        private IProcessable ProcessElement(Noun noun, ISentenceGraph graph)
        {
            if (this.DependencyHelper.IsCompound(noun.DependencyType) || this.DependencyHelper.IsNominalPossesive(noun.DependencyType))
            {
                noun.DependencyType = this.DependencyType;
            }

            return(noun.Process(this, graph));
        }
        protected sealed override IProcessable ProcessElement(Adjective adj, ISentenceGraph graph)
        {
            if (adj is FunctionalAdjective)
            {
                return(this);
            }

            return(base.ProcessElement(adj, graph));
        }
Beispiel #12
0
        private IProcessable ProcessElement(Adjective adj, ISentenceGraph graph)
        {
            // Let each noun process adjective
            foreach (var noun in this.Nouns)
            {
                noun.Process(adj, graph);
            }

            return(this);
        }
Beispiel #13
0
        private IProcessable ProcessElement(Adverb adv, ISentenceGraph graph)
        {
            // Let each noun process the adverb
            foreach (var noun in this.Nouns)
            {
                noun.Process(adv, graph);
            }

            return(this);
        }
        protected virtual IProcessable ProcessElement(Adjective adj, ISentenceGraph graph)
        {
            if (adj.CoordinationType != CoordinationType.AND)
            {
                return(this);
            }

            this.Extensions.Add(adj);
            return(this);
        }
Beispiel #15
0
        private IProcessable ProcessElement(Verb verb, ISentenceGraph graph)
        {
            // skip copula
            if (this.DependencyHelper.IsCopula(verb.DependencyType))
            {
                return(this);
            }

            IProcessable processElement = this;

            // Don't process negated verb
            if (!verb.IsNegated)
            {
                this.Actions.Add(verb);
            }

            // Process all depending drawables
            if (verb.DependingDrawables.Count != 0)
            {
                verb.DependingDrawables.ForEach(dd => processElement = processElement.Process(dd, graph));
                verb.DependingDrawables.Clear();
            }

            // Process all related actions
            verb.RelatedActions.ForEach(ra => processElement.Process(ra, graph));
            verb.RelatedActions.Clear();

            // Process unprocessed adposition
            if (verb.DrawableAdposition != null)
            {
                processElement.Process(verb.DrawableAdposition, graph);
            }

            // Replace verb object in the graph
            if (verb.Object != null)
            {
                if (verb.Object is NounSet ns)
                {
                    ns.Nouns.ForEach(n =>
                    {
                        if (graph.Vertices.Contains(n))
                        {
                            graph.ReplaceVertex((IDrawable)processElement, n);
                        }
                    });
                }

                if (graph.Vertices.Contains((IDrawable)verb.Object))
                {
                    graph.ReplaceVertex((IDrawable)processElement, (IDrawable)verb.Object);
                }
            }

            return(processElement);
        }
Beispiel #16
0
        private IProcessable ProcessElement <T>(T drawable, ISentenceGraph graph) where T : IProcessable
        {
            if (this.DependencyHelper.IsAppositional(this.DependencyType))
            {
                this.DependingDrawables.Add(drawable);
                return(this);
            }

            this.DependencyType = "nummod";
            return(drawable.Process(this, graph));
        }
Beispiel #17
0
        private IProcessable ProcessElement(Adjective adj, ISentenceGraph graph)
        {
            // Use the scale of the functional adjective
            if (adj is FunctionalAdjective funcAdj)
            {
                this.Scale *= funcAdj.Scale;
            }

            this.Extensions.Add(adj);
            return(this);
        }
Beispiel #18
0
        /// <summary>
        /// Interface overriden method
        /// </summary>
        /// <param name="element">Element to process</param>
        /// <param name="graph">Sentence graph</param>
        /// <returns>Processed element</returns>
        public IProcessable Process(IProcessable element, ISentenceGraph graph)
        {
            if (element == null)
            {
                return(this);
            }

            if (element is Negation)
            {
                return(this.ProcessNegation((Negation)element));
            }

            if (element.IsNegated && !(this is Noun) && !(element is Verb))
            {
                if (element is IDrawable drawable)
                {
                    graph.RemoveVertex(drawable, true);
                }

                return(this);
            }

            if (this.IsNegated && this.DependencyHelper.IsSubject(element.DependencyType))
            {
                if (this is Verb verb)
                {
                    this.ProcessableHelper.RemoveVerbFromGraph(verb, graph);
                }

                return(element);
            }


            if (!this.CoordinationTypeHelper.IsAllowedCoordination(this.CoordinationType) && this.DependencyHelper.IsConjuction(element.DependencyType))
            {
                this.CoordinationType = CoordinationType.AND;
                if (element is IDrawable drawable)
                {
                    graph.RemoveVertex(drawable, true);
                }

                if (element is Verb verb)
                {
                    this.ProcessableHelper.RemoveVerbFromGraph(verb, graph);
                }

                return(this);
            }

            var returnElement = this.ProcessElement(element, graph);

            return(returnElement.IsNegated && returnElement != this ? this : returnElement);
        }
Beispiel #19
0
        private IProcessable ProcessElement(Adposition adp, ISentenceGraph graph)
        {
            if (adp.GetAdpositions().Count() == 1)
            {
                this.Adpositions.Add(adp);
            }
            else
            {
                this.Adpositions.Insert(0, adp);
            }

            return(this);
        }
Beispiel #20
0
        private IProcessable ProcessElement(Adjective adj, ISentenceGraph graph)
        {
            if (adj.Id > this.Id)
            {
                this.ExtensionsAfter.Add(adj);
            }
            else
            {
                this.ExtensionsBefore.Add(adj);
            }

            return(this);
        }
Beispiel #21
0
        private IProcessable ProcessElement(Verb verb, ISentenceGraph graph)
        {
            this.RelatedActions.Add(verb);

            // Add depending drawables from dependency tree to future processing
            if (verb.DependingDrawables.Count != 0)
            {
                this.DependingDrawables.AddRange(verb.DependingDrawables);
                verb.DependingDrawables.Clear();
            }

            return(this);
        }
Beispiel #22
0
        private IProcessable ProcessElement(Numeral num, ISentenceGraph graph)
        {
            IProcessable processElem = this;

            num.DependingDrawables.ForEach(dd => processElem = processElem.Process(dd, graph));
            num.DependingActions.ForEach(da => processElem   = processElem.Process(da, graph));
            this.Process(num.DependingNumeral, graph);

            // Process appositional
            if (this.DependencyHelper.IsAppositional(num.DependencyType))
            {
                return(processElem);
            }

            // Process numeral expressing part of noun phrase
            if (this.DependencyHelper.IsNounPhrase(this.DependencyType) || this.DependencyHelper.IsCompound(this.DependencyType))
            {
                this.Extensions.Add(num);
                return(processElem);
            }

            // We don't process time
            if (this.DependencyHelper.IsTime(num.DependencyType))
            {
                return(processElem);
            }

            // Add extension if numeral is not modifying number of instances
            if (!this.DependencyHelper.IsNumeralModifier(num.DependencyType))
            {
                if (num.Id > this.Id)
                {
                    this.Suffixes.Add(num);
                }
                else
                {
                    this.Extensions.Add(num);
                }

                return(processElem);
            }

            // no need to create noun set
            if (num.GetValue() <= 1)
            {
                return(processElem);
            }

            // Create new noun with given number of values
            return(new NounSet(this.ElementFactory, this.EdgeFactory, this, num.GetValue()));
        }
Beispiel #23
0
        private IProcessable ProcessElement(Adposition adp, ISentenceGraph graph)
        {
            // Check if adposition is part of this verb
            if (this.DependencyHelper.IsCompound(adp.DependencyType))
            {
                this.PhrasePart = adp;
            }
            else
            {
                this.DrawableAdposition = adp;
            }

            return(this);
        }
Beispiel #24
0
        /// <summary>
        /// Removes verbs and all its dependencies from graph
        /// </summary>
        /// <param name="verb">Verb to remove</param>
        /// <param name="graph">Graph</param>
        public void RemoveVerbFromGraph(Verb verb, ISentenceGraph graph)
        {
            // Remove object
            if (verb.Object != null)
            {
                graph.RemoveVertex((IDrawable)verb.Object, true);
            }

            // Remove depending drawables from graph
            verb.DependingDrawables.ForEach(dd => graph.RemoveVertex((IDrawable)dd, true));

            // Remove recursively
            verb.RelatedActions.ForEach(ra => RemoveVerbFromGraph(ra, graph));
        }
        /// <summary>
        /// Postionates all absolute edges
        /// </summary>
        /// <param name="graph">Sentence graph</param>
        /// <param name="width">Max width</param>
        /// <param name="height">Max height</param>
        /// <returns>Absolute groups of vertices</returns>
        private Dictionary <IDrawable, PlaceType> PositionateAbsoluteEdges(ISentenceGraph graph, int width, int height)
        {
            var dict = new Dictionary <IDrawable, PlaceType>();

            // positionate all absolute relations
            foreach (IAbsolutePositionateEdge absEdge in graph.Edges.Where(edge => edge is IAbsolutePositionateEdge && edge.Right == null))
            {
                absEdge.Positionate(width, height);
                if (!dict.ContainsKey(absEdge.Left))
                {
                    dict.Add(absEdge.Left, absEdge.Type);
                }
            }

            return(dict);
        }
        /// <summary>
        /// Method for resolving conflicts between vetices
        /// </summary>
        /// <param name="graph">Graph to resolve</param>
        /// <param name="width">screen width</param>
        /// <param name="height">screen height</param>
        private void ResolveConflicts(ISentenceGraph graph, int width, int height)
        {
            // positionate absolute edges and get absolute groups
            var  absoluteGroups        = this.PositionateAbsoluteEdges(graph, width, height);
            bool isPositionedCorrectly = false;

            // While there is some conflict, check positions
            while (!isPositionedCorrectly)
            {
                isPositionedCorrectly = true;
                foreach (var vertex in graph.Groups)
                {
                    // skip unpositioned vertices
                    if (!vertex.IsPositioned)
                    {
                        continue;
                    }

                    // check conflicts ---> repositionate(move)
                    var conflicts = this.ConflictHelper.GetConflictingVertices(vertex, graph.Groups);

                    // continue if no conflicts were found
                    if (conflicts.Count == 0)
                    {
                        continue;
                    }

                    // -------resolve conflicts--------
                    isPositionedCorrectly = false;
                    foreach (var conflictVertex in conflicts)
                    {
                        // resolve absolute conflicts
                        if (vertex.IsFixed)
                        {
                            this.ConflictHelper.ResolveAbsoluteConflict(vertex, conflictVertex, absoluteGroups[vertex], absoluteGroups[conflictVertex], width, height);
                        }
                        // move conflicts to the right
                        else
                        {
                            conflictVertex.Position += this.ConflictHelper.GetShift(vertex, conflictVertex);
                        }
                    }
                }
            }
        }
Beispiel #27
0
        private IProcessable ProcessElement(Adverb adv, ISentenceGraph graph)
        {
            // check if it is part of this verb
            if (this.DependencyHelper.IsCompound(adv.DependencyType))
            {
                this.PhrasePart = adv;
            }
            else if (adv.Id > this.Id)
            {
                this.ExtensionsAfter.Add(adv);
            }
            else
            {
                this.ExtensionsBefore.Add(adv);
            }

            return(this);
        }
        /// <summary>
        /// Method that positionates all edges of graph
        /// </summary>
        /// <param name="graph">Graph to positionate</param>
        /// <param name="width">screen width</param>
        /// <param name="height">screen height</param>
        private void PositionateAllEdges(ISentenceGraph graph, int width, int height)
        {
            // positionate all vertices
            foreach (var vertex in graph.Vertices)
            {
                // skip if already positioned
                if (vertex.IsPositioned)
                {
                    continue;
                }

                // positionate via DFS
                this.PositionateDFS(graph, vertex, width, height);

                // assign random new position if vertex is independent
                if (vertex.Position == null)
                {
                    vertex.Position = this.PositionHelper.GetEmptyPosition(vertex);
                }
            }

            // Getting final vertex "groups" after positioning
            HashSet <IDrawable> groups = new HashSet <IDrawable>();

            foreach (var vertex in graph.Vertices)
            {
                // If vertex is group as itself, insert it into groups.
                if (vertex.Group == null)
                {
                    groups.Add(vertex);
                    continue;
                }

                // add only unique and valid groups.
                if (vertex.Group.IsValid && !groups.Contains(vertex.Group))
                {
                    groups.Add(vertex.Group);
                }
            }

            // Set groups of graph
            graph.Groups = groups;
        }
        protected sealed override IProcessable ProcessElement(Adverb adv, ISentenceGraph graph)
        {
            // Go through all adverbs and find modifier ones
            adv.ExtendingAdverbs.SelectMany(advs => advs.ExtendingAdverbs).Select(ad =>
            {
                if (this.ChangeScale(ad))
                {
                    this.Extensions.Add(ad);
                }

                return(ad);
            }).ToList();

            if (this.ChangeScale(adv))
            {
                this.Extensions.Add(adv);
            }

            return(this);
        }
Beispiel #30
0
        /// <summary>
        /// Processes two drawable elements.
        /// Tries to create edge between them.
        /// Also checks other options.
        /// </summary>
        /// <param name="graph">Sentence graph</param>
        /// <param name="left">left vertex</param>
        /// <param name="right">right vertex</param>
        /// <param name="leftAdpositions">left adpositions</param>
        /// <param name="rightAdpositions">right adpositions</param>
        /// <param name="finalAction">Actual to do if "of" is found</param>
        /// <param name="isRightSubject">Flag if right vertex is subject</param>
        /// <returns>New edge or null</returns>
        public bool ProcessEdge(ISentenceGraph graph, IEdgeFactory edgeFactory, IDrawable left, IDrawable right, List <Adposition> leftAdpositions, List <Adposition> rightAdpositions, bool isRightSubject, Action finalAction)
        {
            // Get adpositions from adpositions combinations
            List <string>    leftAdp  = leftAdpositions.SelectMany(a => a.GetAdpositions()).Select(a => a.ToString()).ToList();
            List <string>    rightAdp = rightAdpositions.SelectMany(a => a.GetAdpositions()).Select(a => a.ToString()).ToList();
            IPositionateEdge edge     = edgeFactory.Create(left, right, leftAdp, rightAdp, isRightSubject);

            // Clear used adpositions
            if (leftAdp.Count == 0)
            {
                leftAdpositions.Clear();
            }
            if (rightAdp.Count == 0)
            {
                rightAdpositions.Clear();
            }

            // Add only not null edge
            if (edge != null)
            {
                graph.AddEdge(edge);
            }
            else
            {
                // Check if drawable contains "of" -> then it is an extension of this
                if (rightAdpositions.Count == 1 && rightAdpositions[0].ToString() == "of")
                {
                    // Replace vertex in graph
                    graph.ReplaceVertex(left, right);

                    // Run final action
                    finalAction();
                }
                else
                {
                    graph.AddVertex(right);
                }
            }

            return(edge != null);
        }