using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using QuickGraph;
using QuickGraph.Algorithms.ShortestPath;
using System.Diagnostics;
namespace GraphSharp
{
public static class GraphHelper
{
///
/// Returns with the adjacent vertices of the vertex.
///
/// The graph.
/// The vertex which neighbours' we want to get.
/// List of the adjacent vertices of the vertex.
public static IEnumerable GetNeighbours( this IBidirectionalGraph g, TVertex vertex )
where TEdge : IEdge
{
return ( ( from e in g.InEdges( vertex ) select e.Source )
.Concat(
( from e in g.OutEdges( vertex ) select e.Target ) ) ).Distinct();
}
public static IEnumerable GetOutNeighbours( this IVertexAndEdgeListGraph g, TVertex vertex )
where TEdge : IEdge
{
return ( from e in g.OutEdges( vertex )
select e.Target ).Distinct();
}
///
/// If the graph g is directed, then returns every edges which source is one of the vertices in the set1
/// and the target is one of the vertices in set2.
///
/// Type of the vertex.
/// Type of the edge.
/// The graph.
///
///
/// Return the list of the selected edges.
public static IEnumerable GetEdgesBetween( this IVertexAndEdgeListGraph g, List set1, List set2 )
where TEdge : IEdge
{
var edgesBetween = new List();
//vegig kell menni az osszes vertex minden elen, es megnezni, hogy a target hol van
foreach ( TVertex v in set1 )
{
foreach ( TEdge edge in g.OutEdges( v ) )
{
if ( set2.Contains( edge.Target ) )
edgesBetween.Add( edge );
}
}
return edgesBetween;
}
///
/// Returns with the sources in the graph.
///
///
///
/// The graph.
/// Returns with the sources in the graph.
public static IEnumerable GetSources( this IBidirectionalGraph g )
where TEdge : IEdge
{
return from v in g.Vertices
where g.InDegree( v ) == 0
select v;
}
///
/// Gets the diameter of a graph.
/// The diameter is the greatest distance between two vertices.
///
/// The graph.
/// The diameter of the Graph g.
public static float GetDiameter( this Graph g )
where Edge : IEdge
where Graph : IBidirectionalGraph
{
float[,] distances;
return g.GetDiameter( out distances );
}
///
/// Gets the diameter of a graph.
/// The diameter is the greatest distance between two vertices.
///
/// The graph.
/// This is an out parameter. It gives the distances between every vertex-pair.
/// The diameter of the Graph g.
public static float GetDiameter( this Graph g, out float[,] distances )
where Edge : IEdge
where Graph : IBidirectionalGraph
{
distances = GetDistances( g );
int n = g.VertexCount;
float distance = float.NegativeInfinity;
for ( int i = 0; i < n - 1; i++ )
{
for ( int j = i + 1; j < n; j++ )
{
if ( float.MaxValue == distances[i, j] )
continue;
distance = Math.Max( distance, distances[i, j] );
}
}
return distance;
}
/// The graph.
/// Returns with the distance between the vertices (distance: number of the edges).
public static float[,] GetDistances( Graph g )
where Edge : IEdge
where Graph : IBidirectionalGraph
{
var distances = new float[g.VertexCount, g.VertexCount];
for ( int k = 0; k < g.VertexCount; k++ )
{
for ( int j = 0; j < g.VertexCount; j++ )
{
distances[k, j] = float.PositiveInfinity;
}
}
var undirected = new UndirectedBidirectionalGraph( g );
//minden élet egy hosszal veszünk figyelembe - unweighted
var weights = new Dictionary();
foreach ( Edge edge in undirected.Edges )
{
weights[edge] = 1;
}
//compute the distances from every vertex: O(n(n^2 + e)) complexity
int i = 0;
foreach ( Vertex source in g.Vertices )
{
//compute the distances from the 'source'
var spaDijkstra =
new UndirectedDijkstraShortestPathAlgorithm( undirected, edge => weights[edge], ShortestDistanceRelaxer.Instance );
spaDijkstra.Compute( source );
int j = 0;
foreach ( Vertex v in undirected.Vertices )
{
float d = (float) spaDijkstra.Distances[v];
distances[i, j] = Math.Min( distances[i, j], d );
distances[i, j] = Math.Min( distances[i, j], distances[j, i] );
distances[j, i] = Math.Min( distances[i, j], distances[j, i] );
j++;
}
i++;
}
return distances;
}
public static BidirectionalGraph> CreateGraph(
IEnumerable vertices,
IEnumerable edges,
string sourcePropertyName,
string targetPropertyName )
where TVertex : class
{
var graph = new BidirectionalGraph>();
graph.AddVertexRange( vertices );
//get the property infos
System.Reflection.PropertyInfo spi = typeof( TOtherEdge ).GetProperty( sourcePropertyName );
System.Reflection.PropertyInfo tpi = typeof( TOtherEdge ).GetProperty( targetPropertyName );
//creating the new edges
foreach ( TOtherEdge oe in edges )
{
var edge = new Edge(
spi.GetValue( oe, null ) as TVertex,
tpi.GetValue( oe, null ) as TVertex );
graph.AddEdge( edge );
}
return graph;
}
///
/// Creates a new BidirectionalGraph with the given types from the
/// list of vertices, and the list of edges.
///
/// The type of the vertices.
/// The type of the edges in the new graph.
/// The type of the items in the list of the edges.
/// The list of the vertices.
/// The list of the edges.
/// Delegate which converts an edge from the type TOtherEdge
/// to the type TEdge.
/// Parallel edges are allowed or not?.
/// The new BidirectionalGraph
public static BidirectionalGraph CreateGraph(
IEnumerable vertices,
IEnumerable edges,
Func factoryMethod,
bool allowParallelEdges )
where TEdge : IEdge
{
var graph = new BidirectionalGraph( allowParallelEdges );
//add the vertices to the graph
graph.AddVertexRange( vertices );
//create the edges
foreach ( TOtherEdge oe in edges )
{
TEdge e = factoryMethod( oe );
graph.AddEdge( e );
}
return graph;
}
public static BidirectionalGraph CreateGraph(
IEnumerable vertices,
IEnumerable edges,
Func factoryMethod )
where TEdge : IEdge
{
return CreateGraph( vertices, edges, factoryMethod, true );
}
public static TVertex OtherVertex( this IEdge edge, TVertex thisVertex )
{
return edge.Source.Equals( thisVertex ) ? edge.Target : edge.Source;
}
public static void AddEdgeRange( this IMutableEdgeListGraph graph, IEnumerable edges )
where TEdge : IEdge
{
foreach ( var edge in edges )
graph.AddEdge( edge );
}
public static BidirectionalGraph Convert(
this IVertexAndEdgeListGraph oldGraph,
Func vertexMapperFunc,
Func edgeMapperFunc )
where TOldEdge : IEdge
where TNewEdge : IEdge
{
return oldGraph.Convert(
new BidirectionalGraph( oldGraph.AllowParallelEdges, oldGraph.VertexCount ),
vertexMapperFunc,
edgeMapperFunc );
}
public static BidirectionalGraph Convert(
this IVertexAndEdgeListGraph oldGraph,
Func edgeMapperFunc )
where TOldEdge : IEdge
where TNewEdge : IEdge
{
return oldGraph.Convert( null, edgeMapperFunc );
}
public static TNewGraph Convert(
this IVertexAndEdgeListGraph oldGraph,
TNewGraph newGraph,
Func vertexMapperFunc,
Func edgeMapperFunc )
where TOldEdge : IEdge
where TNewEdge : IEdge
where TNewGraph : IMutableVertexAndEdgeListGraph
{
//VERTICES
if ( vertexMapperFunc != null )
newGraph.AddVertexRange( oldGraph.Vertices.Select( vertexMapperFunc ) );
else
newGraph.AddVertexRange( oldGraph.Vertices.Cast() );
//EDGES
if ( edgeMapperFunc != null )
newGraph.AddEdgeRange( oldGraph.Edges.Select( edgeMapperFunc ) );
else
newGraph.AddEdgeRange( oldGraph.Edges.Cast() );
return newGraph;
}
public static TNewGraph Convert(
this IVertexAndEdgeListGraph oldGraph,
TNewGraph newGraph,
Func edgeMapperFunc )
where TOldEdge : IEdge
where TNewEdge : IEdge
where TNewGraph : IMutableVertexAndEdgeListGraph
{
return oldGraph.Convert( newGraph, null, edgeMapperFunc );
}
public static TNewGraph Convert(
this IVertexAndEdgeListGraph oldGraph,
TNewGraph newGraph )
where TOldEdge : IEdge
where TNewGraph : IMutableVertexAndEdgeListGraph
{
return oldGraph.Convert( newGraph, null, null );
}
public static BidirectionalGraph CopyToBidirectionalGraph(
this IVertexAndEdgeListGraph graph)
where TEdge : IEdge
{
var newGraph = new BidirectionalGraph();
//copy the vertices
newGraph.AddVerticesAndEdgeRange(graph.Edges);
return newGraph;
}
}
}