public IEnumerable <TEdge> GetIncomingEdges(TVertex vertex)
 {
     if (!IncomingEdges.ContainsKey(vertex))
     {
         return(Enumerable.Empty <TEdge>());
     }
     return(IncomingEdges[vertex].SelectMany(v => v.Value));
 }
Exemple #2
0
 /// <summary>
 /// Gets the incoming edges to a key, regardless if the node has been added or not.
 /// </summary>
 public List <TKey> GetIncoming(TKey key)
 {
     if (!IncomingEdges.TryGetValue(key, out HashSet <TKey> edges))
     {
         return(new List <TKey>());
     }
     return(edges.ToList());
 }
 /// <summary>
 /// Removes all edges from this vertex and removes it from the graph.
 /// </summary>
 /// <returns>This</returns>
 public Vertex <T> Remove()
 {
     IncomingEdges.ForEach(x => x.Remove());
     OutgoingEdges.ForEach(x => x.Remove());
     IncomingEdges.Clear();
     OutgoingEdges.Clear();
     Graph.Vertices.Remove(this);
     return(this);
 }
Exemple #4
0
        public void RemoveZeroDegreeNodes()
        {
            var toDelete = OutgoingEdges.Keys.Where(vertex => !OutgoingEdges[vertex].Any() && !IncomingEdges[vertex].Any());

            foreach (var vertex in toDelete)
            {
                OutgoingEdges.Remove(vertex);
                IncomingEdges.Remove(vertex);
            }
        }
Exemple #5
0
 private IDictionary <TVertex, IList <TEdge> > GetIncomingEdgesMap(TVertex vertex)
 {
     if (IncomingEdges.TryGetValue(vertex, out var map))
     {
         return(map);
     }
     map = InnerMap;
     OutgoingEdges[vertex] = InnerMap;
     IncomingEdges[vertex] = map;
     return(map);
 }
Exemple #6
0
        public void AddEdge(ref FlowEdge edge)
        {
            if (Index == edge.From)
            {
                OutcomingEdges.Add(edge);
            }

            if (Index == edge.To)
            {
                IncomingEdges.Add(edge);
            }
        }
 /// <summary>
 /// Removes the edge.
 /// </summary>
 /// <param name="edge">The edge.</param>
 /// <returns>This</returns>
 public Vertex <T> RemoveEdge(Edge <T> edge)
 {
     if (edge.Sink == this)
     {
         IncomingEdges.Remove(edge);
     }
     else
     {
         OutgoingEdges.Remove(edge);
     }
     return(this);
 }
Exemple #8
0
 /// <summary>
 /// Removes all edges from this vertex and removes it from the graph.
 /// </summary>
 /// <returns>This</returns>
 public Vertex <T> Remove()
 {
     for (var x = 0; x < IncomingEdges.Count; ++x)
     {
         IncomingEdges[x].Remove();
     }
     for (var x = 0; x < OutgoingEdges.Count; ++x)
     {
         OutgoingEdges[x].Remove();
     }
     IncomingEdges.Clear();
     OutgoingEdges.Clear();
     Graph.Vertices.Remove(this);
     return(this);
 }
Exemple #9
0
 public bool RemoveVertex(TVertex vertex)
 {
     if (!OutgoingEdges.ContainsKey(vertex))
     {
         return(false);
     }
     foreach (var other in OutgoingEdges[vertex].Keys)
     {
         IncomingEdges[other].Remove(vertex);
     }
     foreach (var other in IncomingEdges[vertex].Keys)
     {
         OutgoingEdges[other].Remove(vertex);
     }
     OutgoingEdges.Remove(vertex);
     IncomingEdges.Remove(vertex);
     return(true);
 }
Exemple #10
0
 public bool RemoveEdges(TVertex source, TVertex dest)
 {
     if (!OutgoingEdges.ContainsKey(source))
     {
         return(false);
     }
     if (!IncomingEdges.ContainsKey(dest))
     {
         return(false);
     }
     if (!OutgoingEdges[source].ContainsKey(dest))
     {
         return(false);
     }
     OutgoingEdges[source].Remove(dest);
     IncomingEdges[dest].Remove(source);
     return(true);
 }
Exemple #11
0
 private void AddEdges(TKey key, IList <TKey> outgoing)
 {
     OutgoingEdges.Add(key, new HashSet <TKey>(outgoing));
     foreach (var dest in outgoing)
     {
         if (!IncomingEdges.TryGetValue(dest, out HashSet <TKey> incoming))
         {
             IncomingEdges[dest] = new HashSet <TKey> {
                 key
             }
         }
         ;
         else
         {
             incoming.Add(key);
         }
     }
 }
Exemple #12
0
        public bool SearchIncomingEdges(Edge e, out Edge eli, out Edge eri)
        {
            if (IncomingEdges.SearchLeftRight(e, out eli, out eri))
            {
                return(true);
            }

            // Try to mimic a cyclical edge list
            if (eli == null)
            {
                eli = IncomingEdges.Last;
            }
            if (eri == null)
            {
                eri = IncomingEdges.First;
            }

            return(false);
        }
