/// <summary> /// Finds and returns the shortest path between from and to, /// considering the weight of the nodes, the weight of the /// links or both. /// </summary> public static Path FindShortestPath(IGraph graph, INode from, INode to, bool useNodeWeights, bool useLinkWeights) { if (!useNodeWeights && !useLinkWeights) { return(FindShortestPath(graph, from, to)); } // Find all paths between from and to and // pick the less heavy one PathList paths = FindPaths(graph, from, to, false); if (paths.Count == 0) { return(null); } SortedList table = new SortedList(); foreach (Path path in paths) { table[path.GetWeight(useNodeWeights, useLinkWeights)] = path; } // Return the first path return(table[table.GetKey(0)] as Path); }
/// <summary> /// Finds the longest path between two nodes. /// Returns null if no path exists. /// </summary> public static Path FindLongestPath(IGraph graph, INode from, INode to) { PathList paths = FindPaths(graph, from, to, false); if (paths.Count > 0) { return(paths[paths.Count - 1]); } else { return(null); } }
/// <summary> /// Finds and returns the shortest path between from and to. /// Returns null if no path exists. /// </summary> public static Path FindShortestPath(IGraph graph, INode from, INode to) { PathList paths = FindPaths(graph, from, to, true); if (paths.Count > 0) { return(paths[0]); } else { return(null); } }
/// <summary> /// Detects whether the specified node participates in a cycle. /// </summary> public static Path FindCycle(IGraph graph, INode participant) { PathList cycles = FindPaths(graph, participant, participant, false); if (cycles.Count > 0) { // Remove the last node from the path to avoid duplicates Path path = cycles[0]; path.Nodes.RemoveAt(path.Nodes.Count - 1); path.Items.RemoveAt(path.Items.Count - 1); return(path); } return(null); }
/// <summary> /// Detects whether there is a cycle in a graph. /// </summary> public static Path FindCycle(IGraph graph) { foreach (INode node in graph.Nodes) { PathList cycles = FindPaths(graph, node, node, false); if (cycles.Count > 0) { // Remove the last node from the path to avoid duplicates Path path = cycles[0]; path.Nodes.RemoveAt(path.Nodes.Count - 1); path.Items.RemoveAt(path.Items.Count - 1); return(path); } } return(null); }
public static PathList FindAllCycles(IGraph graph) { PathList result = new PathList(); foreach (INode node in graph.Nodes) { PathList cycles = FindPaths(graph, node, node, false); // Remove the last node from the path to avoid duplicates foreach (Path path in cycles) { path.Nodes.RemoveAt(path.Nodes.Count - 1); path.Items.RemoveAt(path.Items.Count - 1); } // Add cycles to result list skipping equal sycles. foreach (Path path in cycles) { bool found = false; foreach (Path path2 in result) { if (path2.SameCycle(path)) { found = true; break; } } if (!found) { result.Add(path); } } } return(result); }
private static PathList FindPaths(IGraph graph, INode from, INode to, bool shortestOnly) { PathList result = new PathList(); Path path = null; if (from == to && shortestOnly) { // Return a collection with a single path consisting of a single node. path = new Path(); path.Add(from); result.Add(path); return result; } // Perform the search PathList tempCol = new PathList(); Path tempPath; // Create the first path, constisting only of the first node tempCol.Add(tempPath = new Path()); tempPath.Add(from); bool pathFound = false; while (true) { int size = tempCol.Count; if (size == 0) break; if (pathFound && shortestOnly) break; // For all paths - get their next nodes for (int i = 0; i < size; i++) { tempPath = tempCol[0]; tempCol.RemoveAt(0); // Get the last node for this path and find its successors INode lastNode = tempPath.Nodes[tempPath.Nodes.Count - 1]; LinkCollection links = lastNode.OutLinks; foreach (ILink link in links) { INode nextNode; // Get the next node in the path nextNode = graph.Directed ? link.Destination : link.GetOppositeNode(lastNode); // Check if the path target is reached if (nextNode.Equals(to)) { // We've reached the end Path newPath = new Path(tempPath); newPath.Add(link, nextNode); result.Add(newPath); pathFound = true; continue; } // The node does not belong to the path -> add it if (!tempPath.Contains(nextNode)) { Path newPath = new Path(tempPath); newPath.Add(link, nextNode); tempCol.Add(newPath); } } } } return result; }
public static PathList FindAllCycles(IGraph graph) { PathList result = new PathList(); foreach (INode node in graph.Nodes) { PathList cycles = FindPaths(graph, node, node, false); // Remove the last node from the path to avoid duplicates foreach (Path path in cycles) { path.Nodes.RemoveAt(path.Nodes.Count - 1); path.Items.RemoveAt(path.Items.Count - 1); } // Add cycles to result list skipping equal sycles. foreach (Path path in cycles) { bool found = false; foreach (Path path2 in result) { if (path2.SameCycle(path)) { found = true; break; } } if (!found) result.Add(path); } } return result; }
/// <summary> /// Finds the longest path in the graph. The time limit /// specifies the maximum duration of the search process /// in milliseconds. /// Returns null if no path exists. /// </summary> public static Path FindLongestPath(IGraph graph, long timeLimit) { PathList paths = new PathList(); // create initial set of paths of length zero foreach (INode node in graph.Nodes) { // create a path consisting only of this node Path path = new Path(); path.Add(node); paths.Add(path); // paths in which this node participates PathStats pathStats = new PathStats(); pathStats.currentSet.Add(path, path); node.Data = pathStats; } long startMillis = DateTime.Now.Ticks / 10000; // find set of paths that are one node longer than in previous set bool morePathsAdded = false; do { morePathsAdded = false; PathList newPaths = new PathList(); // try to extend each path in the previous set foreach (Path path in paths) { INode lastNode = path.Nodes[path.Nodes.Count - 1]; foreach (ILink link in lastNode.OutLinks) { INode nodeToAdd = graph.Directed ? link.Destination : link.GetOppositeNode(lastNode); // test for cycles PathStats testPaths = nodeToAdd.Data as PathStats; if (testPaths.currentSet.Contains(path)) continue; // extend the path with this node Path newPath = new Path(path); newPath.Add(link, nodeToAdd); // update all nodes in the new path foreach (INode node in newPath.Nodes) { PathStats nodePaths = node.Data as PathStats; nodePaths.newSet.Add(newPath, newPath); } // add to the new set morePathsAdded = true; newPaths.Add(newPath); } } if (morePathsAdded) { paths = newPaths; // remove shorter paths from node associated path lists // they are not needed in next iterations foreach (INode node in graph.Nodes) { PathStats nodePaths = node.Data as PathStats; Hashtable swap = nodePaths.currentSet; nodePaths.currentSet = nodePaths.newSet; nodePaths.newSet = swap; nodePaths.newSet.Clear(); } } // Check time limit if (timeLimit > 0 && DateTime.Now.Ticks / 10000 - startMillis > timeLimit) break; } while (morePathsAdded); // cleanup foreach (INode node in graph.Nodes) node.Data = null; if (paths.Count == 0) return null; return paths[0]; }
private static PathList FindPaths(IGraph graph, INode from, INode to, bool shortestOnly) { PathList result = new PathList(); Path path = null; if (from == to && shortestOnly) { // Return a collection with a single path consisting of a single node. path = new Path(); path.Add(from); result.Add(path); return(result); } // Perform the search PathList tempCol = new PathList(); Path tempPath; // Create the first path, constisting only of the first node tempCol.Add(tempPath = new Path()); tempPath.Add(from); bool pathFound = false; while (true) { int size = tempCol.Count; if (size == 0) { break; } if (pathFound && shortestOnly) { break; } // For all paths - get their next nodes for (int i = 0; i < size; i++) { tempPath = tempCol[0]; tempCol.RemoveAt(0); // Get the last node for this path and find its successors INode lastNode = tempPath.Nodes[tempPath.Nodes.Count - 1]; LinkCollection links = lastNode.OutLinks; foreach (ILink link in links) { INode nextNode; // Get the next node in the path nextNode = graph.Directed ? link.Destination : link.GetOppositeNode(lastNode); // Check if the path target is reached if (nextNode.Equals(to)) { // We've reached the end Path newPath = new Path(tempPath); newPath.Add(link, nextNode); result.Add(newPath); pathFound = true; continue; } // The node does not belong to the path -> add it if (!tempPath.Contains(nextNode)) { Path newPath = new Path(tempPath); newPath.Add(link, nextNode); tempCol.Add(newPath); } } } } return(result); }
/// <summary> /// Finds the longest path in the graph. The time limit /// specifies the maximum duration of the search process /// in milliseconds. /// Returns null if no path exists. /// </summary> public static Path FindLongestPath(IGraph graph, long timeLimit) { PathList paths = new PathList(); // create initial set of paths of length zero foreach (INode node in graph.Nodes) { // create a path consisting only of this node Path path = new Path(); path.Add(node); paths.Add(path); // paths in which this node participates PathStats pathStats = new PathStats(); pathStats.currentSet.Add(path, path); node.Data = pathStats; } long startMillis = DateTime.Now.Ticks / 10000; // find set of paths that are one node longer than in previous set bool morePathsAdded = false; do { morePathsAdded = false; PathList newPaths = new PathList(); // try to extend each path in the previous set foreach (Path path in paths) { INode lastNode = path.Nodes[path.Nodes.Count - 1]; foreach (ILink link in lastNode.OutLinks) { INode nodeToAdd = graph.Directed ? link.Destination : link.GetOppositeNode(lastNode); // test for cycles PathStats testPaths = nodeToAdd.Data as PathStats; if (testPaths.currentSet.Contains(path)) { continue; } // extend the path with this node Path newPath = new Path(path); newPath.Add(link, nodeToAdd); // update all nodes in the new path foreach (INode node in newPath.Nodes) { PathStats nodePaths = node.Data as PathStats; nodePaths.newSet.Add(newPath, newPath); } // add to the new set morePathsAdded = true; newPaths.Add(newPath); } } if (morePathsAdded) { paths = newPaths; // remove shorter paths from node associated path lists // they are not needed in next iterations foreach (INode node in graph.Nodes) { PathStats nodePaths = node.Data as PathStats; Hashtable swap = nodePaths.currentSet; nodePaths.currentSet = nodePaths.newSet; nodePaths.newSet = swap; nodePaths.newSet.Clear(); } } // Check time limit if (timeLimit > 0 && DateTime.Now.Ticks / 10000 - startMillis > timeLimit) { break; } }while (morePathsAdded); // cleanup foreach (INode node in graph.Nodes) { node.Data = null; } if (paths.Count == 0) { return(null); } return(paths[0]); }