private static void BuildInterpretationPlan(LGSPGraph graph) { graph.matchingState.patternGraph = BuildPatternGraph(graph); PlanGraph planGraph = PlanGraphGenerator.GeneratePlanGraph(graph.Model, graph.statistics, graph.matchingState.patternGraph, false, false, false, new Dictionary <PatternElement, SetValueType>()); PlanGraphGenerator.MarkMinimumSpanningArborescence(planGraph, graph.matchingState.patternGraph.name, false); SearchPlanGraph searchPlanGraph = SearchPlanGraphGeneratorAndScheduler.GenerateSearchPlanGraph(planGraph); ScheduledSearchPlan scheduledSearchPlan = SearchPlanGraphGeneratorAndScheduler.ScheduleSearchPlan( searchPlanGraph, graph.matchingState.patternGraph, false, false); InterpretationPlanBuilder builder = new InterpretationPlanBuilder(scheduledSearchPlan, searchPlanGraph, graph.Model); graph.matchingState.interpretationPlan = builder.BuildInterpretationPlan("ComparisonMatcher_" + graph.GraphId); ++GraphMatchingState.numInterpretationPlans; graph.matchingState.changesCounterAtInterpretationPlanBuilding = graph.changesCounterAtLastAnalyze; Debug.Assert(graph.changesCounterAtLastAnalyze == graph.ChangesCounter); #if LOG_ISOMORPHY_CHECKING SourceBuilder sb = new SourceBuilder(); graph.matchingState.interpretationPlan.Dump(sb); writer.WriteLine(); writer.WriteLine(sb.ToString()); writer.WriteLine(); writer.Flush(); #endif }
/// <summary> /// Marks the minimum spanning arborescence of a plan graph by setting the IncomingMSAEdge /// fields for all nodes /// </summary> /// <param name="planGraph">The plan graph to be marked</param> /// <param name="dumpName">Names the dump targets if dump compiler flags are set</param> public void MarkMinimumSpanningArborescence(PlanGraph planGraph, String dumpName) { if(DumpSearchPlan) DumpPlanGraph(planGraph, dumpName, "initial"); // nodes not already looked at Dictionary<PlanNode, bool> leftNodes = new Dictionary<PlanNode, bool>(planGraph.Nodes.Length); foreach(PlanNode node in planGraph.Nodes) leftNodes.Add(node, true); // epoch = search run Dictionary<PlanPseudoNode, bool> epoch = new Dictionary<PlanPseudoNode, bool>(); LinkedList<PlanSuperNode> superNodeStack = new LinkedList<PlanSuperNode>(); // work left ? while(leftNodes.Count > 0) { // get first remaining node Dictionary<PlanNode, bool>.Enumerator enumerator = leftNodes.GetEnumerator(); enumerator.MoveNext(); PlanPseudoNode curNode = enumerator.Current.Key; // start a new search run epoch.Clear(); do { // next node in search run epoch.Add(curNode, true); if(curNode is PlanNode) leftNodes.Remove((PlanNode) curNode); // cheapest incoming edge of current node float cost; PlanEdge cheapestEdge = curNode.GetCheapestIncoming(curNode, out cost); if(cheapestEdge == null) break; curNode.IncomingMSAEdge = cheapestEdge; // cycle found ? while(epoch.ContainsKey(cheapestEdge.Source.TopNode)) { // contract the cycle to a super node PlanSuperNode superNode = new PlanSuperNode(cheapestEdge.Source.TopNode); superNodeStack.AddFirst(superNode); epoch.Add(superNode, true); if(superNode.IncomingMSAEdge == null) goto exitSecondLoop; // continue with new super node as current node curNode = superNode; cheapestEdge = curNode.IncomingMSAEdge; } curNode = cheapestEdge.Source.TopNode; } while(true); exitSecondLoop: ; } if(DumpSearchPlan) { DumpPlanGraph(planGraph, dumpName, "contracted"); DumpContractedPlanGraph(planGraph, dumpName); } // breaks all cycles represented by setting the incoming msa edges of the // representative nodes to the incoming msa edges according to the supernode /*no, not equivalent: foreach(PlanSuperNode superNode in superNodeStack) superNode.Child.IncomingMSAEdge = superNode.IncomingMSAEdge;*/ foreach (PlanSuperNode superNode in superNodeStack) { PlanPseudoNode curNode = superNode.IncomingMSAEdge.Target; while (curNode.SuperNode != superNode) curNode = curNode.SuperNode; curNode.IncomingMSAEdge = superNode.IncomingMSAEdge; if(curNode.IncomingMSAEdge == null) throw new Exception(); } if(DumpSearchPlan) DumpFinalPlanGraph(planGraph, dumpName); }
/// <summary> /// Generate search plan graph out of the plan graph, /// search plan graph only contains edges chosen by the MSA algorithm. /// Edges in search plan graph are given in the nodes by outgoing list, as needed for scheduling, /// in contrast to incoming list in plan graph, as needed for MSA computation. /// </summary> /// <param name="planGraph">The source plan graph</param> /// <returns>A new search plan graph</returns> public SearchPlanGraph GenerateSearchPlanGraph(PlanGraph planGraph) { SearchPlanNode searchPlanRoot = new SearchPlanNode("search plan root"); SearchPlanNode[] searchPlanNodes = new SearchPlanNode[planGraph.Nodes.Length]; SearchPlanEdge[] searchPlanEdges = new SearchPlanEdge[planGraph.Nodes.Length - 1 + 1]; // +1 for root Dictionary<PlanNode, SearchPlanNode> planToSearchPlanNode = // for generating edges new Dictionary<PlanNode, SearchPlanNode>(planGraph.Nodes.Length); planToSearchPlanNode.Add(planGraph.Root, searchPlanRoot); // generate the search plan graph nodes, same as plan graph nodes, // representing pattern graph nodes and edges int i = 0; foreach(PlanNode planNode in planGraph.Nodes) { if(planNode.NodeType == PlanNodeType.Edge) searchPlanNodes[i] = new SearchPlanEdgeNode(planNode, null, null); else searchPlanNodes[i] = new SearchPlanNodeNode(planNode); planToSearchPlanNode.Add(planNode, searchPlanNodes[i]); ++i; } // generate the search plan graph edges, // that are the plan graph edges chosen by the MSA algorithm, in reversed direction // and add references to originating pattern elements i = 0; foreach(PlanNode planNode in planGraph.Nodes) { PlanEdge planEdge = planNode.IncomingMSAEdge; searchPlanEdges[i] = new SearchPlanEdge(planEdge.Type, planToSearchPlanNode[planEdge.Source], planToSearchPlanNode[planEdge.Target], planEdge.Cost); planToSearchPlanNode[planEdge.Source].OutgoingEdges.Add(searchPlanEdges[i]); if(planNode.NodeType == PlanNodeType.Edge) { SearchPlanEdgeNode searchPlanEdgeNode = (SearchPlanEdgeNode) planToSearchPlanNode[planNode]; SearchPlanNode patElem; if(planEdge.Target.PatternEdgeSource != null && planToSearchPlanNode.TryGetValue(planEdge.Target.PatternEdgeSource, out patElem)) { searchPlanEdgeNode.PatternEdgeSource = (SearchPlanNodeNode) patElem; searchPlanEdgeNode.PatternEdgeSource.OutgoingPatternEdges.Add(searchPlanEdgeNode); } if(planEdge.Target.PatternEdgeTarget != null && planToSearchPlanNode.TryGetValue(planEdge.Target.PatternEdgeTarget, out patElem)) { searchPlanEdgeNode.PatternEdgeTarget = (SearchPlanNodeNode) patElem; searchPlanEdgeNode.PatternEdgeTarget.IncomingPatternEdges.Add(searchPlanEdgeNode); } } ++i; } return new SearchPlanGraph(searchPlanRoot, searchPlanNodes, searchPlanEdges); }
private void DumpFinalPlanGraph(PlanGraph planGraph, String dumpname) { StreamWriter sw = new StreamWriter(dumpname + "-finalplangraph.vcg", false); sw.WriteLine("graph:{\ninfoname 1: \"Attributes\"\ndisplay_edge_labels: no\nport_sharing: no\nsplines: no\n" + "\nmanhattan_edges: no\nsmanhattan_edges: no\norientation: bottom_to_top\nedges: yes\nnodes:yes\nclassname 1: \"normal\""); sw.WriteLine("node:{title:\"root\" label:\"ROOT\"}\n"); sw.WriteLine("graph:{{title:\"pattern\" label:\"{0}\" status:clustered color:lightgrey", dumpname); foreach(PlanNode node in planGraph.Nodes) { DumpNode(sw, node); DumpEdge(sw, node.IncomingMSAEdge, false); } sw.WriteLine("}\n}"); sw.Close(); }
private void DumpContractedPlanGraph(PlanGraph planGraph, String dumpname) { StreamWriter sw = new StreamWriter(dumpname + "-contractedplangraph.vcg", false); sw.WriteLine("graph:{\ninfoname 1: \"Attributes\"\ndisplay_edge_labels: no\nport_sharing: no\nsplines: no\n" + "\nmanhattan_edges: no\nsmanhattan_edges: no\norientation: bottom_to_top\nedges: yes\nnodes:yes\nclassname 1: \"normal\""); sw.WriteLine("node:{title:\"root\" label:\"ROOT\"}\n"); sw.WriteLine("graph:{{title:\"pattern\" label:\"{0}\" status:clustered color:lightgrey", dumpname); Dictionary<PlanSuperNode, bool> dumpedSuperNodes = new Dictionary<PlanSuperNode, bool>(); foreach(PlanNode node in planGraph.Nodes) { PlanSuperNode superNode = node.TopSuperNode; if(superNode != null) { if(dumpedSuperNodes.ContainsKey(superNode)) continue; DumpSuperNode(sw, superNode, dumpedSuperNodes); DumpEdge(sw, superNode.IncomingMSAEdge, true); } else { DumpNode(sw, node); DumpEdge(sw, node.IncomingMSAEdge, false); } } sw.WriteLine("}\n}"); sw.Close(); }
/// <summary> /// Generate search plan graph out of the plan graph, /// search plan graph only contains edges chosen by the MSA algorithm. /// Edges in search plan graph are given in the nodes by outgoing list, as needed for scheduling, /// in contrast to incoming list in plan graph, as needed for MSA computation. /// </summary> /// <param name="planGraph">The source plan graph</param> /// <returns>A new search plan graph</returns> public static SearchPlanGraph GenerateSearchPlanGraph(PlanGraph planGraph) { SearchPlanNode searchPlanRoot = new SearchPlanNode("search plan root"); SearchPlanNode[] searchPlanNodes = new SearchPlanNode[planGraph.Nodes.Length]; SearchPlanEdge[] searchPlanEdges = new SearchPlanEdge[planGraph.Nodes.Length - 1 + 1]; // +1 for root Dictionary <PlanNode, SearchPlanNode> planToSearchPlanNode = // for generating edges new Dictionary <PlanNode, SearchPlanNode>(planGraph.Nodes.Length); planToSearchPlanNode.Add(planGraph.Root, searchPlanRoot); // generate the search plan graph nodes, same as plan graph nodes, // representing pattern graph nodes and edges int i = 0; foreach (PlanNode planNode in planGraph.Nodes) { if (planNode.NodeType == PlanNodeType.Edge) { searchPlanNodes[i] = new SearchPlanEdgeNode(planNode, null, null); } else { searchPlanNodes[i] = new SearchPlanNodeNode(planNode); } planToSearchPlanNode.Add(planNode, searchPlanNodes[i]); ++i; } // generate the search plan graph edges, // that are the plan graph edges chosen by the MSA algorithm, in reversed direction // and add references to originating pattern elements i = 0; foreach (PlanNode planNode in planGraph.Nodes) { PlanEdge planEdge = planNode.IncomingMSAEdge; searchPlanEdges[i] = new SearchPlanEdge(planEdge.Type, planToSearchPlanNode[planEdge.Source], planToSearchPlanNode[planEdge.Target], planEdge.Cost); planToSearchPlanNode[planEdge.Source].OutgoingEdges.Add(searchPlanEdges[i]); if (planNode.NodeType == PlanNodeType.Edge) { SearchPlanEdgeNode searchPlanEdgeNode = (SearchPlanEdgeNode)planToSearchPlanNode[planNode]; SearchPlanNode patElem; if (planEdge.Target.PatternEdgeSource != null && planToSearchPlanNode.TryGetValue(planEdge.Target.PatternEdgeSource, out patElem)) { searchPlanEdgeNode.PatternEdgeSource = (SearchPlanNodeNode)patElem; searchPlanEdgeNode.PatternEdgeSource.OutgoingPatternEdges.Add(searchPlanEdgeNode); } if (planEdge.Target.PatternEdgeTarget != null && planToSearchPlanNode.TryGetValue(planEdge.Target.PatternEdgeTarget, out patElem)) { searchPlanEdgeNode.PatternEdgeTarget = (SearchPlanNodeNode)patElem; searchPlanEdgeNode.PatternEdgeTarget.IncomingPatternEdges.Add(searchPlanEdgeNode); } } ++i; } return(new SearchPlanGraph(searchPlanRoot, searchPlanNodes, searchPlanEdges)); }