Skip to content

Commit

Permalink
#7 remove old stuff, added unittests
Browse files Browse the repository at this point in the history
  • Loading branch information
mfe- committed Dec 25, 2019
1 parent e8a6a37 commit ef2fd66
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 159 deletions.
53 changes: 9 additions & 44 deletions Algorithms.Graph/Edge.Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using DataStructures;
using System.Collections.Generic;


namespace Algorithms.Graph
{
Expand All @@ -9,58 +7,25 @@ namespace Algorithms.Graph
/// </summary>
public static class EdgeExtensions
{
public class EdgeComparer : IEqualityComparer<IEdge>
{
#region IEqualityComparer
/// <summary>
/// Returns a value indicating whether this instance is equal to the edge. Transposed edges will be handled as equal edge.
/// http://msdn.microsoft.com/en-us/library/bb338049(v=vs.100).aspx
/// </summary>
/// <param name="x">edge x</param>
/// <param name="y">edge y</param>
/// <returns></returns>
public bool Equals(IEdge e1, IEdge e2)
{
//edge are equal
if (e1.Equals(e2) && e2.Equals(e1)) return true;

//edges are not equal but transposed (e1: v1->v2 e2: v2->v1 )
if ((e1.Equals(e2) && e2.Equals(e1)).Equals(false) &&
(EdgeExtensions.Equals(e1, e2, true) && EdgeExtensions.Equals(e1, e2, true)).Equals(true)) return true;

//diffrent edges
return false;
}

public int GetHashCode(IEdge obj)
{
return obj.GetHashCode();
}
#endregion
}
/// <summary>
/// Returns a value indicating whether this instance is equal to the edge.
/// </summary>
/// <param name="edge">The edge to compare to this instance.</param>
/// <param name="permute">If the parameter is true transported edges will be handled as equal</param>
/// <param name="graphIsdirected">If the parameter is false transported edges will be handled as equal</param>
/// <returns>True if the instance and the overgiven edge are euqa; otherwiese, false.</returns>
public static bool Equals(this IEdge e, IEdge edge, bool permute)
public static bool Equals(this IEdge e, IEdge edge, bool graphIsdirected = true)
{
if (permute)
//(use == operator instead of Equals for directed graphs,
//as the overriden equals of the edge implementeation returns true for transposed edges)
if (!graphIsdirected)
{
if (!e.U.Equals(edge.V)) return false;
if (!e.V.Equals(edge.U)) return false;
if (!e.Weighted.Equals(edge.Weighted)) return false;
if (!e.GetHashCode().Equals(edge.GetHashCode())) return false;
return true;
//transposed edges uses the hash of the internal guids of the vertices
if (e != null) return e.Equals(edge);
return false;
}
else
{
if (!e.U.Equals(edge.U)) return false;
if (!e.V.Equals(edge.V)) return false;
if (!e.Weighted.Equals(edge.Weighted)) return false;
if (!e.GetHashCode().Equals(edge.GetHashCode())) return false;
return true;
return e == edge;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Algorithms.Graph/Graph.Extensions.Xml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static DataContractSerializerSettings GetDataContractSerializerSettings()
{
return GetDataContractSerializerSettings(new List<Type>());
}
public static DataContractSerializerSettings GetDataContractSerializerSettings(List<Type> knownTypes = null, DataContractResolver dataContractResolver = null)
public static DataContractSerializerSettings GetDataContractSerializerSettings(List<Type> knownTypes, DataContractResolver dataContractResolver = null)
{
List<Type> types = new List<Type>() { typeof(Vertex<object>), typeof(Edge<object>) };
if (knownTypes != null)
Expand Down Expand Up @@ -80,6 +80,7 @@ public static void Load(this DataStructures.Graph g, String pfilename, int maxDe
}
public static DataStructures.Graph Load(this XElement e, Action<DataContractSerializerSettings> DataContractSerializerSettingsActionInvokrer = null)
{
if (e == null) throw new ArgumentNullException(nameof(e));
DataStructures.Graph g = new DataStructures.Graph();
//load graph
MemoryStream memoryStream = new MemoryStream();
Expand Down
110 changes: 37 additions & 73 deletions Algorithms.Graph/Graph.Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ namespace Algorithms.Graph
/// </summary>
public static partial class GraphExtensions
{
/// <summary>
/// Determines whether the graph is directed or undirected.
/// Uses the <seealso cref="AdjacencyMatrix"/> to generate a matrix and checks whether its a symmetric
/// </summary>
/// <param name="g"></param>
/// <returns></returns>
public static bool IsDirected(this DataStructures.Graph g)
{
//schauen ob alle vertex jeweils 2mal verbudnen sind also 1->2 und 2->1 nur dann ist es directed=false ansonsten directed=true
Expand All @@ -18,7 +24,7 @@ public static bool IsDirected(this DataStructures.Graph g)
//also ist der graph genau dann ungerichtet wenn die matrix symmetrisch ist
//http://en.wikipedia.org/wiki/Transpose
//a transportieren also a^t = a symmetrisch
int[][] matrix = g.AdjacencyList();
int[][] matrix = g.AdjacencyMatrix();
int[][] matrixT = new int[matrix.Length][];
for (int i = 0; i < matrix.Length; i++)
{
Expand Down Expand Up @@ -66,35 +72,40 @@ public static IEdge GetOppositeEdge(this IEdge edge)
}
/// <summary>
/// Returns all vertices from the graph
/// http://www.brpreiss.com/books/opus4/html/page551.html
/// http://www.cse.ohio-state.edu/~gurari/course/cis680/cis680Ch14.html#QQ1-46-90
/// </summary>
/// <param name="s">Root IVertex of graph</param>
/// <returns>All reachable vertices</returns>
public static IEnumerable<IVertex> DepthFirstTraversal(this DataStructures.Graph s)
{
if (s == null) throw new ArgumentNullException(nameof(s));
List<IVertex> l = new List<IVertex>();
IEnumerable<IVertex> l = Enumerable.Empty<IVertex>();
foreach (IVertex v in s.Vertices)
l.AddRange(DepthFirstTraversal(v, new List<IVertex>()));
{
var verticeList = DepthFirstTraversal(v, new List<IVertex>());
l = l.Union(verticeList);
}
return l;
}
private static List<IVertex> DepthFirstTraversal(this IVertex s, List<IVertex> visited)
{
//visist x
visited.Add(s);

//FOR each y such that (x,y) is an IEdge DO
foreach (IEdge e in s.Edges)
{
if (!visited.Contains(e.V))
{
visited = DepthFirstTraversal(e.V, visited);
DepthFirstTraversal(e.V, visited);
}
}
return visited;
}
public static IEnumerable<IVertex> DephFirstSearch(this IVertex s)
/// <summary>
/// DepthFirstSearch implemented as Stack
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static IEnumerable<IVertex> DepthFirstSearchStack(this IVertex s)
{
List<IVertex> visited = new List<IVertex>();

Expand All @@ -105,14 +116,15 @@ public static IEnumerable<IVertex> DephFirstSearch(this IVertex s)
while (stack.Count != 0)
{
IVertex v = stack.Pop();
visited.Add(v);
foreach (IEdge e in v.Edges)
if (!visited.Contains(v))
{
if (!visited.Contains(e.V))
visited.Add(v);
foreach (IEdge e in v.Edges)
{
stack.Push(e.V);
}
}

}

return visited;
Expand All @@ -126,9 +138,9 @@ public static IEnumerable<IVertex> DephFirstSearch(this IVertex s)
/// </summary>
/// <param name="g">Graph on which the adjacency list should be created</param>
/// <returns></returns>
public static int[][] AdjacencyList(this DataStructures.Graph g)
public static int[][] AdjacencyMatrix(this DataStructures.Graph g)
{
var vertices = DepthFirstTraversal(g).Sort().Distinct().ToArray();
var vertices = DepthFirstTraversal(g).Sort().ToArray();
//create matrix
int c = vertices.Length;
int[][] m = new int[c][];
Expand Down Expand Up @@ -159,6 +171,7 @@ public static int[][] AdjacencyList(this DataStructures.Graph g)

public static DataStructures.Graph KruskalDepthFirstSearch(this DataStructures.Graph g)
{
if (g == null) throw new ArgumentNullException(nameof(g));
//works only with undircted graphs
if (g.Directed.Equals(true))
throw new ArgumentException("Graph is not undirected");
Expand All @@ -167,8 +180,12 @@ public static DataStructures.Graph KruskalDepthFirstSearch(this DataStructures.G
DataStructures.Graph g_ = g;

List<IVertex> vertices = new List<IVertex>();
//order IEdges by pyramiding weighted
IEdge[] IEdges = DepthFirstTraversal(g).SelectMany(a => a.Edges).OrderBy(e => e.Weighted).Distinct(new EdgeExtensions.EdgeComparer()).ToArray();
//order IEdges by pyramiding weighted, distinct them
IEdge[] IEdges = DepthFirstTraversal(g).
SelectMany(a => a.Edges).
OrderBy(e => e.Weighted).
Distinct().
ToArray();
//remove IEdges
foreach (IVertex z in g_.DepthFirstTraversal())
{
Expand All @@ -189,7 +206,7 @@ public static DataStructures.Graph KruskalDepthFirstSearch(this DataStructures.G
v.AddEdge(u, e.Weighted);
//check if circle

var o = DepthFirstSearch(u, u);
var o = DepthFirstSearch(u, u, false);

if (o.First().U.Equals(u) && o.Last().V.Equals(u))
{
Expand All @@ -212,58 +229,22 @@ public static DataStructures.Graph KruskalDepthFirstSearch(this DataStructures.G
public static IEnumerable<IEdge> DepthFirstSearch(this IVertex start, IVertex goal = null, bool graphIsdirected = true)
{
if (start == null) throw new ArgumentNullException(nameof(start));
if (graphIsdirected)
{
return DepthFirstSearchDirected(start, new List<IEdge>(), goal);
}
else
{
return DepthFirstSearchUndirected(start, new List<IEdge>(), goal);
}
return DepthFirstSearch(start, new List<IEdge>(), goal, graphIsdirected);
}
private static IEnumerable<IEdge> DepthFirstSearchUndirected(IVertex current, List<IEdge> edges, IVertex goal)
private static IEnumerable<IEdge> DepthFirstSearch(IVertex current, List<IEdge> edges, IVertex goal, bool graphIsdirected)
{
foreach (IEdge e in current.Edges)
{
if (!edges.Any(a => a.Equals(e)))
if (!edges.Any(a => EdgeExtensions.Equals(a, e, graphIsdirected)))
{
//mark edges
edges.Add(e);
DepthFirstSearchUndirected(e.V, edges, goal);
DepthFirstSearch(e.V, edges, goal, graphIsdirected);
}
if (edges.Any() && edges.Last().V.Equals(goal)) return edges;
}

return edges;
}
private static IEnumerable<IEdge> DepthFirstSearchDirected(IVertex current, List<IEdge> edges, IVertex goal)
{
foreach (IEdge e in current.Edges)
{
//check if already visited IVertex
//(use == operator instead of Equals for directed graphs,
//as the overriden equals of the Edge implementeation returns true for transposed edges)
if (!edges.Any(a => a == e))
{
//mark edges
edges.Add(e);
DepthFirstSearchDirected(e.V, edges, goal);
}
if (edges.Any() && edges.Last().V.Equals(goal)) return edges;
}
return edges;
}

/// <summary>
/// Determinds if the overgiven <paramref name="v"/> is adjacent to the current IVertex
/// </summary>
/// <param name="v">the IVertex to check</param>
/// <returns>True if the overgiven IVertex is adjacent</returns>
public static Boolean Adjacent(this IVertex v)
{
if (v == null) throw new ArgumentNullException(nameof(v));
return !v.Edges.Any(a => a.U.Equals(v) || a.V.Equals(v));
}
/// <summary>
/// Calculates the distance by summing the weighted of the IEdges.
/// </summary>
Expand All @@ -279,22 +260,5 @@ public static int Distance(this IEnumerable<IEdge> edges)

return distance;
}


public static object Connected(this DataStructures.Graph g, IVertex a, IVertex b)
{
// Eine Folge von karten e1,e2,...ek e E(G) eines ungerichteten G heißt katenfolge , wenn es knoten v,v1,v2,...vk1 w eV(G) mit
//% gibt ,d.h. man kann die katen e1,2,...ek,ohne absetzen durchlafeun. k... anzahl der kanten
//Tiefensuchen hier nehmen Katenfolge von a -> b zurück geben
return null;
}
//public static bool Connected(this Graph g, IVertex a, IVertex b)
//{
// // Eine Folge von karten e1,e2,...ek e E(G) eines ungerichteten G heißt katenfolge , wenn es knoten v,v1,v2,...vk1 w eV(G) mit
// //% gibt ,d.h. man kann die katen e1,2,...ek,ohne absetzen durchlafeun. k... anzahl der kanten
// //Tiefensuchen hier nehmen Katenfolge von a -> b zurück geben
// //return g.Connected(a,b) ==null ? false : true;
// return false;
//}
}
}
25 changes: 0 additions & 25 deletions Algorithms.Graph/Vertex.cs

This file was deleted.

Loading

0 comments on commit ef2fd66

Please sign in to comment.