public void TestAddingEdges() { IWeightedGraph <int> graph = new UndirectedWeightedGraph <int>(); int[] vertices = { 45, -3, 77, -9, 33, -71 }; float?[,] adjacency_matrix = { { null, 8.4f, 0.4f, null, null, null }, { 8.4f, null, null, 8.1f, null, 1.7f }, { 0.4f, null, null, null, 7.7f, null }, { null, 8.1f, null, null, 3.0f, 7.0f }, { null, null, 7.7f, 3.0f, null, null }, { null, 1.7f, null, 7.0f, null, null } }; // Sanity check Assert.AreEqual(vertices.Length, adjacency_matrix.GetLength(0)); Assert.AreEqual(vertices.Length, adjacency_matrix.GetLength(1)); // Add the vertices foreach (var vertex in vertices) { Assert.IsTrue(graph.AddVertex(vertex)); } // Add the edges. Iterate over the lower triangular matrix // only as the upper triangular matrix (above the diagonal) // is the mirror of the lower triangular matrix. for (int row = 1; row < vertices.Length; ++row) { for (int col = 0; col < row; ++col) { // Sanity check Assert.AreEqual(adjacency_matrix[row, col], adjacency_matrix[col, row]); if (adjacency_matrix[row, col] != null) { Assert.IsTrue(graph.AddEdge(row, col, adjacency_matrix[row, col].Value)); } } } // Make sure that the graph has the expected structure for (int row = 0; row < vertices.Length; ++row) { for (int col = 0; col < vertices.Length; ++col) { Assert.AreEqual(adjacency_matrix[row, col] != null, graph.EdgeExists(row, col)); if (adjacency_matrix[row, col] != null) { // Compare with tolerance in ULPs Assert.That( adjacency_matrix[row, col].Value, Is.EqualTo(graph.GetEdgeWeight(row, col)).Within(1).Ulps); } } } }
public void Test() { UndirectedWeightedGraph graph1 = new UndirectedWeightedGraph(false); #region Basic stuff Assert.AreEqual(false, graph1.directed); Assert.AreEqual(true, graph1.weighted); Assert.AreEqual(false, graph1.multigraph); #endregion #region Vertex stuff for (char i = 'a'; i <= 'h'; i++) { graph1.AddVertex(Convert.ToString(i)); } graph1.AddVertex("a"); Assert.AreEqual(8, graph1.verticesCount); graph1.RemoveVertex("h"); graph1.RemoveVertex("z"); Assert.AreEqual(7, graph1.verticesCount); Assert.AreEqual(true, graph1.ExistVertex("a")); Assert.AreEqual(false, graph1.ExistVertex("z")); #endregion #region Edge stuff graph1.AddEdge("a", "b", 10); graph1.AddEdge("a", "b", 2); Assert.AreEqual(1, graph1.edgesCount); graph1.AddEdge("a", "a"); graph1.AddEdge("a", "a", 2); Assert.AreEqual(1, graph1.edgesCount); graph1.AddEdge("a", "z", 2); graph1.AddEdge("z", "a", 2); graph1.AddEdge("y", "z", 2); Assert.AreEqual(1, graph1.edgesCount); graph1.AddEdge("b", "c", 1); graph1.AddEdge("c", "d", 1); graph1.AddEdge("d", "e", 1); graph1.AddEdge("e", "f", 1); graph1.AddEdge("f", "g", 1); Assert.AreEqual(6, graph1.edgesCount); graph1.RemoveEdge("a", "b"); graph1.RemoveEdge("a", "c", 1); graph1.RemoveEdge("f", "g", 1); Assert.AreEqual(5, graph1.edgesCount); Assert.AreEqual(true, graph1.ExistEdge("a", "b")); Assert.AreEqual(true, graph1.ExistEdge("b", "a")); Assert.AreEqual(10, graph1.GetEdgeWeight("a", "b")); graph1.ChangeWeight("a", "b", 10, 20); Assert.AreEqual(20, graph1.GetEdgeWeight("a", "b")); graph1.RemoveVertex("d"); Assert.AreEqual(3, graph1.edgesCount); #endregion graph1.Clear(); Assert.AreEqual(0, graph1.verticesCount); Assert.AreEqual(0, graph1.edgesCount); UndirectedWeightedGraph graph2 = new UndirectedWeightedGraph(true); #region Basic stuff Assert.AreEqual(false, graph2.directed); Assert.AreEqual(true, graph2.weighted); Assert.AreEqual(true, graph2.multigraph); #endregion #region Vertex stuff for (char i = 'a'; i <= 'h'; i++) { graph2.AddVertex(Convert.ToString(i)); } graph2.AddVertex("a"); Assert.AreEqual(8, graph2.verticesCount); graph2.RemoveVertex("h"); graph2.RemoveVertex("z"); Assert.AreEqual(7, graph2.verticesCount); Assert.AreEqual(true, graph2.ExistVertex("a")); Assert.AreEqual(false, graph2.ExistVertex("z")); #endregion #region Edge stuff graph2.AddEdge("a", "b", 10); graph2.AddEdge("a", "b", 2); Assert.AreEqual(2, graph2.edgesCount); graph2.AddEdge("a", "a"); graph2.AddEdge("a", "a", 2); Assert.AreEqual(2, graph2.edgesCount); graph2.AddEdge("a", "z", 2); graph2.AddEdge("z", "a", 2); graph2.AddEdge("y", "z", 2); Assert.AreEqual(2, graph2.edgesCount); graph2.AddEdge("b", "c", 1); graph2.AddEdge("c", "d", 1); graph2.AddEdge("d", "e", 1); graph2.AddEdge("e", "f", 1); graph2.AddEdge("f", "g", 1); Assert.AreEqual(7, graph2.edgesCount); graph2.RemoveEdge("a", "b"); graph1.RemoveEdge("a", "c", 1); graph2.RemoveEdge("f", "g", 1); Assert.AreEqual(6, graph2.edgesCount); Assert.AreEqual(true, graph2.ExistEdge("a", "b")); Assert.AreEqual(1, graph2.GetEdgeWeight("a", "b")); graph2.ChangeWeight("a", "b", 10, 20); Assert.AreEqual(1, graph2.GetEdgeWeight("a", "b")); graph2.RemoveVertex("d"); Assert.AreEqual(4, graph2.edgesCount); #endregion graph2.Clear(); Assert.AreEqual(0, graph2.verticesCount); Assert.AreEqual(0, graph2.edgesCount); }
public void TestFindingMinimumSpanningTree() { // Item1 - the vertices to add to the graph // Item2 - the adjacency matrix that defines the edges // of the graph. // Item3 - expected MST weight Tuple <string[], float?[, ], float>[] test_vectors = { new Tuple <string[], float?[, ], float>( new string[] { "A" }, new float?[, ] { { null } }, 0f), new Tuple <string[], float?[, ], float>( new string[] { "A","B" }, new float?[, ] { { null, 5.0f }, { 5.0f, null } }, 5f), new Tuple <string[], float?[, ], float>( new string[] { "A","B", "C", "D", "E", "F", "G", "H", "I", "J" }, new float?[, ] { { null, 2f, 4f, 4f, null, null, null, null, null, null }, { 2f, null, 3f, null, 7f, null, null, null, null, null }, { 4f, 3f, null, 1f, 8f, 9f, null, null, null, null }, { 4f, null, 1f, null, null, 10f, null, null, null, null }, { null, 7f, 8f, null, null, null, 3f, 11f, null, null }, { null, null, 9f, 10f, null, null, null, null, 6f, null }, { null, null, null, null, 3f, null, null, null, 6f, null }, { null, null, null, null, 11f, null, null, null, 1f, 2f }, { null, null, null, null, null, 6f, 6f, 1f, null, 5f }, { null, null, null, null, null, null, null, 2f, 5f, null } }, 31f), new Tuple <string[], float?[, ], float>( new string[] { "A","B", "C", "D", "E", "F", "G", "H", "I", "J", "K"}, new float?[, ] { { null, null, 3f, null, null, 2f, null, null, null, null, 1f}, { null, null, 7f, null, 3f, 3f, null, null, null,8f, null }, { 3f, 7f, null, null, null, 10f, null, null, 2f, null, 1f}, { null, null, null, null, null, null, null, null, null,5f, null }, { null, 3f, null, null, null, null, null, 4f, 1f, null, 7f}, { 2f, 3f, 10f, null, null, null, null, null, null,4f, null }, { null, null, null, null, null, null, null, 7f, 5f, null, 9f}, { null, null, null, null, 4f, null, 7f, null, null, null, null}, { null, null, 2f, null, 1f, null, 5f, null, null, null, null}, { null, 8f, null, 5f, null, 4f, null, null, null, null, null}, { 1f, null, 1f, null, 7f, null, 9f, null, null, null, null} }, 28f) }; foreach (var test_vector in test_vectors) { var graph = new UndirectedWeightedGraph <string>(3); // Sanity check Assert.AreEqual(test_vector.Item1.Length, test_vector.Item2.GetLength(0)); Assert.AreEqual(test_vector.Item1.Length, test_vector.Item2.GetLength(1)); // Add vertices foreach (var vertex in test_vector.Item1) { graph.AddVertex(vertex); } // Assert that the graph size is as expected Assert.AreEqual(test_vector.Item1.Length, graph.Size); // Add edges. Iterate over the upper triangular matrix only // as the lower triangular matrix (below the diagonal) must // be its mirror. for (int row = 0; row < test_vector.Item1.Length; ++row) { for (int col = row + 1; col < test_vector.Item1.Length; ++col) { // Sanity check Assert.AreEqual(test_vector.Item2[row, col], test_vector.Item2[col, row]); if (test_vector.Item2[row, col] != null) { graph.AddEdge(row, col, test_vector.Item2[row, col].Value); } } } // Compute the MST IWeightedGraph <string> mst = graph.FindMinimumSpanningTree(); // Assert that the size of the produced MST is expected Assert.AreEqual(test_vector.Item1.Length, mst.Size); // A vertex is 'marked' when we encounter an edge that starts // or ends in a given vertex. All vertices must be marked in // the end. bool[] marked_vertices = new bool[test_vector.Item1.Length]; // The number of discovered edges (bidirectional edges are // count only once). The number of edges in an MST must be // equal to the number of vertices minus one. int edge_count = 0; // The total weight of the MST. float mst_weight = 0.0f; // Iterate over the upper triangular matrix only. The lower // triangular matrix must be a mirror of it. for (int row = 0; row < test_vector.Item1.Length; ++row) { for (int col = row + 1; col < test_vector.Item1.Length; ++col) { // If (row, col) edge exists in MST, (col, row) must exist // as well as this is an undirected graph Assert.AreEqual(mst.EdgeExists(row, col), mst.EdgeExists(col, row)); if (mst.EdgeExists(row, col)) { // If the edge exists in MST, it must also exist in the // original graph Assert.IsTrue(graph.EdgeExists(row, col)); // Assert that the weight of (row, col) edge equals // the weight of that edge in the original graph Assert.AreEqual(graph.GetEdgeWeight(row, col), mst.GetEdgeWeight(row, col)); // Assert that (col, row) edge weight matches the (row, col) // edge weight (must be the case as this is an undirected // graph). Assert.AreEqual(mst.GetEdgeWeight(row, col), mst.GetEdgeWeight(col, row)); // 'Mark' the start and end vertices marked_vertices[row] = marked_vertices[col] = true; // Add to the total mst weight mst_weight += mst.GetEdgeWeight(row, col); // Increment the number of discovered edges ++edge_count; } } } // If all of the following asserts pass, the generated graph // is in fact a MST if (test_vector.Item1.Length > 1) { // Assert that every vertex has been marked foreach (var marked in marked_vertices) { Assert.IsTrue(marked); } } // Assert that the number of discovered edges is one less than // the number of vertices in the graph Assert.AreEqual(test_vector.Item1.Length - 1, edge_count); // Assert that the total MST weight matches the expected weight Assert.That( test_vector.Item3, Is.EqualTo(mst_weight).Within(1).Ulps); } }