Есть проблема с алгоритмом -
искомый подграф - subGraph
граф в котором ищем - graph
1* берем любую вершину в subGraph - v1
2* проходим по вершинам в graph и ищем одинаковую v1 вершину - v2, если нашли в 3*
3* Если v1 уже содержится в результате то пропускаем эту итерацию.
Берём все исходящие вершины из v2 в graph и v1 в subGraph и ищем пересечение этих множеств.
Если множество пусто(для какой либо из вершины v1 нет соответствующей v2) говорим что весь этот вариант не подходит иначе добавляем v1 и v2 в результат.
Идём в 4*
4* Выделяем это пересечение и по циклу с каждой парой вершин(или сответсвием одной вершины в subGraph с несколькими вершинами в graph) идём в 3*.
В итоге формируется всё множество подходящих подгафов в graph подграфу subGraph и затираются неподходящие(на каком-то шаге).
Проблема появилась с подграфом вида - http://xmages.net/show.php/1945929_123-jpg.html
Понимаю, что мало кому захочется разбираться, но может кто-то из присутствующих уже делал такое и может поделиться опытом(грабли какие там могут быть или ещё что).
п.с. циклы в графах я нахожу поиском вершины в уже добавленных
namespace OFTD.DOM.Graph
{
public static class UndirectedGraphExtensions
{
public static IEnumerable<IDictionary<TVertex, TVertex>> SearchSubgraphs<TVertex, TEdge>(
IUndirectedGraph<TVertex, TEdge> graph,
IUndirectedGraph<TVertex, TEdge> visitedGraph)
where TEdge : IUndirectedEdge<TVertex>
where TVertex : Element
{
var allMatches = new List<List<Dictionary<TVertex, TVertex>>>();
if ((graph.Vertices.Count() == 0) || (visitedGraph.Vertices.Count() == 0))
return new List<IDictionary<TVertex, TVertex>>();// allMatches;
var firstInVisited = visitedGraph.Vertices.First();
foreach (var v in graph.Vertices)
{
if (equalp(v, firstInVisited))
{
var dict = new Dictionary<TVertex, TVertex>();
var matchesFromThisVertex = new List<Dictionary<TVertex, TVertex>>();
matchesFromThisVertex.Add(dict);
allMatches.Add(matchesFromThisVertex);
searchIterations(ref matchesFromThisVertex, 0, graph, visitedGraph, firstInVisited, v, null, null);
}
}
foreach (var list in allMatches)
{
list.RemoveAll(removeAllNullsDictionary);
}
allMatches.RemoveAll(removeAllEmptyList);
var result = new List<IDictionary<TVertex, TVertex>>();
foreach (var list in allMatches)
foreach (var dictionary in list)
result.Add(dictionary);
return result;
}
private static bool removeAllNullsDictionary<TVertex>(Dictionary<TVertex,TVertex> dict)
where TVertex : Element
{
return (Equals(dict, null) || (dict.Count < 20));
}
private static bool removeAllEmptyList<TVertex>(List<Dictionary<TVertex, TVertex>> list)
where TVertex : Element
{
return (list.Count == 0) ? true : false;
}
public static void searchIterations<TVertex, TEdge>(ref List<Dictionary<TVertex, TVertex>> matchs, int matchIndex,
IUndirectedGraph<TVertex, TEdge> graph,
IUndirectedGraph<TVertex, TEdge> visitedGraph,
TVertex vgVert, TVertex gVert, TVertex previousVertexVg, TVertex previousVertexG)
where TEdge : IUndirectedEdge<TVertex>
where TVertex : Element
{
if(matchs.ElementAt(matchIndex) == null)
return;
if(matchs.ElementAt(matchIndex).ContainsKey(vgVert))
return;
matchs.ElementAt(matchIndex).Add(vgVert, gVert);
var vgEdgesOuts = visitedGraph.AdjacentEdges(vgVert).ToList();
var gEdgesOuts = graph.AdjacentEdges(gVert).ToList();
var vgVertsOuts = getOutVertexes(vgVert, vgEdgesOuts);
var gVertsOuts = getOutVertexes(gVert, gEdgesOuts);
if(previousVertexVg != null)
{
vgVertsOuts.Remove(previousVertexVg);
gVertsOuts.Remove(previousVertexG);
}
if (vgVertsOuts.Count == 0)
return;
if(gVertsOuts.Count == 0)
{
matchs[matchIndex] = null;
return;
}
var intersectionsV = groupIntersectionVerts(vgVertsOuts, gVertsOuts);
if(intersectionsV == null)
{
matchs[matchIndex] = null;
return;
}
var indexNext = matchIndex;
foreach (var list in intersectionsV)
{
var tmpList = new List<TVertex>(list);
tmpList.RemoveAt(0);
foreach (var vertexInG in tmpList)
{
if (indexNext > matchIndex)
{
var clonedDict = new Dictionary<TVertex, TVertex>(matchs.ElementAt(matchIndex));
matchs.Add(clonedDict);
}
searchIterations(ref matchs, indexNext, graph, visitedGraph, list.First(), vertexInG, vgVert, gVert);
indexNext++;
}
}
}
private static List<TVertex> getOutVertexes<TVertex, TEdge>(TVertex previousVert, List<TEdge> outsEdges)
where TEdge : IUndirectedEdge<TVertex>
where TVertex : Element
{
var outsVerts = new List<TVertex>();
foreach (var edge in outsEdges)
{
if(edge.Source == previousVert)
outsVerts.Add(edge.Target);
else
outsVerts.Add(edge.Source);
}
return outsVerts;
}
private static List<List<TVertex>> groupIntersectionVerts<TVertex>(List<TVertex> vs, List<TVertex> v)
where TVertex : Element
{
var allIntersections = new List<List<TVertex>>();
foreach (var svertex in vs)
{
var intersection = new List<TVertex>();
intersection.Add(svertex);
foreach (var vertex in v)
{
if(equalp(svertex, vertex))
intersection.Add(vertex);
}
if (intersection.Count == 1)
return null;
allIntersections.Add(intersection);
}
return allIntersections;
}
private static bool equalp<TVertex> (TVertex v1, TVertex v2)
where TVertex : Element
{
return (string.Equals(v1.XmlName, v2.XmlName));
}
}
}