Skip to content
Snippets Groups Projects
Commit b5d14999 authored by Timon Römer's avatar Timon Römer
Browse files

Fixes WorstCaseSearch.cs

parent 1218e8d3
Branches
No related tags found
No related merge requests found
...@@ -6,7 +6,7 @@ namespace FlowForge; ...@@ -6,7 +6,7 @@ namespace FlowForge;
public class BreadthFirstSearchStrategy : ISearchStrategy public class BreadthFirstSearchStrategy : ISearchStrategy
{ {
public bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, bool forceWorstCase = false) public bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, FlowEdge? specialEdge = null)
{ {
Console.WriteLine("Breadth Depth First Search..."); Console.WriteLine("Breadth Depth First Search...");
// parent map to walk back path // parent map to walk back path
...@@ -25,7 +25,7 @@ public class BreadthFirstSearchStrategy : ISearchStrategy ...@@ -25,7 +25,7 @@ public class BreadthFirstSearchStrategy : ISearchStrategy
Console.WriteLine("Current Node: " + current); Console.WriteLine("Current Node: " + current);
var outEdges = flowGraph.Graph.OutEdges(current).ToList(); var outEdges = flowGraph.Graph.OutEdges(current).ToList();
List<FlowEdge> sortedOutEdges = forceWorstCase ? outEdges.OrderBy(edge => edge.Residual).ToList() : outEdges.OrderBy(edge => int.Parse(edge.Target.Id)).ToList(); List<FlowEdge> sortedOutEdges = outEdges.OrderBy(edge => int.Parse(edge.Target.Id)).ToList();
Console.WriteLine("Sorted out edges for node:"); Console.WriteLine("Sorted out edges for node:");
foreach (FlowEdge edge in sortedOutEdges) foreach (FlowEdge edge in sortedOutEdges)
......
...@@ -6,31 +6,15 @@ namespace FlowForge; ...@@ -6,31 +6,15 @@ namespace FlowForge;
public class DepthFirstSearchStrategy : ISearchStrategy public class DepthFirstSearchStrategy : ISearchStrategy
{ {
public bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, bool forceWorstCase = false) public bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, FlowEdge? specialEdge = null)
{ {
try try
{ {
if (forceWorstCase) if (specialEdge != null)
{ {
// Attempt to retrieve the nodes by ID
FlowNode? node2 = flowGraph.GetVertexById("2");
FlowNode? node3 = flowGraph.GetVertexById("3");
// Validate that the nodes were found
if (node2 == null || node3 == null)
{
throw new InvalidOperationException("One or more required vertices (2 or 3) could not be found in the graph.");
}
// Attempt to find the edge between node2 and node3
if (!flowGraph.Graph.TryGetEdge(node2, node3, out var edgeFrom2To3) || edgeFrom2To3 == null)
{
throw new InvalidOperationException("The edge between node2 and node3 does not exist.");
}
// Use the worst-case search to find the augmenting path // Use the worst-case search to find the augmenting path
WorstCaseSearch worstCaseSearch = new WorstCaseSearch(); WorstCaseSearch worstCaseSearch = new WorstCaseSearch();
return worstCaseSearch.FindAugmentingPathWithEdge(flowGraph, source, target, edgeFrom2To3, pathFlow); return WorstCaseSearch.FindAugmentingPathWithEdge(flowGraph, source, target, specialEdge, pathFlow);
} }
} }
catch (Exception e) catch (Exception e)
......
...@@ -26,7 +26,7 @@ public class FordFulkersonAlgorithm ...@@ -26,7 +26,7 @@ public class FordFulkersonAlgorithm
this.TargetId = targetId; this.TargetId = targetId;
} }
public double Run(ISearchStrategy strategy, bool forceWorstCase = false) public double Run(ISearchStrategy strategy, FlowEdge? specialEdge = null)
{ {
// get source and target nodes // get source and target nodes
FlowNode? source = _flowGraph.GetVertexById(SourceId); FlowNode? source = _flowGraph.GetVertexById(SourceId);
...@@ -37,9 +37,10 @@ public class FordFulkersonAlgorithm ...@@ -37,9 +37,10 @@ public class FordFulkersonAlgorithm
throw new ArgumentException("Invalid source or target node!"); throw new ArgumentException("Invalid source or target node!");
} }
Console.WriteLine("Start of Ford-Fulkerson Algorithm..."); Console.WriteLine("Start of Ford-Fulkerson Algorithm...");
if (forceWorstCase)
if (specialEdge != null)
{ {
Console.WriteLine("Using worst case scenario for edge selection."); Console.WriteLine("Using worst case scenario for edge selection with special edge " + specialEdge);
} }
double maxFlow = 0.0; double maxFlow = 0.0;
...@@ -51,7 +52,7 @@ public class FordFulkersonAlgorithm ...@@ -51,7 +52,7 @@ public class FordFulkersonAlgorithm
SaveGraphState(); SaveGraphState();
// execute as long as there is an augmenting path // execute as long as there is an augmenting path
while (strategy.FindAugmentingPath(_flowGraph, source, target, pathFlow, forceWorstCase)) while (strategy.FindAugmentingPath(_flowGraph, source, target, pathFlow, specialEdge))
{ {
PrintOrderedPath(pathFlow); PrintOrderedPath(pathFlow);
...@@ -140,12 +141,18 @@ public class FordFulkersonAlgorithm ...@@ -140,12 +141,18 @@ public class FordFulkersonAlgorithm
{ {
Console.WriteLine("Augmenting Path found:"); Console.WriteLine("Augmenting Path found:");
if (!pathFlow.Any())
{
Console.WriteLine("pathFlow is empty.");
return;
}
// Step 1: Find the starting edge // Step 1: Find the starting edge
FlowEdge startEdge = pathFlow.Keys FlowEdge startEdge = pathFlow.Keys
.First(edge => !pathFlow.Keys.Any(e => e.Target.Id == edge.Source.Id)); .First(edge => pathFlow.Keys.All(e => e.Target.Id != edge.Source.Id));
// Step 2: Follow the path from start to end // Step 2: Follow the path from start to end
List<FlowEdge> orderedPath = new List<FlowEdge> { startEdge }; var orderedPath = new List<FlowEdge> { startEdge };
while (true) while (true)
{ {
var currentEdge = orderedPath.Last(); var currentEdge = orderedPath.Last();
......
...@@ -4,7 +4,7 @@ namespace FlowForge; ...@@ -4,7 +4,7 @@ namespace FlowForge;
public interface ISearchStrategy public interface ISearchStrategy
{ {
bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, bool forceWorstCase = false); bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, FlowEdge? specialEdge = null);
public static void BuildAugmentingPath(FlowNode source, FlowNode target, Dictionary<FlowNode, FlowEdge> parentMap, Dictionary<FlowEdge, double> pathFlow) public static void BuildAugmentingPath(FlowNode source, FlowNode target, Dictionary<FlowNode, FlowEdge> parentMap, Dictionary<FlowEdge, double> pathFlow)
{ {
......
<Window x:Class="FlowForge.MainWindow" <Window x:Class="FlowForge.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Flow-Forge" Height="600" Width="1080"> Title="Flow-Forge" Height="600" Width="1150">
<Grid x:Name="MainGrid"> <Grid x:Name="MainGrid">
<!-- Define two rows: one fixed height for the button and one for the graph viewer --> <!-- Define two rows: one fixed height for the button and one for the graph viewer -->
<Grid.RowDefinitions> <Grid.RowDefinitions>
...@@ -84,9 +84,27 @@ ...@@ -84,9 +84,27 @@
Content="Force worst case" Content="Force worst case"
VerticalAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Margin="880,-15,0,10" Margin="885,-15,0,10"
Grid.Row="0" Grid.Row="0"
IsChecked="True"/> IsChecked="False"
Checked="WorstCaseCheckbox_Checked"
Unchecked="WorstCaseCheckbox_Unchecked"/>
<StackPanel x:Name="EdgeDefinitionStackPanel"
Orientation="Horizontal"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="880,30,0,0"
Grid.Row="0"
Visibility="Collapsed"> <!-- Initially hidden -->
<TextBlock Text="Source:" VerticalAlignment="Center" Margin="5"/>
<TextBox x:Name="SourceNodeInput" Width="50" Margin="5"/>
<TextBlock Text="Target:" VerticalAlignment="Center" Margin="5"/>
<TextBox x:Name="TargetNodeInput" Width="50" Margin="5"/>
</StackPanel>
<!-- Placeholder for graph viewer --> <!-- Placeholder for graph viewer -->
<Grid x:Name="GraphViewerGrid" Grid.Row="1"/> <Grid x:Name="GraphViewerGrid" Grid.Row="1"/>
......
...@@ -28,6 +28,8 @@ namespace FlowForge ...@@ -28,6 +28,8 @@ namespace FlowForge
private MsaglDrawing.Graph _msaglGraph = new MsaglDrawing.Graph(); private MsaglDrawing.Graph _msaglGraph = new MsaglDrawing.Graph();
private bool _isInitialized = false; private bool _isInitialized = false;
private FlowEdge? _specialEdge = null;
public MainWindow() public MainWindow()
{ {
...@@ -76,6 +78,8 @@ namespace FlowForge ...@@ -76,6 +78,8 @@ namespace FlowForge
// Display the graph after initialization // Display the graph after initialization
DisplayGraph(); DisplayGraph();
SnapToGridButton_Click(sender, e); // Snap nodes to grid
} }
private void InitializeGraphFromFile(string filePath) private void InitializeGraphFromFile(string filePath)
...@@ -155,8 +159,8 @@ namespace FlowForge ...@@ -155,8 +159,8 @@ namespace FlowForge
//SaveNodePositions(_gViewer.Graph); // Save positions before running the algorithm //SaveNodePositions(_gViewer.Graph); // Save positions before running the algorithm
bool forceWorstCase = WorstCaseCheckbox.IsChecked ?? false; AssignSpecialEdge();
double maxFlow = _fordFulkerson.Run(new DepthFirstSearchStrategy(), forceWorstCase); double maxFlow = _fordFulkerson.Run(new DepthFirstSearchStrategy(), _specialEdge);
_isInitialized = true; _isInitialized = true;
DisplayGraph(); DisplayGraph();
...@@ -176,7 +180,7 @@ namespace FlowForge ...@@ -176,7 +180,7 @@ namespace FlowForge
SaveNodePositions(_gViewer?.Graph); // Save positions before running the algorithm SaveNodePositions(_gViewer?.Graph); // Save positions before running the algorithm
bool forceWorstCase = WorstCaseCheckbox.IsChecked ?? false; bool forceWorstCase = WorstCaseCheckbox.IsChecked ?? false;
double maxFlow = _fordFulkerson.Run(new BreadthFirstSearchStrategy(), forceWorstCase); double maxFlow = _fordFulkerson.Run(new BreadthFirstSearchStrategy());
_isInitialized = true; _isInitialized = true;
DisplayGraph(); DisplayGraph();
...@@ -386,5 +390,55 @@ namespace FlowForge ...@@ -386,5 +390,55 @@ namespace FlowForge
_gViewer.Graph = _msaglGraph; _gViewer.Graph = _msaglGraph;
} }
} }
private void WorstCaseCheckbox_Checked(object sender, RoutedEventArgs e)
{
Console.WriteLine("Force worst case enabled.");
EdgeDefinitionStackPanel.Visibility = Visibility.Visible; // Show the StackPanel
}
private void WorstCaseCheckbox_Unchecked(object sender, RoutedEventArgs e)
{
Console.WriteLine("Force worst case disabled.");
EdgeDefinitionStackPanel.Visibility = Visibility.Collapsed; // Hide the StackPanel
}
private void AssignSpecialEdge()
{
// Get the source and target from the text boxes
string sourceNodeId = SourceNodeInput.Text.Trim();
string targetNodeId = TargetNodeInput.Text.Trim();
// Validate inputs
if (string.IsNullOrEmpty(sourceNodeId) || string.IsNullOrEmpty(targetNodeId))
{
Console.WriteLine("Source or target node ID is empty.");
_specialEdge = null;
return;
}
// Retrieve the source and target nodes from the graph
FlowNode? sourceNode = _flowGraph.GetVertexById(sourceNodeId);
FlowNode? targetNode = _flowGraph.GetVertexById(targetNodeId);
if (sourceNode == null || targetNode == null)
{
Console.WriteLine($"Could not find one or both nodes: Source ({sourceNodeId}), Target ({targetNodeId}).");
_specialEdge = null;
return;
}
// Find the edge between source and target
if (!_flowGraph.Graph.TryGetEdge(sourceNode, targetNode, out var edge) || edge == null)
{
Console.WriteLine($"The edge between {sourceNodeId} and {targetNodeId} does not exist.");
_specialEdge = null;
return;
}
// Assign the edge to the specialEdge field
_specialEdge = edge;
Console.WriteLine($"Special edge assigned: {_specialEdge}");
}
} }
} }
\ No newline at end of file
...@@ -6,11 +6,10 @@ namespace FlowForge; ...@@ -6,11 +6,10 @@ namespace FlowForge;
public class WorstCaseSearch public class WorstCaseSearch
{ {
public bool FindAugmentingPathWithEdge(FlowGraph flowGraph, FlowNode source, FlowNode target, FlowEdge requiredEdge, Dictionary<FlowEdge, double> pathFlow) public static bool FindAugmentingPathWithEdge(FlowGraph flowGraph, FlowNode source, FlowNode target, FlowEdge requiredEdge, Dictionary<FlowEdge, double> pathFlow)
{ {
// Determine if the required edge is valid in either direction // Determine if the required edge is valid in either direction
FlowEdge? validEdge; FlowEdge? validEdge;
bool isReversed = false;
if (requiredEdge.Residual > 0) if (requiredEdge.Residual > 0)
{ {
...@@ -21,7 +20,6 @@ public class WorstCaseSearch ...@@ -21,7 +20,6 @@ public class WorstCaseSearch
{ {
if (validEdge.Residual > 0) if (validEdge.Residual > 0)
{ {
isReversed = true;
Console.WriteLine($"Searching for augmenting path that includes edge {requiredEdge.Target.Id} -> {requiredEdge.Source.Id}"); Console.WriteLine($"Searching for augmenting path that includes edge {requiredEdge.Target.Id} -> {requiredEdge.Source.Id}");
} }
else else
...@@ -42,7 +40,7 @@ public class WorstCaseSearch ...@@ -42,7 +40,7 @@ public class WorstCaseSearch
// Phase 1: Find a path from source to the starting node of the valid edge // Phase 1: Find a path from source to the starting node of the valid edge
var phase1Path = new Dictionary<FlowEdge, double>(); var phase1Path = new Dictionary<FlowEdge, double>();
var phase1Success = FindAugmentingPath(flowGraph, source, validEdge.Source, phase1Path); bool phase1Success = FindAugmentingPath(flowGraph, source, validEdge.Source, phase1Path);
if (!phase1Success) if (!phase1Success)
{ {
...@@ -63,7 +61,7 @@ public class WorstCaseSearch ...@@ -63,7 +61,7 @@ public class WorstCaseSearch
// Phase 2: Find a path from the ending node of the valid edge to the target // Phase 2: Find a path from the ending node of the valid edge to the target
var phase2Path = new Dictionary<FlowEdge, double>(); var phase2Path = new Dictionary<FlowEdge, double>();
var phase2Success = FindAugmentingPath(flowGraph, validEdge.Target, target, phase2Path); var phase2Success = FindAugmentingPath(updatedGraph, validEdge.Target, target, phase2Path);
if (!phase2Success) if (!phase2Success)
{ {
...@@ -71,6 +69,21 @@ public class WorstCaseSearch ...@@ -71,6 +69,21 @@ public class WorstCaseSearch
return FindAugmentingPath(flowGraph, source, target, pathFlow); return FindAugmentingPath(flowGraph, source, target, pathFlow);
} }
Console.WriteLine("Phase 1 Path:");
foreach (var kvp in phase1Path)
{
Console.WriteLine($"Edge: {kvp.Key.Source.Id} -> {kvp.Key.Target.Id}, Capacity: {kvp.Value}");
}
Console.WriteLine($"Valid Edge: {validEdge.Source.Id} -> {validEdge.Target.Id}, Residual: {validEdge.Residual}");
Console.WriteLine("Phase 2 Path:");
foreach (var kvp in phase2Path)
{
Console.WriteLine($"Edge: {kvp.Key.Source.Id} -> {kvp.Key.Target.Id}, Capacity: {kvp.Value}");
}
// Combine the results // Combine the results
pathFlow.Clear(); pathFlow.Clear();
foreach (var kvp in phase1Path) foreach (var kvp in phase1Path)
...@@ -101,9 +114,14 @@ public class WorstCaseSearch ...@@ -101,9 +114,14 @@ public class WorstCaseSearch
} }
} }
public bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, bool forceWorstCase = false) private static bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow)
{ {
Console.WriteLine($"Searching for sub-augmenting path from {source.Id} -> {target.Id}"); Console.WriteLine($"Searching for sub-augmenting path from {source.Id} -> {target.Id}");
if (source.Equals(target))
{
return true;
}
// parent map to walk back path // parent map to walk back path
var parentMap = new Dictionary<FlowNode, FlowEdge>(); var parentMap = new Dictionary<FlowNode, FlowEdge>();
...@@ -120,7 +138,7 @@ public class WorstCaseSearch ...@@ -120,7 +138,7 @@ public class WorstCaseSearch
Console.WriteLine("Current Node: " + current); Console.WriteLine("Current Node: " + current);
var outEdges = flowGraph.Graph.OutEdges(current).ToList(); var outEdges = flowGraph.Graph.OutEdges(current).ToList();
List<FlowEdge> sortedOutEdges = forceWorstCase ? outEdges.OrderBy(edge => edge.Residual).ToList() : outEdges.OrderBy(edge => int.Parse(edge.Target.Id)).ToList(); List<FlowEdge> sortedOutEdges = outEdges.OrderBy(edge => int.Parse(edge.Target.Id)).ToList();
Console.WriteLine("Sorted out edges for node:"); Console.WriteLine("Sorted out edges for node:");
foreach (FlowEdge edge in sortedOutEdges) foreach (FlowEdge edge in sortedOutEdges)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment