/// <summary> /// Generates a scheduled search plan for a given search plan graph /// </summary> public ScheduledSearchPlan ScheduleSearchPlan(SearchPlanGraph spGraph, PatternGraph patternGraph, bool isNegativeOrIndependent) { // 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 the initialization of all def to be yielded to elements and variables, // must come after the 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); } } // 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); float cost = operations.Count > 0 ? operations[0].CostToEnd : 0; return new ScheduledSearchPlan(patternGraph, operations.ToArray(), cost); }
/// <summary> /// Creates an interpretation plan builder for the given scheduled search plan. /// Only a limited amount of search operations is supported, the ones needed for isomorphy checking. /// </summary> /// <param name="ssp">the scheduled search plan to build an interpretation plan for</param> /// <param name="spg">the search plan graph for determining the pattern element needed for attribute checking</param> /// <param name="model">the model over which the patterns are to be searched</param> public InterpretationPlanBuilder(ScheduledSearchPlan ssp, SearchPlanGraph spg, IGraphModel model) { this.ssp = ssp; this.spg = spg; this.model = model; }