public void SimpleCycle() { var graph = new MutableDirectedGraph(); NodeId a = graph.CreateNode(); NodeId b = graph.CreateNode(); NodeId c = graph.CreateNode(); NodeId d = graph.CreateNode(); NodeId e = graph.CreateNode(); NodeId f = graph.CreateNode(); graph.AddEdge(a, b); graph.AddEdge(b, c); graph.AddEdge(c, b); // Cycle-forming backedge (violates topo order). graph.AddEdge(d, e); graph.AddEdge(e, f); XAssert.IsTrue(graph.IsReachableFrom(a, b), "Shouldn't visit the backedge"); XAssert.IsTrue(graph.IsReachableFrom(a, c), "Shouldn't visit the backedge"); try { // Note that to fail, we need a > e here due to a fast-path for 'unreachable' // that doesn't look at any edges. graph.IsReachableFrom(a, f); // Fails since it should find the backedge c -> b } catch (BuildXLException) { return; } XAssert.Fail("Expected a failure due to a topological order violation"); }
/// <summary> /// Creates a test graph. /// There are light edges between nodes 0 - 1, 1 - 2, and 2 - 0. /// There are heavy edges between 0 - 1 and 1 - 3 /// </summary> private static void CreateGraphWithLightEdges(out MutableDirectedGraph graph, out NodeId[] nodes) { graph = new MutableDirectedGraph(); XAssert.AreEqual(graph.NodeCount, 0); XAssert.AreEqual(graph.EdgeCount, 0); // Test creation. nodes = new NodeId[4]; for (int i = 0; i < nodes.Length; ++i) { nodes[i] = graph.CreateNode(); } XAssert.AreEqual(graph.NodeCount, nodes.Length); XAssert.AreEqual(graph.EdgeCount, 0); foreach (NodeId t in nodes) { XAssert.IsTrue(graph.ContainsNode(t)); XAssert.IsTrue(graph.IsSourceNode(t)); XAssert.IsTrue(graph.IsSinkNode(t)); } graph.AddEdge(nodes[0], nodes[1], isLight: true); graph.AddEdge(nodes[1], nodes[2], isLight: true); graph.AddEdge(nodes[2], nodes[0], isLight: true); graph.AddEdge(nodes[0], nodes[1], isLight: false); graph.AddEdge(nodes[1], nodes[3], isLight: false); }
public void TopologicalOrderViolationsIgnoredIfRequested() { var graph = new MutableDirectedGraph(); NodeId a = graph.CreateNode(); NodeId b = graph.CreateNode(); NodeId c = graph.CreateNode(); NodeId d = graph.CreateNode(); graph.AddEdge(a, b); graph.AddEdge(d, c); // This edge breaks the topological labelling. XAssert.IsFalse(graph.IsReachableFrom(a, c, skipOutOfOrderNodes: true)); }
public void TriviallyConnectedNodes() { var graph = new MutableDirectedGraph(); NodeId a = graph.CreateNode(); NodeId b = graph.CreateNode(); graph.AddEdge(a, b); XAssert.IsTrue(graph.IsReachableFrom(a, b)); XAssert.IsFalse(graph.IsReachableFrom(b, a)); }
public void TrivialViolationOfTopologicalOrder() { var graph = new MutableDirectedGraph(); NodeId a = graph.CreateNode(); NodeId b = graph.CreateNode(); NodeId c = graph.CreateNode(); NodeId d = graph.CreateNode(); graph.AddEdge(a, b); graph.AddEdge(d, c); // This edge breaks the topological labelling. try { // Note that to fail, we need c > a here due to a fast-path for 'unreachable' // that doesn't look at any edges. graph.IsReachableFrom(a, c); } catch (BuildXLException) { return; } XAssert.Fail("Expected a failure due to a topological order violation"); }
public void MultipleLevels() { var graph = new MutableDirectedGraph(); NodeId l0 = graph.CreateNode(); NodeId l1_n1 = graph.CreateNode(); NodeId l1_n2 = graph.CreateNode(); graph.AddEdge(l0, l1_n1); graph.AddEdge(l0, l1_n2); graph.AddEdge(l1_n1, l1_n2); NodeId l2_n1 = graph.CreateNode(); NodeId l2_n2 = graph.CreateNode(); graph.AddEdge(l1_n1, l2_n1); graph.AddEdge(l1_n2, l2_n2); NodeId l3_n1 = graph.CreateNode(); NodeId l3_n2 = graph.CreateNode(); graph.AddEdge(l2_n1, l3_n1); graph.AddEdge(l2_n2, l3_n2); NodeId l4 = graph.CreateNode(); graph.AddEdge(l3_n1, l4); graph.AddEdge(l3_n2, l4); XAssert.IsTrue(graph.IsReachableFrom(l1_n1, l3_n2)); XAssert.IsTrue(graph.IsReachableFrom(l0, l4)); XAssert.IsFalse(graph.IsReachableFrom(l3_n2, l1_n1)); XAssert.IsFalse(graph.IsReachableFrom(l4, l0)); }
private static IReadonlyDirectedGraph CreateRandomAcyclicGraph(Random rng, int nodeCount) { var graph = new MutableDirectedGraph(); var nodes = new NodeId[nodeCount]; for (int i = 0; i < nodeCount; i++) { nodes[i] = graph.CreateNode(); } for (int i = 0; i < nodeCount; i++) { int toIndex = i; while ((toIndex = rng.Next(toIndex + 1, nodeCount)) < nodeCount) { graph.AddEdge(nodes[i], nodes[toIndex]); } } return(graph); }
/// <summary> /// Creates a test graph. /// </summary> private static void CreateGraph(out MutableDirectedGraph graph, out NodeId[] nodes) { graph = new MutableDirectedGraph(); XAssert.AreEqual(graph.NodeCount, 0); XAssert.AreEqual(graph.EdgeCount, 0); // Test creation. nodes = new NodeId[12]; for (int i = 0; i < nodes.Length; ++i) { nodes[i] = graph.CreateNode(); } XAssert.AreEqual(graph.NodeCount, nodes.Length); XAssert.AreEqual(graph.EdgeCount, 0); foreach (NodeId t in nodes) { XAssert.IsTrue(graph.ContainsNode(t)); XAssert.IsTrue(graph.IsSourceNode(t)); XAssert.IsTrue(graph.IsSinkNode(t)); } graph.AddEdge(nodes[5], nodes[0]); graph.AddEdge(nodes[5], nodes[1]); graph.AddEdge(nodes[6], nodes[1]); graph.AddEdge(nodes[6], nodes[2]); graph.AddEdge(nodes[7], nodes[5]); graph.AddEdge(nodes[8], nodes[5]); graph.AddEdge(nodes[9], nodes[6]); graph.AddEdge(nodes[9], nodes[3]); graph.AddEdge(nodes[9], nodes[4]); graph.AddEdge(nodes[10], nodes[8]); graph.AddEdge(nodes[11], nodes[8]); graph.AddEdge(nodes[11], nodes[9]); }