public DirectedEdgedGraph <T, E> Inverse() { DirectedEdgedGraph <T, E> result = new DirectedEdgedGraph <T, E>(Comparer); foreach (var item in Nodes) { result.Add(item); foreach (var related in RelatedTo(item)) { result.Add(related.Key, item, related.Value); } } return(result); }
public DirectedEdgedGraph <T, E> WhereEdges(Func <Edge <T, E>, bool> condition) { DirectedEdgedGraph <T, E> result = new DirectedEdgedGraph <T, E>(Comparer); foreach (var item in Nodes) { result.Add(item, RelatedTo(item).Where(to => condition(new Edge <T, E>(item, to.Key, to.Value)))); } return(result); }
public static E GetOrCreate <T, E>(this DirectedEdgedGraph <T, E> graph, T from, T to) where E : new() { var dic = graph.TryRelatedTo(from); if (dic != null) { return(dic.GetOrCreate(to)); } E newEdge = new E(); graph.Add(from, to, newEdge); return(newEdge); }
public DirectedEdgedGraph <T, E> WhereEdges(Func <Edge <T, E>, bool> condition, bool keepAllNodes) { if (keepAllNodes) { DirectedEdgedGraph <T, E> result = new DirectedEdgedGraph <T, E>(Comparer); foreach (var item in Nodes) { result.Add(item, RelatedTo(item).Where(to => condition(new Edge <T, E>(item, to.Key, to.Value)))); } return(result); } else { DirectedEdgedGraph <T, E> result = new DirectedEdgedGraph <T, E>(Comparer); foreach (var e in EdgesWithValue.Where(condition)) { result.Add(e.From, e.To, e.Value); } return(result); } }
/// <summary> /// A simple but effective linear-time heuristic constructs a vertex ordering, /// just as in the topological sort heuristic above, and deletes any arc going from right to left. /// /// This heuristic builds up the ordering from the outside in based on the in- and out-degrees of each vertex. /// - Any vertex of in-degree 0 is a source and can be placed first in the ordering. /// - Any vertex of out-degree 0 is a sink and can be placed last in the ordering, again without violating any constraints. /// - If not, we find the vertex with the maximum difference between in- and out-degree, /// and place it on the side of the permutation that will salvage the greatest number of constraints. /// Delete any vertex from the DAG after positioning it and repeat until the graph is empty. /// </summary> /// <returns></returns> public DirectedEdgedGraph <T, E> FeedbackEdgeSet() { DirectedEdgedGraph <T, E> result = new DirectedEdgedGraph <T, E>(Comparer); DirectedEdgedGraph <T, E> clone = this.Clone(); DirectedEdgedGraph <T, E> inv = this.Inverse(); HashSet <T> head = new HashSet <T>(); // for sources HashSet <T> tail = new HashSet <T>(); // for sinks while (clone.Count > 0) { var sinks = clone.Sinks(); if (sinks.Count() != 0) { foreach (var sink in sinks) { DirectedEdgedGraph <T, E> .RemoveFullNodeSymetric(clone, inv, sink); tail.Add(sink); } continue; } var sources = inv.Sinks(); if (sources.Count() != 0) { foreach (var source in sources) { DirectedEdgedGraph <T, E> .RemoveFullNodeSymetric(clone, inv, source); head.Add(source); } continue; } Func <T, int> fanInOut = n => clone.RelatedTo(n).Count() - inv.RelatedTo(n).Count(); MinMax <T> mm = clone.WithMinMaxPair(fanInOut); if (fanInOut(mm.Max) > -fanInOut(mm.Min)) { T node = mm.Max; foreach (var n in inv.RelatedTo(node)) { result.Add(n.Key, node, n.Value); } DirectedEdgedGraph <T, E> .RemoveFullNodeSymetric(clone, inv, node); head.Add(node); } else { T node = mm.Min; foreach (var n in clone.RelatedTo(node)) { result.Add(node, n.Key, n.Value); } DirectedEdgedGraph <T, E> .RemoveFullNodeSymetric(clone, inv, node); head.Add(node); } } return(result); }