private static void CostDecreaseForLeavingInlinedIndependent(SearchPlanEdge planEdge) { // considerably lower the costs for operations leaving the inlined independent part, so this is done early if (planEdge.Target is SearchPlanEdgeNode) // we may leave the independent part only with an edge { if (planEdge.Source.PatternElement.OriginalIndependentElement != null) // when the start is a node from an inlined independent { SearchPlanEdgeNode edge = (SearchPlanEdgeNode)planEdge.Target; if (edge.PatternEdgeSource.PatternElement.OriginalIndependentElement != null && edge.PatternEdgeTarget.PatternElement.OriginalIndependentElement == null || edge.PatternEdgeSource.PatternElement.OriginalIndependentElement == null && edge.PatternEdgeTarget.PatternElement.OriginalIndependentElement != null) { // and the edge is incident to elements inside and outside of the inlined independent planEdge.Cost = (float)Math.Sqrt(Math.Sqrt(planEdge.Cost)); } } } }
/// <summary> /// Generates a scheduled search plan for a given search plan graph /// </summary> public static ScheduledSearchPlan ScheduleSearchPlan(SearchPlanGraph spGraph, PatternGraph patternGraph, bool isNegativeOrIndependent, bool lazyNegativeIndependentConditionEvaluation) { // the schedule List <SearchOperation> operations = new List <SearchOperation>(); // a set of search plan edges representing the currently reachable not yet visited elements PriorityQueue <SearchPlanEdge> activeEdges = new PriorityQueue <SearchPlanEdge>(); // first schedule all preset elements foreach (SearchPlanEdge edge in spGraph.Root.OutgoingEdges) { if (edge.Target.IsPreset && edge.Type != SearchOperationType.DefToBeYieldedTo) { foreach (SearchPlanEdge edgeOutgoingFromPresetElement in edge.Target.OutgoingEdges) { activeEdges.Add(edgeOutgoingFromPresetElement); } // note: here a normal preset is converted into a neg/idpt preset operation if in negative/independent pattern SearchOperation newOp = new SearchOperation( isNegativeOrIndependent ? SearchOperationType.NegIdptPreset : edge.Type, edge.Target, spGraph.Root, 0); operations.Add(newOp); } } // then schedule all map with storage / pick from index / pick from storage / pick from name index elements not depending on other elements foreach (SearchPlanEdge edge in spGraph.Root.OutgoingEdges) { if (edge.Type == SearchOperationType.MapWithStorage) { foreach (SearchPlanEdge edgeOutgoingFromPickedElement in edge.Target.OutgoingEdges) { activeEdges.Add(edgeOutgoingFromPickedElement); } SearchOperation newOp = new SearchOperation(edge.Type, edge.Target, spGraph.Root, 0); newOp.Storage = edge.Target.PatternElement.Storage; newOp.StorageIndex = edge.Target.PatternElement.StorageIndex; operations.Add(newOp); } } foreach (SearchPlanEdge edge in spGraph.Root.OutgoingEdges) { if (edge.Type == SearchOperationType.PickFromStorage) { foreach (SearchPlanEdge edgeOutgoingFromPickedElement in edge.Target.OutgoingEdges) { activeEdges.Add(edgeOutgoingFromPickedElement); } SearchOperation newOp = new SearchOperation(edge.Type, edge.Target, spGraph.Root, 0); newOp.Storage = edge.Target.PatternElement.Storage; operations.Add(newOp); } } foreach (SearchPlanEdge edge in spGraph.Root.OutgoingEdges) { if (edge.Type == SearchOperationType.PickFromIndex) { foreach (SearchPlanEdge edgeOutgoingFromPickedElement in edge.Target.OutgoingEdges) { activeEdges.Add(edgeOutgoingFromPickedElement); } SearchOperation newOp = new SearchOperation(edge.Type, edge.Target, spGraph.Root, 0); newOp.IndexAccess = edge.Target.PatternElement.IndexAccess; operations.Add(newOp); } } foreach (SearchPlanEdge edge in spGraph.Root.OutgoingEdges) { if (edge.Type == SearchOperationType.PickByName) { foreach (SearchPlanEdge edgeOutgoingFromPickedElement in edge.Target.OutgoingEdges) { activeEdges.Add(edgeOutgoingFromPickedElement); } SearchOperation newOp = new SearchOperation(edge.Type, edge.Target, spGraph.Root, 0); newOp.NameLookup = edge.Target.PatternElement.NameLookup; operations.Add(newOp); } } foreach (SearchPlanEdge edge in spGraph.Root.OutgoingEdges) { if (edge.Type == SearchOperationType.PickByUnique) { foreach (SearchPlanEdge edgeOutgoingFromPickedElement in edge.Target.OutgoingEdges) { activeEdges.Add(edgeOutgoingFromPickedElement); } SearchOperation newOp = new SearchOperation(edge.Type, edge.Target, spGraph.Root, 0); newOp.UniqueLookup = edge.Target.PatternElement.UniqueLookup; operations.Add(newOp); } } // iterate over all reachable elements until the whole graph has been scheduled(/visited), // choose next cheapest operation, update the reachable elements and the search plan costs SearchPlanNode lastNode = spGraph.Root; for (int i = 0; i < spGraph.Nodes.Length - spGraph.NumPresetElements - spGraph.NumIndependentStorageIndexElements; ++i) { foreach (SearchPlanEdge edge in lastNode.OutgoingEdges) { if (edge.Target.IsPreset) { continue; } if (edge.Target.PatternElement.Storage != null && edge.Target.PatternElement.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() == null) { continue; } if (edge.Target.PatternElement.IndexAccess != null && edge.Target.PatternElement.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() == null) { continue; } if (edge.Target.PatternElement.NameLookup != null && edge.Target.PatternElement.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() == null) { continue; } if (edge.Target.PatternElement.UniqueLookup != null && edge.Target.PatternElement.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() == null) { continue; } CostDecreaseForLeavingInlinedIndependent(edge); activeEdges.Add(edge); } SearchPlanEdge minEdge = activeEdges.DequeueFirst(); lastNode = minEdge.Target; SearchOperation newOp = new SearchOperation(minEdge.Type, lastNode, minEdge.Source, minEdge.Cost); newOp.Storage = minEdge.Target.PatternElement.Storage; newOp.StorageIndex = minEdge.Target.PatternElement.StorageIndex; newOp.IndexAccess = minEdge.Target.PatternElement.IndexAccess; newOp.NameLookup = minEdge.Target.PatternElement.NameLookup; newOp.UniqueLookup = minEdge.Target.PatternElement.UniqueLookup; foreach (SearchOperation op in operations) { op.CostToEnd += minEdge.Cost; } operations.Add(newOp); } // remove the elements stemming from inlined independents // they were added in the hope that they might help in matching this pattern, // they don't if they are matched after the elements of this pattern (in fact they only increase the costs then) RemoveInlinedIndependentElementsAtEnd(operations); // insert inlined element identity check into the schedule in case neither of the possible assignments was scheduled InsertInlinedElementIdentityCheckIntoSchedule(patternGraph, operations); // insert inlined variable assignments into the schedule InsertInlinedVariableAssignmentsIntoSchedule(patternGraph, operations); // insert conditions into the schedule InsertConditionsIntoSchedule(patternGraph.ConditionsPlusInlined, operations, lazyNegativeIndependentConditionEvaluation); // schedule the initialization of all def to be yielded to elements and variables at the end, // must come after the pattern elements (and preset elements), as they may be used in the def initialization foreach (SearchPlanEdge edge in spGraph.Root.OutgoingEdges) { if (edge.Type == SearchOperationType.DefToBeYieldedTo && (!isNegativeOrIndependent || (edge.Target.PatternElement.pointOfDefinition == patternGraph && edge.Target.PatternElement.originalElement == null))) { SearchOperation newOp = new SearchOperation( SearchOperationType.DefToBeYieldedTo, edge.Target, spGraph.Root, 0); newOp.Expression = edge.Target.PatternElement.Initialization; operations.Add(newOp); } } foreach (PatternVariable var in patternGraph.variablesPlusInlined) { if (var.defToBeYieldedTo && (!isNegativeOrIndependent || var.pointOfDefinition == patternGraph && var.originalVariable == null)) { SearchOperation newOp = new SearchOperation( SearchOperationType.DefToBeYieldedTo, var, spGraph.Root, 0); newOp.Expression = var.initialization; operations.Add(newOp); } } float cost = operations.Count > 0 ? operations[0].CostToEnd : 0; return(new ScheduledSearchPlan(patternGraph, operations.ToArray(), cost)); }
/// <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)); }