Exemple #13
0
        public bool RemoveEdge(TVertex source, TVertex dest, TEdge data)
        {
            if (!OutgoingEdges.ContainsKey(source))
            {
                return(false);
            }
            if (!IncomingEdges.ContainsKey(dest))
            {
                return(false);
            }
            if (!OutgoingEdges[source].ContainsKey(dest))
            {
                return(false);
            }

            bool foundOut = OutgoingEdges.ContainsKey(source) && OutgoingEdges[source].ContainsKey(dest) && OutgoingEdges[source][dest].Remove(data);
            bool foundIn  = IncomingEdges.ContainsKey(dest) && IncomingEdges[dest].ContainsKey(source) && IncomingEdges[dest][source].Remove(data);

            if (foundOut && !foundIn)
            {
                throw new Exception("Edge found in outgoing but not incoming"); // TODO: Specialized Exception
            }
            if (foundIn && !foundOut)
            {
                throw new Exception("Edge found in incoming but not outgoing"); // TODO: Specialized Exception
            }
            if (OutgoingEdges.ContainsKey(source) && (!OutgoingEdges[source].ContainsKey(dest) || OutgoingEdges[source][dest].Count == 0))
            {
                OutgoingEdges[source].Remove(dest);
            }
            if (IncomingEdges.ContainsKey(dest) && (!IncomingEdges[dest].ContainsKey(source) || IncomingEdges[dest][source].Count == 0))
            {
                IncomingEdges[dest].Remove(source);
            }

            return(foundOut);
        }
Exemple #14
0
        /// <summary>
        /// Checks if adding the node causes a cycle.
        /// </summary>
        public Boolean CausesCycle(TKey key, IList <TKey> outgoing)
        {
            if (outgoing.Contains(key))
            {
                return(true); // Self cycle
            }
            if (!IncomingEdges.TryGetValue(key, out HashSet <TKey> incoming) || incoming.Count == 0)
            {
                return(false); // No incoming edges, so we can't have a cycle.
            }
            // If a path exists from any outgoing edge to any incoming edge, adding the node will cause a cycle.
            foreach (TKey start in outgoing)
            {
                foreach (TKey end in incoming)
                {
                    if (PathExists(start, end))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemple #15
0
 /// <summary>
 /// Creates a shallow copy of the graph, referencing the same keys and data as the original.
 /// </summary>
 /// <returns>A shallow copy of the original.</returns>
 public Graph <TKey, TData> Clone() => new Graph <TKey, TData>
 (
     new Dictionary <TKey, TData>(Data),
     IncomingEdges.ToDictionary(kvp => kvp.Key, kvp => new HashSet <TKey>(kvp.Value)),
     OutgoingEdges.ToDictionary(kvp => kvp.Key, kvp => new HashSet <TKey>(kvp.Value))
 );
 public void Clear()
 {
     IncomingEdges.Clear();
     OutgoingEdges.Clear();
 }
 public IEnumerable <TVertex> GetParents(TVertex vertex)
 => IncomingEdges.TryGetValue(vertex, out var parentMap)
         ? parentMap.Keys
         : Enumerable.Empty <TVertex>();
 public bool Remove(DirectedEdge <T, DirectedVertex <T> > edge)
 {
     return(IncomingEdges.Remove(edge) |
            OutgoingEdges.Remove(edge));
 }
 public void AddIncoming <TV>(DirectedEdge <T, TV> edge) where TV : DirectedVertex <T>
 {
     IncomingEdges.Add((IEdge <T, DirectedVertex <T> >)edge);
 }
Exemple #20
0
        /// <summary>
        /// Returns the nodes topologically sorted into layers. Nodes with no outgoing edges are in the first layer,
        /// while nodes that only point to nodes in the first layer are in the second layer, and so on. Any node that
        /// points to a node that has not been added to the graph is considered detached.
        /// </summary>
        /// <returns>A tuple containing a list of layers and a list of detached keys.</returns>
        public (List <List <TKey> > layers, List <TKey> detached) TopologicalSort()
        {
            // This method could probably be optimized significantly.
            // Now that I know it's called a topological sort, could use Kahn's algorithm.
            // However, we'll still need to take into account detached nodes where the nodes they point
            // to don't actually exist.

            List <List <TKey> > layers = new List <List <TKey> > {
                new List <TKey>()
            };
            List <TKey> detached = new List <TKey>();

            foreach (var kvp in OutgoingEdges)
            {
                TKey           key          = kvp.Key;
                HashSet <TKey> destinations = OutgoingEdges[key];
                if (OutgoingEdges[key].Count == 0)
                {
                    layers[0].Add(key); // If a key has no outgoing edges, it's added to the first layer
                }
                else if (destinations.Any(dest => !OutgoingEdges.ContainsKey(dest)))
                {
                    detached.Add(key); // If a key has any outgoing edges that are not in the graph, it is considered detached.
                }
            }

            HashSet <TKey> satisfiedKeys   = new HashSet <TKey>(layers[0]);
            HashSet <TKey> unsatisfiedKeys = new HashSet <TKey>();

            while (layers[layers.Count - 1].Count > 0)
            {
                IEnumerable <TKey> candidates =
                    layers[layers.Count - 1]
                    .SelectMany(previous => IncomingEdges.ContainsKey(previous) ? IncomingEdges[previous] : new HashSet <TKey>())
                    .Where(key => OutgoingEdges.ContainsKey(key))
                    .Concat(unsatisfiedKeys)
                    .Distinct();

                unsatisfiedKeys.Clear();

                List <TKey> currentLevel = new List <TKey>();
                foreach (TKey candidate in candidates)
                {
                    Boolean satisfied = true;
                    foreach (TKey outgoing in OutgoingEdges[candidate])
                    {
                        // Check if each of the outgoing keys have been set already.
                        if (satisfiedKeys.Contains(outgoing))
                        {
                            continue;
                        }

                        // If not, then the candidate gets bumped up to the next level.
                        satisfied = false;
                        break;
                    }

                    if (!satisfied)
                    {
                        unsatisfiedKeys.Add(candidate);
                        continue;
                    }

                    currentLevel.Add(candidate);
                }

                layers.Add(currentLevel);
                foreach (var key in currentLevel)
                {
                    satisfiedKeys.Add(key);
                }
            }

            layers.RemoveAt(layers.Count - 1);
            detached.AddRange(unsatisfiedKeys);
            return(layers, detached);
        }