private static void RemoveRefenceCycles(SolvingNode[] nodes) { while (true) { var refList = FindRefNodesGraph(nodes); var arrayOfRefList = refList.ToArray(); var refGraph = ConvertToRefArrayGraph(arrayOfRefList); var refTopology = GraphTools.SortTopology(refGraph); if (!refTopology.HasCycle) { return; } var refCycle = refTopology.NodeNames.Select(n => nodes[n.To]).ToArray(); SolvingFunctions.MergeGroup(refCycle); } }
public static NodeSortResult Toposort(SolvingNode[] nodes) { //На данном этапе - в nodes лежат все узлы участвующие в вычислениях //нужно убрать все циклы с ребрами "равно", что-бы можно было спокойно работать далее //не опасаясь Stackoverflow RemoveRefenceCycles(nodes); //Теперь из графа можно исключить все ребра "равно". Для этого нужно перекинуть //все взаимодействия (Ancestor и Member) на оригинальные узлы // //Это нужно для того что бы можно было провести направленный топосорт MergeAllReferences(nodes, out var refs, out var concretes); var graph = ConvertToArrayGraph(concretes); var sorted = GraphTools.SortTopology(graph); var order = sorted.NodeNames.Select(n => concretes[n.To]).Reverse().ToArray(); return(new NodeSortResult(order, refs, sorted.HasCycle ? sorted.NodeNames.Any(n => n.Type == EdgeType.Member) ? SortStatus.MemebershipCycle : SortStatus.AncestorCycle : SortStatus.Sorted)); }