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

Adds worst case code

parent 1bea2ff2
No related branches found
No related tags found
No related merge requests found
using System;
using System.Collections.Generic;
using System.Linq;
namespace FlowForge;
public class BreadthFirstSearchStrategy : ISearchStrategy
{
public bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, bool forceWorstCase = false)
{
Console.WriteLine("Breadth Depth First Search...");
// parent map to walk back path
var parentMap = new Dictionary<FlowNode, FlowEdge>();
Queue<FlowNode> nodesToVisit = new Queue<FlowNode>();
nodesToVisit.Enqueue(source);
// map to store visited nodes
var visited = new HashSet<FlowNode> {source};
while (nodesToVisit.Any())
{
var current = nodesToVisit.Dequeue();
Console.WriteLine("Current Node: " + current);
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();
Console.WriteLine("Sorted out edges for node:");
foreach (FlowEdge edge in sortedOutEdges)
{
Console.WriteLine($"{edge.Source.Id} -> {edge.Target.Id}, Current Flow: {edge.CurrentFlow}");
}
Console.WriteLine("Looping through:");
List<FlowNode> nodesToAdd = new List<FlowNode>();
// go through all outgoing edges
foreach (FlowEdge currentEdge in sortedOutEdges)
{
if (currentEdge.Residual <= 0 || visited.Contains(currentEdge.Target)) continue;
Console.WriteLine($"{currentEdge.Source.Id} -> {currentEdge.Target.Id}, Current Flow: {currentEdge.CurrentFlow}");
visited.Add(currentEdge.Target);
parentMap.Add(currentEdge.Target, currentEdge);
// if we reached the target node
if (currentEdge.Target.Equals(target))
{
ISearchStrategy.BuildAugmentingPath(source, target, parentMap, pathFlow);
return true;
}
nodesToAdd.Add(currentEdge.Target);
}
foreach (var node in nodesToAdd.OrderBy(n => int.Parse(n.Id)))
{
nodesToVisit.Enqueue(node);
}
}
return false;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
namespace FlowForge;
public class DepthFirstSearchStrategy : ISearchStrategy
{
public bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, bool forceWorstCase = false)
{
if (forceWorstCase)
{
FlowNode? node2 = flowGraph.GetVertexById("2");
FlowNode? node3 = flowGraph.GetVertexById("3");
flowGraph.Graph.TryGetEdge(node2 ?? throw new InvalidOperationException(), node3 ?? throw new InvalidOperationException(), out var edgeFrom2To3);
WorstCaseSearch worstCaseSearch = new WorstCaseSearch();
return worstCaseSearch.FindAugmentingPathWithEdge(flowGraph, source, target, edgeFrom2To3 ?? throw new InvalidOperationException(), pathFlow);
}
// parent map to walk back path
var parentMap = new Dictionary<FlowNode, FlowEdge>();
Stack<FlowNode> nodesToVisit = new Stack<FlowNode>();
nodesToVisit.Push(source);
// map to store visited nodes
var visited = new HashSet<FlowNode>();
while (nodesToVisit.Any())
{
var current = nodesToVisit.Pop();
Console.WriteLine("Current Node: " + current);
// if we reached the target node
if (current.Equals(target))
{
ISearchStrategy.BuildAugmentingPath(source, target, parentMap, pathFlow);
return true;
}
var outEdges = flowGraph.Graph.OutEdges(current).ToList();
List<FlowEdge> sortedOutEdges = outEdges.OrderBy(edge => int.Parse(edge.Target.Id)).ToList();
Console.WriteLine("Sorted out edges for node:");
foreach (FlowEdge edge in sortedOutEdges)
{
Console.WriteLine($"{edge.Source.Id} -> {edge.Target.Id}, Current Flow: {edge.CurrentFlow}");
}
Console.WriteLine("Looping through:");
List<FlowNode> nodesToAdd = new List<FlowNode>();
// go through all outgoing edges
foreach (FlowEdge currentEdge in sortedOutEdges)
{
if (currentEdge.Residual <= 0 || visited.Contains(currentEdge.Target)) continue;
Console.WriteLine($"{currentEdge.Source.Id} -> {currentEdge.Target.Id}, Current Flow: {currentEdge.CurrentFlow}");
parentMap[currentEdge.Target] = currentEdge;
nodesToAdd.Add(currentEdge.Target);
}
foreach (var node in nodesToAdd.OrderByDescending(n => int.Parse(n.Id)))
{
nodesToVisit.Push(node);
}
visited.Add(current);
}
return false;
}
}
......@@ -8,13 +8,7 @@ public class FlowEdge : Edge<FlowNode>
public double CurrentFlow { get; set; }
public double Residual
{
get => MaxFlow - CurrentFlow;
//set => CurrentFlow = MaxFlow - value;
//make the setter private
private set => CurrentFlow = MaxFlow - value;
}
public double Residual => MaxFlow - CurrentFlow;
public bool IsBackwards { get; set; }
public bool IsHighlighted { get; set; }
......
......@@ -26,7 +26,7 @@ public class FordFulkersonAlgorithm
this.TargetId = targetId;
}
public double Run(SearchStrategy strategy=SearchStrategy.BreadthFirstSearch)
public double Run(ISearchStrategy strategy, bool forceWorstCase = false)
{
// get source and target nodes
FlowNode? source = _flowGraph.GetVertexById(SourceId);
......@@ -37,6 +37,10 @@ public class FordFulkersonAlgorithm
throw new ArgumentException("Invalid source or target node!");
}
Console.WriteLine("Start of Ford-Fulkerson Algorithm...");
if (forceWorstCase)
{
Console.WriteLine("Using worst case scenario for edge selection.");
}
double maxFlow = 0.0;
var pathFlow = new Dictionary<FlowEdge, double>();
......@@ -47,7 +51,7 @@ public class FordFulkersonAlgorithm
SaveGraphState();
// execute as long as there is an augmenting path
while (strategy == SearchStrategy.BreadthFirstSearch ? FindAugmentingPathBfs(source, target, pathFlow) : FindAugmentingPathDfs(source, target, pathFlow))
while (strategy.FindAugmentingPath(_flowGraph, source, target, pathFlow, forceWorstCase))
{
PrintOrderedPath(pathFlow);
......@@ -132,137 +136,6 @@ public class FordFulkersonAlgorithm
return pathMinFlow;
}
private bool FindAugmentingPathBfs(FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow)
{
// parent map to walk back path
var parentMap = new Dictionary<FlowNode, FlowEdge>();
Queue<FlowNode> nodesToVisit = new Queue<FlowNode>();
nodesToVisit.Enqueue(source);
// map to store visited nodes
var visited = new HashSet<FlowNode> {source};
while (nodesToVisit.Any())
{
var current = nodesToVisit.Dequeue();
Console.WriteLine("Current Node: " + current);
var outEdges = _flowGraph.Graph.OutEdges(current).ToList();
List<FlowEdge> sortedOutEdges = outEdges.OrderBy(edge => int.Parse(edge.Target.Id)).ToList();
Console.WriteLine("Sorted out edges for node:");
foreach (FlowEdge edge in sortedOutEdges)
{
Console.WriteLine($"{edge.Source.Id} -> {edge.Target.Id}, Current Flow: {edge.CurrentFlow}");
}
Console.WriteLine("Looping through:");
List<FlowNode> nodesToAdd = new List<FlowNode>();
// go through all outgoing edges
foreach (FlowEdge currentEdge in sortedOutEdges)
{
if (currentEdge.Residual <= 0 || visited.Contains(currentEdge.Target)) continue;
Console.WriteLine($"{currentEdge.Source.Id} -> {currentEdge.Target.Id}, Current Flow: {currentEdge.CurrentFlow}");
visited.Add(currentEdge.Target);
parentMap.Add(currentEdge.Target, currentEdge);
// if we reached the target node
if (currentEdge.Target.Equals(target))
{
BuildAugmentingPath(source, target, parentMap, pathFlow);
return true;
}
nodesToAdd.Add(currentEdge.Target);
}
foreach (var node in nodesToAdd.OrderBy(n => int.Parse(n.Id)))
{
nodesToVisit.Enqueue(node);
}
}
return false;
}
private bool FindAugmentingPathDfs(FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow)
{
// parent map to walk back path
var parentMap = new Dictionary<FlowNode, FlowEdge>();
Stack<FlowNode> nodesToVisit = new Stack<FlowNode>();
nodesToVisit.Push(source);
// map to store visited nodes
var visited = new HashSet<FlowNode>();
while (nodesToVisit.Any())
{
var current = nodesToVisit.Pop();
Console.WriteLine("Current Node: " + current);
// if we reached the target node
if (current.Equals(target))
{
BuildAugmentingPath(source, target, parentMap, pathFlow);
return true;
}
var outEdges = _flowGraph.Graph.OutEdges(current).ToList();
List<FlowEdge> sortedOutEdges = outEdges.OrderBy(edge => int.Parse(edge.Target.Id)).ToList();
Console.WriteLine("Sorted out edges for node:");
foreach (FlowEdge edge in sortedOutEdges)
{
Console.WriteLine($"{edge.Source.Id} -> {edge.Target.Id}, Current Flow: {edge.CurrentFlow}");
}
Console.WriteLine("Looping through:");
List<FlowNode> nodesToAdd = new List<FlowNode>();
// go through all outgoing edges
foreach (FlowEdge currentEdge in sortedOutEdges)
{
if (currentEdge.Residual <= 0 || visited.Contains(currentEdge.Target)) continue;
Console.WriteLine($"{currentEdge.Source.Id} -> {currentEdge.Target.Id}, Current Flow: {currentEdge.CurrentFlow}");
parentMap[currentEdge.Target] = currentEdge;
nodesToAdd.Add(currentEdge.Target);
}
foreach (var node in nodesToAdd.OrderByDescending(n => int.Parse(n.Id)))
{
nodesToVisit.Push(node);
}
visited.Add(current);
}
return false;
}
private static void BuildAugmentingPath(FlowNode source, FlowNode target, Dictionary<FlowNode, FlowEdge> parentMap, Dictionary<FlowEdge, double> pathFlow)
{
FlowNode currentNode = target;
pathFlow.Clear();
while (currentNode != source)
{
FlowEdge pathEdge = parentMap[currentNode];
pathFlow[pathEdge] = pathEdge.Residual;
currentNode = pathEdge.Source;
}
}
private static void PrintOrderedPath(Dictionary<FlowEdge, double> pathFlow)
{
Console.WriteLine("Augmenting Path found:");
......
using System.Collections.Generic;
namespace FlowForge;
public interface ISearchStrategy
{
bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, bool forceWorstCase = false);
public static void BuildAugmentingPath(FlowNode source, FlowNode target, Dictionary<FlowNode, FlowEdge> parentMap, Dictionary<FlowEdge, double> pathFlow)
{
FlowNode currentNode = target;
pathFlow.Clear();
while (currentNode != source)
{
FlowEdge pathEdge = parentMap[currentNode];
pathFlow[pathEdge] = pathEdge.Residual;
currentNode = pathEdge.Source;
}
}
}
......@@ -155,7 +155,8 @@ namespace FlowForge
//SaveNodePositions(_gViewer.Graph); // Save positions before running the algorithm
double maxFlow = _fordFulkerson.Run(FordFulkersonAlgorithm.SearchStrategy.DepthFirstSearch);
bool forceWorstCase = WorstCaseCheckbox.IsChecked ?? false;
double maxFlow = _fordFulkerson.Run(new DepthFirstSearchStrategy(), forceWorstCase);
_isInitialized = true;
DisplayGraph();
......@@ -173,7 +174,9 @@ namespace FlowForge
if (_gViewer != null) _gViewer.NeedToCalculateLayout = true;
SaveNodePositions(_gViewer?.Graph); // Save positions before running the algorithm
double maxFlow = _fordFulkerson.Run(FordFulkersonAlgorithm.SearchStrategy.BreadthFirstSearch);
bool forceWorstCase = WorstCaseCheckbox.IsChecked ?? false;
double maxFlow = _fordFulkerson.Run(new BreadthFirstSearchStrategy(), forceWorstCase);
_isInitialized = true;
DisplayGraph();
......
using System;
using System.Collections.Generic;
using System.Linq;
namespace FlowForge;
public class WorstCaseSearch
{
public bool FindAugmentingPathWithEdge(FlowGraph flowGraph, FlowNode source, FlowNode target, FlowEdge requiredEdge, Dictionary<FlowEdge, double> pathFlow)
{
Console.WriteLine($"Searching for augmenting path that includes edge {requiredEdge.Source.Id} -> {requiredEdge.Target.Id}");
// Determine if the required edge is valid in either direction
FlowEdge? validEdge = null;
bool isReversed = false;
if (requiredEdge.Residual > 0)
{
validEdge = requiredEdge;
}
else if (flowGraph.Graph.TryGetEdge(requiredEdge.Target, requiredEdge.Source, out validEdge))
{
if (validEdge.Residual > 0)
{
isReversed = true;
}
else
{
validEdge = null;
}
}
else
{
validEdge = null;
}
if (validEdge == null)
{
Console.WriteLine("No valid residual capacity on the required edge in either direction.");
return FindAugmentingPath(flowGraph, source, target, pathFlow);
}
// Phase 1: Find a path from source to the starting node of the valid edge
var phase1Path = new Dictionary<FlowEdge, double>();
var phase1Success = FindAugmentingPath(flowGraph, source, isReversed ? validEdge.Target : validEdge.Source, phase1Path);
if (!phase1Success)
{
Console.WriteLine("No path found from source to the required edge.");
return FindAugmentingPath(flowGraph, source, target, pathFlow);
}
// Phase 2: Find a path from the ending node of the valid edge to the target
var phase2Path = new Dictionary<FlowEdge, double>();
var phase2Success = FindAugmentingPath(flowGraph, isReversed ? validEdge.Source : validEdge.Target, target, phase2Path);
if (!phase2Success)
{
Console.WriteLine("No path found from the required edge to the target.");
return FindAugmentingPath(flowGraph, source, target, pathFlow);
}
// Combine the results
pathFlow.Clear();
foreach (var kvp in phase1Path)
{
pathFlow[kvp.Key] = kvp.Value;
}
pathFlow[validEdge] = validEdge.Residual; // Include the required edge
foreach (var kvp in phase2Path)
{
pathFlow[kvp.Key] = kvp.Value;
}
Console.WriteLine("Augmenting path including the required edge found!");
return true;
}
private bool FindAugmentingPath(FlowGraph flowGraph, FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow)
{
// parent map to walk back path
var parentMap = new Dictionary<FlowNode, FlowEdge>();
Stack<FlowNode> nodesToVisit = new Stack<FlowNode>();
nodesToVisit.Push(source);
// map to store visited nodes
var visited = new HashSet<FlowNode>();
while (nodesToVisit.Any())
{
var current = nodesToVisit.Pop();
Console.WriteLine("Current Node: " + current);
// if we reached the target node
if (current.Equals(target))
{
ISearchStrategy.BuildAugmentingPath(source, target, parentMap, pathFlow);
return true;
}
var outEdges = flowGraph.Graph.OutEdges(current).ToList();
List<FlowEdge> sortedOutEdges = outEdges.OrderBy(edge => int.Parse(edge.Target.Id)).ToList();
Console.WriteLine("Sorted out edges for node:");
foreach (FlowEdge edge in sortedOutEdges)
{
Console.WriteLine($"{edge.Source.Id} -> {edge.Target.Id}, Current Flow: {edge.CurrentFlow}");
}
Console.WriteLine("Looping through:");
List<FlowNode> nodesToAdd = new List<FlowNode>();
// go through all outgoing edges
foreach (FlowEdge currentEdge in sortedOutEdges)
{
if (currentEdge.Residual <= 0 || visited.Contains(currentEdge.Target)) continue;
Console.WriteLine($"{currentEdge.Source.Id} -> {currentEdge.Target.Id}, Current Flow: {currentEdge.CurrentFlow}");
parentMap[currentEdge.Target] = currentEdge;
nodesToAdd.Add(currentEdge.Target);
}
foreach (var node in nodesToAdd.OrderByDescending(n => int.Parse(n.Id)))
{
nodesToVisit.Push(node);
}
visited.Add(current);
}
return false;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment