protected SearchPlanNode(PlanNode planNode) { NodeType = planNode.NodeType; ElementID = planNode.ElementID; IsPreset = planNode.IsPreset; PatternElement = planNode.PatternElement; }
public PlanEdge(SearchOperationType type, PlanNode source, PlanNode target, float cost) { Source = source; Target = target; Cost = cost; mstCost = (float)Math.Max(Math.Log(cost), 1); // mstCost = (float) Math.Max(Math.Log(cost), 0.0001); // mstCost = cost; Type = type; }
/// <summary> /// Instantiates an edge plan node. /// </summary> /// <param name="patEdge">The pattern edge for this plan node.</param> /// <param name="elemID">The element ID for this plan node.</param> /// <param name="isPreset">True, if this element is a known element.</param> /// <param name="patternEdgeSource">The plan node corresponding to the source of the pattern edge.</param> /// <param name="patternEdgeTarget">The plan node corresponding to the target of the pattern edge.</param> public PlanNode(PatternEdge patEdge, int elemID, bool isPreset, PlanNode patternEdgeSource, PlanNode patternEdgeTarget) { NodeType = PlanNodeType.Edge; ElementID = elemID; IsPreset = isPreset; PatternElement = patEdge; PatternEdgeSource = patternEdgeSource; PatternEdgeTarget = patternEdgeTarget; }
public readonly PlanEdge[] Edges; // edges of the plan graph, representing search operations public PlanGraph(PlanNode root, PlanNode[] nodes, PlanEdge[] edges) { Root = root; Nodes = nodes; Edges = edges; }
private void CreateSourceTargetIncomingOutgoingPlanEdges(PatternEdge edge, PlanNode planNode, List<PlanEdge> planEdges, IDictionary<PatternNode, PatternNode> originalToInlinedIndependent, LGSPGraphStatistics graphStatistics, PatternGraph patternGraph, bool isPreset, float zeroCost) { // only add implicit source operation if edge source is needed and the edge source is // not a preset node and not a storage node and not an index node and not a cast node PatternNode source = GetSourcePlusInlined(edge, patternGraph, originalToInlinedIndependent); if(source != null && !source.TempPlanMapping.IsPreset && source.Storage == null && source.IndexAccess == null && source.NameLookup == null && source.UniqueLookup == null && source.ElementBeforeCasting == null) { SearchOperationType operation = edge.fixedDirection ? SearchOperationType.ImplicitSource : SearchOperationType.Implicit; PlanEdge implSrcPlanEdge = new PlanEdge(operation, planNode, source.TempPlanMapping, zeroCost); planEdges.Add(implSrcPlanEdge); source.TempPlanMapping.IncomingEdges.Add(implSrcPlanEdge); } // only add implicit target operation if edge target is needed and the edge target is // not a preset node and not a storage node and not an index node and not a cast node PatternNode target = GetTargetPlusInlined(edge, patternGraph, originalToInlinedIndependent); if(target != null && !target.TempPlanMapping.IsPreset && target.Storage == null && target.IndexAccess == null && target.NameLookup == null && target.UniqueLookup == null && target.ElementBeforeCasting == null) { SearchOperationType operation = edge.fixedDirection ? SearchOperationType.ImplicitTarget : SearchOperationType.Implicit; PlanEdge implTgtPlanEdge = new PlanEdge(operation, planNode, target.TempPlanMapping, zeroCost); planEdges.Add(implTgtPlanEdge); target.TempPlanMapping.IncomingEdges.Add(implTgtPlanEdge); } // edge must only be reachable from other nodes if it's not a preset and not storage determined and not index determined and not a cast if(!isPreset && edge.Storage == null && edge.IndexAccess == null && edge.NameLookup == null && edge.UniqueLookup == null && edge.ElementBeforeCasting == null) { // no outgoing on source node if no source if(source != null) { int targetTypeID; if(target != null) targetTypeID = target.TypeID; else targetTypeID = model.NodeModel.RootType.TypeID; // cost of walking along edge #if MONO_MULTIDIMARRAY_WORKAROUND float normCost = graphStatistics.vstructs[((source.TypeID * graphStatistics.dim1size + edge.TypeID) * graphStatistics.dim2size + targetTypeID) * 2 + (int)LGSPDirection.Out]; if(!edge.fixedDirection) { normCost += graphStatistics.vstructs[((source.TypeID * graphStatistics.dim1size + edge.TypeID) * graphStatistics.dim2size + targetTypeID) * 2 + (int)LGSPDirection.In]; } #else float normCost = graph.statistics.vstructs[source.TypeID, edge.TypeID, targetTypeID, (int) LGSPDirection.Out]; if (!edge.fixedDirection) { normCost += graph.statistics.vstructs[source.TypeID, edge.TypeID, targetTypeID, (int) LGSPDirection.In]; } #endif if(graphStatistics.nodeCounts[source.TypeID] != 0) normCost /= graphStatistics.nodeCounts[source.TypeID]; normCost = CostIncreaseForInlinedIndependent(edge, normCost); SearchOperationType operation = edge.fixedDirection ? SearchOperationType.Outgoing : SearchOperationType.Incident; PlanEdge outPlanEdge = new PlanEdge(operation, source.TempPlanMapping, planNode, normCost); planEdges.Add(outPlanEdge); planNode.IncomingEdges.Add(outPlanEdge); } // no incoming on target node if no target if(target != null) { int sourceTypeID; if(source != null) sourceTypeID = source.TypeID; else sourceTypeID = model.NodeModel.RootType.TypeID; // cost of walking in opposite direction of edge #if MONO_MULTIDIMARRAY_WORKAROUND float revCost = graphStatistics.vstructs[((target.TypeID * graphStatistics.dim1size + edge.TypeID) * graphStatistics.dim2size + sourceTypeID) * 2 + (int)LGSPDirection.In]; if(!edge.fixedDirection) { revCost += graphStatistics.vstructs[((target.TypeID * graphStatistics.dim1size + edge.TypeID) * graphStatistics.dim2size + sourceTypeID) * 2 + (int)LGSPDirection.Out]; } #else float revCost = graph.statistics.vstructs[target.TypeID, edge.TypeID, sourceTypeID, (int) LGSPDirection.In]; if (!edge.fixedDirection) { revCost += graph.statistics.vstructs[target.TypeID, edge.TypeID, sourceTypeID, (int) LGSPDirection.Out]; } #endif if(graphStatistics.nodeCounts[target.TypeID] != 0) revCost /= graphStatistics.nodeCounts[target.TypeID]; revCost = CostIncreaseForInlinedIndependent(edge, revCost); SearchOperationType operation = edge.fixedDirection ? SearchOperationType.Incoming : SearchOperationType.Incident; PlanEdge inPlanEdge = new PlanEdge(operation, target.TempPlanMapping, planNode, revCost); planEdges.Add(inPlanEdge); planNode.IncomingEdges.Add(inPlanEdge); } } }
private static void CreatePlanNodeAndLookupPlanEdge(PatternEdge edge, int elemId, LGSPGraphStatistics graphStatistics, PatternGraph patternGraph, bool isNegativeOrIndependent, bool isSubpatternLike, PlanNode planRoot, float zeroCost, IDictionary<PatternNode, PatternNode> originalToInlinedIndependent, IDictionary<PatternElement, SetValueType> presetsFromIndependentInlining, out bool isPreset, out PlanNode planNode, out PlanEdge rootToNodePlanEdge) { float cost; SearchOperationType searchOperationType; if(edge.DefToBeYieldedTo) { cost = zeroCost; isPreset = true; searchOperationType = SearchOperationType.DefToBeYieldedTo; } else if(edge.PointOfDefinition == null) { cost = zeroCost; isPreset = true; searchOperationType = isSubpatternLike ? SearchOperationType.SubPreset : SearchOperationType.ActionPreset; } else if(edge.PointOfDefinition != patternGraph && edge.OriginalIndependentElement == null) { cost = zeroCost; isPreset = true; searchOperationType = isNegativeOrIndependent ? SearchOperationType.NegIdptPreset : SearchOperationType.SubPreset; } else if(presetsFromIndependentInlining.ContainsKey(edge)) { cost = zeroCost; isPreset = true; searchOperationType = SearchOperationType.NegIdptPreset; edge.PresetBecauseOfIndependentInlining = true; } else if(edge.Storage != null) { if(edge.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation } else { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.PickFromStorage; // pick from storage instead of lookup from graph } } else if(edge.IndexAccess != null) { if(edge.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation } else { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.PickFromIndex; // pick from index instead of lookup from graph } } else if(edge.NameLookup != null) { if(edge.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation } else { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.PickByName; // pick by name instead of lookup from graph } } else if(edge.UniqueLookup != null) { if(edge.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation } else { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.PickByUnique; // pick by unique instead of lookup from graph } } else if(edge.ElementBeforeCasting != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element before casting is needed, so there is no lookup like operation } else { cost = graphStatistics.edgeCounts[edge.TypeID]; cost = CostIncreaseForInlinedIndependent(edge, cost); isPreset = false; searchOperationType = SearchOperationType.Lookup; } PatternNode source = GetSourcePlusInlined(edge, patternGraph, originalToInlinedIndependent); PatternNode target = GetTargetPlusInlined(edge, patternGraph, originalToInlinedIndependent); planNode = new PlanNode(edge, elemId, isPreset, source != null ? source.TempPlanMapping : null, target != null ? target.TempPlanMapping : null); rootToNodePlanEdge = null; if(searchOperationType != SearchOperationType.Void) rootToNodePlanEdge = new PlanEdge(searchOperationType, planRoot, planNode, cost); }
/// <summary> /// Generate plan graph for given pattern graph with costs from the analyzed host graph. /// Plan graph contains nodes representing the pattern elements (nodes and edges) /// and edges representing the matching operations to get the elements by. /// Edges in plan graph are given in the nodes by incoming list, as needed for MSA computation. /// </summary> public PlanGraph GeneratePlanGraph(LGSPGraphStatistics graphStatistics, PatternGraph patternGraph, bool isNegativeOrIndependent, bool isSubpatternLike, IDictionary<PatternElement, SetValueType> presetsFromIndependentInlining) { // // If you change this method, chances are high you also want to change GenerateStaticPlanGraph in LGSPGrGen // look there for version without ifdef junk // todo: unify it with GenerateStaticPlanGraph in LGSPGrGen // // Create root node // Create plan graph nodes for all pattern graph nodes and all pattern graph edges // Create "lookup" plan graph edge from root node to each plan graph node // Create "implicit source" plan graph edge from each plan graph node originating with a pattern edge // to the plan graph node created by the source node of the pattern graph edge // Create "implicit target" plan graph edge from each plan graph node originating with a pattern edge // to the plan graph node created by the target node of the pattern graph edge // Create "incoming" plan graph edge from each plan graph node originating with a pattern node // to a plan graph node created by one of the incoming edges of the pattern node // Create "outgoing" plan graph edge from each plan graph node originating with a pattern node // to a plan graph node created by one of the outgoing edges of the pattern node // Ensured: there's no plan graph edge with a preset element as target besides the lookup, // so presets are only search operation sources // Create "pick from storage" plan graph edge for plan graph nodes which are to be picked from a storage, // from root node on, instead of lookup, no other plan graph edge having this node as target // Create "pick from storage attribute" plan graph edge from storage attribute owner to storage picking result, // no lookup, no other plan graph edge having this node as target // Create "map" by storage plan graph edge from accessor to storage mapping result // no lookup, no other plan graph edge having this node as target // Create "pick from index" plan graph edge for plan graph nodes which are to be picked from an index, // from root node on, instead of lookup, no other plan graph edge having this node as target // Create "pick from index depending" plan graph edge from node the index expressions depend on, // no lookup, no other plan graph edge having this node as target // Create "cast" plan graph edge from element before casting to cast result, // no lookup, no other plan graph edge having this node as target int numNodes = patternGraph.nodesPlusInlined.Length; if(InlineIndependents && !isNegativeOrIndependent) numNodes += LGSPMatcherGenerator.NumNodesInIndependentsMatchedThere(patternGraph); int numEdges = patternGraph.edgesPlusInlined.Length; if(InlineIndependents && !isNegativeOrIndependent) numEdges += LGSPMatcherGenerator.NumEdgesInIndependentsMatchedThere(patternGraph); PlanNode[] planNodes = new PlanNode[numNodes + numEdges]; List<PlanEdge> planEdges = new List<PlanEdge>(numNodes + 5 * numEdges); // upper bound for num of edges (lookup nodes + lookup edges + impl. tgt + impl. src + incoming + outgoing) Dictionary<PatternNode, PatternNode> originalToInlinedIndependent = new Dictionary<PatternNode, PatternNode>(); int nodesIndex = 0; float zeroCost = 1; PlanNode planRoot = new PlanNode("root"); // create plan nodes and lookup plan edges for all pattern graph nodes for(int i = 0; i < patternGraph.nodesPlusInlined.Length; i++) { PatternNode node = patternGraph.nodesPlusInlined[i]; PlanNode planNode; PlanEdge rootToNodePlanEdge; CreatePlanNodeAndLookupPlanEdge(node, i + 1, graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, planRoot, zeroCost, originalToInlinedIndependent, presetsFromIndependentInlining, out planNode, out rootToNodePlanEdge); planNodes[nodesIndex] = planNode; if(rootToNodePlanEdge != null) { planEdges.Add(rootToNodePlanEdge); planNode.IncomingEdges.Add(rootToNodePlanEdge); } node.TempPlanMapping = planNode; ++nodesIndex; } if(InlineIndependents && !isNegativeOrIndependent) // independent inlining only if not in negative/independent { foreach(PatternGraph independent in patternGraph.independentPatternGraphsPlusInlined) { foreach(PatternNode nodeOriginal in LGSPMatcherGenerator.NodesInIndependentMatchedThere(independent)) { PatternNode node = new PatternNode(nodeOriginal, "_inlined_" + independent.name); originalToInlinedIndependent.Add(nodeOriginal, node); PlanNode planNode; PlanEdge rootToNodePlanEdge; CreatePlanNodeAndLookupPlanEdge(node, -1, graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, planRoot, zeroCost, originalToInlinedIndependent, presetsFromIndependentInlining, out planNode, out rootToNodePlanEdge); planNodes[nodesIndex] = planNode; if(rootToNodePlanEdge != null) { planEdges.Add(rootToNodePlanEdge); planNode.IncomingEdges.Add(rootToNodePlanEdge); } node.TempPlanMapping = planNode; ++nodesIndex; } } } // create plan nodes and lookup plus incidence handling plan edges for all pattern graph edges for(int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { PatternEdge edge = patternGraph.edgesPlusInlined[i]; bool isPreset; PlanNode planNode; PlanEdge rootToNodePlanEdge; CreatePlanNodeAndLookupPlanEdge(edge, i + 1, graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, planRoot, zeroCost, originalToInlinedIndependent, presetsFromIndependentInlining, out isPreset, out planNode, out rootToNodePlanEdge); planNodes[nodesIndex] = planNode; if(rootToNodePlanEdge != null) { planEdges.Add(rootToNodePlanEdge); planNode.IncomingEdges.Add(rootToNodePlanEdge); } CreateSourceTargetIncomingOutgoingPlanEdges(edge, planNode, planEdges, originalToInlinedIndependent, graphStatistics, patternGraph, isPreset, zeroCost); edge.TempPlanMapping = planNode; ++nodesIndex; } if(InlineIndependents && !isNegativeOrIndependent) // independent inlining only if not in negative/independent { foreach(PatternGraph independent in patternGraph.independentPatternGraphsPlusInlined) { foreach(PatternEdge edgeOriginal in LGSPMatcherGenerator.EdgesInIndependentMatchedThere(independent)) { PatternEdge edge = new PatternEdge(edgeOriginal, "_inlined_" + independent.name); bool isPreset; PlanNode planNode; PlanEdge rootToNodePlanEdge; CreatePlanNodeAndLookupPlanEdge(edge, -1, graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, planRoot, zeroCost, originalToInlinedIndependent, presetsFromIndependentInlining, out isPreset, out planNode, out rootToNodePlanEdge); planNodes[nodesIndex] = planNode; if(rootToNodePlanEdge != null) { planEdges.Add(rootToNodePlanEdge); planNode.IncomingEdges.Add(rootToNodePlanEdge); } CreateSourceTargetIncomingOutgoingPlanEdges(edge, planNode, planEdges, originalToInlinedIndependent, graphStatistics, patternGraph, isPreset, zeroCost); edge.TempPlanMapping = planNode; ++nodesIndex; } } } //////////////////////////////////////////////////////////////////////////// // second run handling dependent storage and index picking (can't be done in first run due to dependencies between elements) // create map/pick/cast/assign plan edges for all pattern graph nodes for(int i = 0; i < patternGraph.nodesPlusInlined.Length; ++i) { PatternNode node = patternGraph.nodesPlusInlined[i]; if(node.PointOfDefinition == patternGraph && !presetsFromIndependentInlining.ContainsKey(node)) CreatePickMapCastAssignPlanEdges(node, planEdges, zeroCost); } // create map/pick/cast/assign plan edges for all pattern graph edges for(int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { PatternEdge edge = patternGraph.edgesPlusInlined[i]; if(edge.PointOfDefinition == patternGraph && !presetsFromIndependentInlining.ContainsKey(edge)) CreatePickMapCastAssignPlanEdges(edge, planEdges, zeroCost); } return new PlanGraph(planRoot, planNodes, planEdges.ToArray()); }
private void DumpNode(StreamWriter sw, PlanNode node) { if(node.NodeType == PlanNodeType.Edge) sw.WriteLine("node:{{title:\"{0}\" label:\"{1} : {2}\" shape:ellipse}}", GetDumpName(node), node.PatternElement.TypeID, node.PatternElement.Name); else sw.WriteLine("node:{{title:\"{0}\" label:\"{1} : {2}\"}}", GetDumpName(node), node.PatternElement.TypeID, node.PatternElement.Name); }
private String GetDumpName(PlanNode node) { if(node.NodeType == PlanNodeType.Root) return "root"; else if(node.NodeType == PlanNodeType.Node) return "node_" + node.PatternElement.Name; else return "edge_" + node.PatternElement.Name; }
public SearchPlanNodeNode(PlanNode planNode) : base(planNode) { }
public SearchPlanEdgeNode(PlanNode planNode, SearchPlanNodeNode patEdgeSrc, SearchPlanNodeNode patEdgeTgt) : base(planNode) { PatternEdgeSource = patEdgeSrc; PatternEdgeTarget = patEdgeTgt; }
private static void CreateSourceTargetIncomingOutgoingPlanEdges(PatternEdge edge, PlanNode planNode, List<PlanEdge> planEdges, IDictionary<PatternNode, PatternNode> originalToInlinedIndependent, PatternGraph patternGraph, bool isPreset, float zeroCost) { // only add implicit source operation if edge source is needed and the edge source is // not a preset node and not a storage node and not an index node and not a cast node PatternNode source = LGSPMatcherGenerator.GetSourcePlusInlined(edge, patternGraph, originalToInlinedIndependent); if(source != null && !source.TempPlanMapping.IsPreset && source.Storage == null && source.IndexAccess == null && source.NameLookup == null && source.UniqueLookup == null && source.ElementBeforeCasting == null) { SearchOperationType operation = edge.fixedDirection ? SearchOperationType.ImplicitSource : SearchOperationType.Implicit; PlanEdge implSrcPlanEdge = new PlanEdge(operation, planNode, source.TempPlanMapping, zeroCost); planEdges.Add(implSrcPlanEdge); source.TempPlanMapping.IncomingEdges.Add(implSrcPlanEdge); } // only add implicit target operation if edge target is needed and the edge target is // not a preset node and not a storage node and not an index node and not a cast node PatternNode target = LGSPMatcherGenerator.GetTargetPlusInlined(edge, patternGraph, originalToInlinedIndependent); if(target != null && !target.TempPlanMapping.IsPreset && target.Storage == null && target.IndexAccess == null && target.NameLookup == null && target.UniqueLookup == null && target.ElementBeforeCasting == null) { SearchOperationType operation = edge.fixedDirection ? SearchOperationType.ImplicitTarget : SearchOperationType.Implicit; PlanEdge implTgtPlanEdge = new PlanEdge(operation, planNode, target.TempPlanMapping, zeroCost); planEdges.Add(implTgtPlanEdge); target.TempPlanMapping.IncomingEdges.Add(implTgtPlanEdge); } // edge must only be reachable from other nodes if it's not a preset and not storage determined and not index determined and not a cast if(!isPreset && edge.Storage == null && edge.IndexAccess == null && edge.NameLookup == null && edge.UniqueLookup == null && edge.ElementBeforeCasting == null) { float cost = (edge.Cost + 5.5f) / 2; cost = LGSPMatcherGenerator.CostIncreaseForInlinedIndependent(edge, cost); // no outgoing on source node if no source if(source != null) { SearchOperationType operation = edge.fixedDirection ? SearchOperationType.Outgoing : SearchOperationType.Incident; PlanEdge outPlanEdge = new PlanEdge(operation, source.TempPlanMapping, planNode, cost); planEdges.Add(outPlanEdge); planNode.IncomingEdges.Add(outPlanEdge); } // no incoming on target node if no target if(target != null) { SearchOperationType operation = edge.fixedDirection ? SearchOperationType.Incoming : SearchOperationType.Incident; PlanEdge inPlanEdge = new PlanEdge(operation, target.TempPlanMapping, planNode, cost); planEdges.Add(inPlanEdge); planNode.IncomingEdges.Add(inPlanEdge); } } }
public PlanEdge[] Edges; // edges of the plan graph, representing search operations public PlanGraph(PlanNode root, PlanNode[] nodes, PlanEdge[] edges) { Root = root; Nodes = nodes; Edges = edges; }