private PartialDecomposition(PartialDecomposition oldDecomposition, List <TNode> chain, bool isFromFace) { coveredVertices = new Dictionary <TNode, int>(oldDecomposition.coveredVertices); // Cover chain var numberOfChains = oldDecomposition.NumberOfChains; foreach (var node in chain) { coveredVertices[node] = numberOfChains; } // Remove covered faces remainingFaces = oldDecomposition .remainingFaces .Where(face => face.Any(node => !coveredVertices.ContainsKey(node))) .ToList(); chains = oldDecomposition.chains.Select(x => new Chain <TNode>(x.Nodes.ToList(), x.Number) { IsFromFace = x.IsFromFace }).ToList(); chains.Add(new Chain <TNode>(chain, chains.Count) { IsFromFace = isFromFace, }); }
private GraphComponent GetCycleComponent(PartialDecomposition decomposition, List <TNode> face) { var nodes = new List <TNode>(); var notCoveredNodes = face.Where(x => !decomposition.IsCovered(x)).ToList(); var nodeOrder = new Dictionary <TNode, int>(); while (notCoveredNodes.Count != 0) { var nodeIndex = notCoveredNodes .MinBy( x => Graph .GetNeighbours(x) .Min(y => decomposition.IsCovered(y) ? -1 : nodeOrder.ContainsKey(y) ? nodeOrder[y] : int.MaxValue)); nodeOrder[notCoveredNodes[nodeIndex]] = nodeOrder.Count; nodes.Add(notCoveredNodes[nodeIndex]); notCoveredNodes.RemoveAt(nodeIndex); } return(new GraphComponent() { Nodes = nodes, IsFromFace = true, MinimumNeighborChainNumber = GetMinimumNeighborChainNumber(decomposition, nodes), }); }
/// <inheritdoc /> public override List <Chain <TNode> > GetChains(IGraph <TNode> graph) { Initialize(graph); if (Faces.Count != 0) { // Get faces and remove the largest one Faces.RemoveAt(Faces.MaxBy(x => x.Count)); } var decomposition = new PartialDecomposition(Faces); decomposition = GetFirstComponent(decomposition); while (decomposition.GetAllCoveredVertices().Count != Graph.VerticesCount) { decomposition = ExtendDecomposition(decomposition); } var chains = decomposition.GetFinalDecomposition(); logger.WriteLine("Final decomposition:"); foreach (var chain in chains) { logger.WriteLine($"[{string.Join(",", chain.Nodes)}]"); } return(chains); }
private GraphComponent GetTreeComponent(PartialDecomposition decomposition, TNode startingNode) { return(GetTreeComponent(decomposition, new List <TNode>() { startingNode })); }
private int GetMinimumNeighborChainNumber(PartialDecomposition decomposition, List <TNode> nodes) { var coveredNeighbors = nodes .SelectMany(Graph.GetNeighbours) .Where(decomposition.IsCovered) .ToList(); if (coveredNeighbors.Count != 0) { return(coveredNeighbors.Min(decomposition.GetChainNumber)); } return(-1); }
private GraphComponent GetTreeComponent(PartialDecomposition decomposition, List <TNode> startingNodes) { switch (treeComponentStrategy) { case TreeComponentStrategy.BreadthFirst: return(GetBfsTreeComponent(decomposition, startingNodes)); case TreeComponentStrategy.DepthFirst: return(GetDfsTreeComponent(decomposition, startingNodes)); default: throw new ArgumentOutOfRangeException(); } }
private GraphComponent GetDfsTreeComponent(PartialDecomposition decomposition, List <TNode> startingNodes) { var nodes = new List <TNode>(); var stack = new Stack <TNode>(); nodes.AddRange(startingNodes); foreach (var startingNode in startingNodes) { stack.Push(startingNode); } while (stack.Count != 0 && nodes.Count < maxTreeSize) { var node = stack.Pop(); if (decomposition.GetRemainingFaces().Any(x => x.Contains(node))) { continue; } var neighbors = Graph.GetNeighbours(node); foreach (var neighbor in neighbors) { if (!nodes.Contains(neighbor) && !decomposition.IsCovered(neighbor)) { nodes.Add(neighbor); stack.Push(neighbor); if (nodes.Count >= maxTreeSize) { break; } } } } return(new GraphComponent() { Nodes = nodes, IsFromFace = false, MinimumNeighborChainNumber = GetMinimumNeighborChainNumber(decomposition, nodes), }); }
private PartialDecomposition GetFirstComponent(PartialDecomposition decomposition) { var faces = decomposition.GetRemainingFaces(); if (Faces.Count != 0) { List <TNode> firstFace; if (preferSmallCycles) { var smallestFaceIndex = faces.MinBy(x => x.Count); firstFace = faces[smallestFaceIndex]; } else { var largestFaceIndex = faces.MaxBy(x => x.Count); firstFace = faces[largestFaceIndex]; } var cycleComponent = new GraphComponent() { Nodes = firstFace, IsFromFace = true, MinimumNeighborChainNumber = 0, }; logger.WriteLine("Starting with cycle"); logger.WriteLine(cycleComponent); return(decomposition.AddChain(cycleComponent.Nodes, true)); } var startingNode = Graph.Vertices.First(x => Graph.GetNeighbours(x).Count() == 1); var treeComponent = GetTreeComponent(decomposition, startingNode); logger.WriteLine("Starting with tree"); logger.WriteLine(treeComponent); return(decomposition.AddChain(treeComponent.Nodes, false)); }
private PartialDecomposition ExtendDecomposition(PartialDecomposition decomposition) { var remainingFace = decomposition.GetRemainingFaces(); var blacklist = new List <TNode>(); var components = new List <GraphComponent>(); foreach (var node in decomposition.GetAllCoveredVertices()) { var neighbors = Graph.GetNeighbours(node); var notCoveredNeighbors = neighbors.Where(x => !decomposition.IsCovered(x)); var treeStartingNodes = new List <TNode>(); foreach (var neighbor in notCoveredNeighbors) { if (blacklist.Contains(neighbor)) { continue; } var foundFace = false; foreach (var face in remainingFace) { if (!face.Contains(neighbor)) { continue; } var cycleComponent = GetCycleComponent(decomposition, face); components.Add(cycleComponent); blacklist.AddRange(cycleComponent.Nodes); foundFace = true; break; } if (foundFace) { continue; } treeStartingNodes.Add(neighbor); } if (treeStartingNodes.Count != 0) { if (startTreeWithMultipleVertices) { var treeComponent = GetTreeComponent(decomposition, treeStartingNodes); components.Add(treeComponent); blacklist.AddRange(treeComponent.Nodes); } else { foreach (var startingNode in treeStartingNodes) { var treeComponent = GetTreeComponent(decomposition, startingNode); components.Add(treeComponent); blacklist.AddRange(treeComponent.Nodes); } } } } logger.WriteLine(); logger.WriteLine("Extending decomposition"); logger.WriteLine("Candidates:"); foreach (var component in components) { logger.WriteLine(component); } logger.WriteLine(); var cycleComponents = components.Where(x => x.IsFromFace).ToList(); if (cycleComponents.Count != 0) { var nextCycleIndex = preferSmallCycles ? cycleComponents.MinBy(x => x.Nodes.Count) : cycleComponents.MaxBy(x => x.Nodes.Count); var nextCycle = cycleComponents[nextCycleIndex]; logger.WriteLine("Adding smallest cycle component"); logger.WriteLine(nextCycle); return(decomposition.AddChain(nextCycle.Nodes, true)); } var treeComponents = components .Where(x => !x.IsFromFace) .OrderBy(x => x.MinimumNeighborChainNumber) .ThenByDescending(x => x.Nodes.Count) .ToList(); var biggestTree = treeComponents[0]; if (mergeSmallChains) { if (biggestTree.Nodes.Count < maxTreeSize) { for (var i = 1; i < treeComponents.Count; i++) { var component = treeComponents[i]; if (component.Nodes.Count + biggestTree.Nodes.Count <= maxTreeSize) { biggestTree.Nodes.AddRange(component.Nodes); } } } } logger.WriteLine("Adding biggest oldest tree component"); logger.WriteLine(biggestTree); return(decomposition.AddChain(biggestTree.Nodes, false)); }