// Craete a network from a network file. public static Network LoadNetwork(string filename) { // Make a new network. Network network = new Network(); // Read the data. string[] allLines = File.ReadAllLines(filename); // Get the number of nodes. int numNodes = int.Parse(allLines[0]); // Create the nodes. for (int i = 0; i < numNodes; i++) { network.AllNodes.Add(new NetworkNode()); network.AllNodes[i].Index = i; } // Read the nodes. char[] separators = { ',' }; for (int i = 1; i < allLines.Length; i++) { NetworkNode node = network.AllNodes[i - 1]; string[] nodeFields = allLines[i].Split(separators); // Get the node's text and coordinates. node.Name = nodeFields[0]; node.Location = new PointF( int.Parse(nodeFields[1]), int.Parse(nodeFields[2]) ); // Get the node's links. for (int j = 3; j < nodeFields.Length; j += 3) { // Get the next link. NetworkLink link = new NetworkLink(); link.Nodes[0] = node; int index = int.Parse(nodeFields[j]); link.Nodes[1] = network.AllNodes[index]; link.Cost = int.Parse(nodeFields[j + 1]); link.Capacity = int.Parse(nodeFields[j + 2]); node.Links.Add(link); } } return(network); }
// Find a shortest path tree rooted at fromNode // by using a label correcting algorithm. // Return the tree's total cost. public int FindLabelCorrectingPathTree(NetworkNode fromNode) { // Reset the network. ResetNetwork(); // Set all nodes' distances to infinity and their labels to 0. foreach (NetworkNode node in AllNodes) { node.Distance = int.MaxValue; node.Text = "0"; } // Add the start node to the shortest path tree. fromNode.Visited = true; fromNode.Distance = 0; // Make the candidate list. Queue <NetworkLink> candidateLinks = new Queue <NetworkLink>(); // Add the start node's links to the candidate list. foreach (NetworkLink link in fromNode.Links) { candidateLinks.Enqueue(link); } // Make a shortest path tree. while (candidateLinks.Count > 0) { // Use the first link in the candidate list. NetworkLink link = candidateLinks.Dequeue(); // See if link this improves its destination node's distance. int newDistance = link.Nodes[0].Distance + link.Cost; NetworkNode toNode = link.Nodes[1]; if (newDistance < toNode.Distance) { // This is an improvement. // Update the node's distance. toNode.Distance = newDistance; // Update the node's FromNode and FromLink. toNode.FromNode = link.Nodes[0]; toNode.FromLink = link; // Update the node's label. int numUpdates = int.Parse(toNode.Text); numUpdates++; toNode.Text = numUpdates.ToString(); // Add the node's links to the candidate list. foreach (NetworkLink newLink in toNode.Links) { candidateLinks.Enqueue(newLink); } } } // Set the Visited properties for the visited nodes and links. int cost = 0; foreach (NetworkNode node in AllNodes) { node.Visited = true; if (node.FromLink != null) { node.FromLink.Visited = true; cost += node.FromLink.Cost; } } // Return the total cost. return(cost); }
// Follow a spanning tree's links to find a path from fromNode to toNode. public int FindSpanningTreePath(NetworkNode fromNode, NetworkNode toNode, out List <NetworkNode> pathNodes, out List <NetworkLink> pathLinks) { // Follow the tree's links back from toNode to fromNode. pathNodes = new List <NetworkNode>(); pathLinks = new List <NetworkLink>(); NetworkNode currentNode = toNode; while (currentNode != fromNode) { // Add this node to the path. pathNodes.Add(currentNode); // Find the previous node. NetworkNode prevNode = currentNode.FromNode; // Find the link that leads to currentNode. NetworkLink prevLink = null; foreach (NetworkLink link in prevNode.Links) { if (link.Nodes[1] == currentNode) { prevLink = link; break; } } // Make sure we found the link. Debug.Assert(prevLink != null); // Add the link to the path. pathLinks.Add(prevLink); // Move to the next node. currentNode = prevNode; } // while (currentNode != fromNode) // Add the start node. pathNodes.Add(fromNode); // Reverse the order of the nodes and links. pathNodes.Reverse(); pathLinks.Reverse(); // Unmark all nodes and links. DeselectNodes(); DeselectBranches(); // Marks the path's nodes and links. foreach (NetworkNode node in pathNodes) { node.Visited = true; } foreach (NetworkLink link in pathLinks) { link.Visited = true; } // Calculate the cost of the path. int cost = 0; foreach (NetworkLink link in pathLinks) { cost += link.Cost; } // Return the cost. return(cost); }
// Find a shortest path tree rooted at fromNode // by using a label setting algorithm. // Return the tree's total cost. public int FindLabelSettingPathTree(NetworkNode fromNode) { // Reset the network. ResetNetwork(); // Keep track of the number of nodes in the tree. int numDone = 0; // Add the start node to the shortest path tree. fromNode.Visited = true; fromNode.Distance = 0; fromNode.Text = numDone.ToString(); numDone++; // Track the tree's total cost. int cost = 0; // Make the candidate list. List <NetworkLink> candidateLinks = new List <NetworkLink>(); // Add the start node's links to the candidate list. foreach (NetworkLink link in fromNode.Links) { candidateLinks.Add(link); } // Make a shortest path tree. while (candidateLinks.Count > 0) { // Find the best link. NetworkLink bestLink = null; int bestCost = int.MaxValue; for (int i = candidateLinks.Count - 1; i >= 0; i--) { NetworkLink testLink = candidateLinks[i]; // See if the link leads outside the tree. if (testLink.Nodes[1].Visited) { // Remove this link. candidateLinks.RemoveAt(i); } else { // See if this link is an improvement. int testCost = testLink.Nodes[0].Distance + testLink.Cost; if (testCost < bestCost) { bestCost = testCost; bestLink = testLink; } } } // If we found no link, then the candidate // list must be empty and we're done. if (bestLink == null) { Debug.Assert(candidateLinks.Count == 0); break; } // Use this link. // Remove it from the candidate list. candidateLinks.Remove(bestLink); // Add the node to the tree. NetworkNode bestNode = bestLink.Nodes[1]; bestNode.Distance = bestLink.Nodes[0].Distance + bestLink.Cost; bestNode.Visited = true; bestLink.Visited = true; bestNode.FromNode = bestLink.Nodes[0]; bestNode.Text = numDone.ToString(); numDone++; // Add the node's links to the tree. foreach (NetworkLink newLink in bestNode.Links) { if (!newLink.Nodes[1].Visited) { candidateLinks.Add(newLink); } } // Add the link's cost to the tree's total cost. cost += bestLink.Cost; } // Return the total cost. return(cost); }
// Build a minimal spanning tree. Return its total cost. // When it adds a node to the spanning tree, the algorithm // also adds its links that lead outside of the tree to a list. // Later it searches that list for a minimal link. public int MakeMinimalSpanningTree(NetworkNode root, out bool isConnected) { // Reset the network. ResetNetwork(); // The total cost of the links in the spanning tree. int totalCost = 0; // Add the root node's links to the link candidate list. List <NetworkLink> candidateLinks = new List <NetworkLink>(); foreach (NetworkLink link in root.Links) { candidateLinks.Add(link); } // Visit the root node. root.Visited = true; // Process the list until it's empty. while (candidateLinks.Count > 0) { // Find the link with the lowest cost. NetworkLink bestLink = candidateLinks[0]; int bestCost = bestLink.Cost; for (int i = 1; i < candidateLinks.Count; i++) { if (candidateLinks[i].Cost < bestCost) { // Save this improvement. bestLink = candidateLinks[i]; bestCost = bestLink.Cost; } } // Remove the link from the list. candidateLinks.Remove(bestLink); // Get the node at the other end of the link. NetworkNode toNode = bestLink.Nodes[1]; // See if the link's node is still unmarked. if (!toNode.Visited) { // Use the link. bestLink.Visited = true; totalCost += bestLink.Cost; toNode.Visited = true; // Record the node that got us here. toNode.FromNode = bestLink.Nodes[0]; // Process toNode's links. foreach (NetworkLink newLink in toNode.Links) { // If the node hasn't been visited, // add the link to the list. if (!newLink.Nodes[1].Visited) { candidateLinks.Add(newLink); } } } } // See if the network is connected. isConnected = true; foreach (NetworkNode node in AllNodes) { if (!node.Visited) { isConnected = false; break; } } return(totalCost); }