예제 #1
0
        /// <summary>
        /// Parallelize the scheduled search plan for usage from a parallelized matcher
        /// (non- is-matched-flag-based isomorphy checking)
        /// </summary>
        public static void Parallelize(LGSPMatchingPattern matchingPattern)
        {
            Debug.Assert(matchingPattern.patternGraph.schedulesIncludingNegativesAndIndependents.Length == 1);
            ScheduledSearchPlan ssp = matchingPattern.patternGraph.schedulesIncludingNegativesAndIndependents[0];

            matchingPattern.patternGraph.parallelizedSchedule = new ScheduledSearchPlan[1];
            List <SearchOperation> operations = new List <SearchOperation>(ssp.Operations.Length);

            for (int i = 0; i < ssp.Operations.Length; ++i)
            {
                SearchOperation so    = ssp.Operations[i];
                SearchOperation clone = (SearchOperation)so.Clone();
                clone.Isomorphy.Parallel = true;
                operations.Add(clone);
                if (clone.Element is PatternCondition)
                {
                    SetNeedForParallelizedVersion((clone.Element as PatternCondition).ConditionExpression);
                }
            }
            ScheduledSearchPlan clonedSsp = new ScheduledSearchPlan(
                matchingPattern.patternGraph, operations.ToArray(), operations.Count > 0 ? operations[0].CostToEnd : 0);

            matchingPattern.patternGraph.parallelizedSchedule[0] = clonedSsp;
            ParallelizeNegativeIndependent(clonedSsp);
            ParallelizeAlternativeIterated(matchingPattern.patternGraph);
            ParallelizeYielding(matchingPattern.patternGraph);
        }
예제 #2
0
        private static void InsertInlinedIndependentCheckForDuplicateMatch(List <SearchOperation> operations)
        {
            bool isInlinedIndependentElementExisting = false;

            foreach (SearchOperation op in operations)
            {
                if (SearchPlanGraphGeneratorAndScheduler.IsOperationAnInlinedIndependentElement(op))
                {
                    isInlinedIndependentElementExisting = true;
                    break;
                }
            }

            if (isInlinedIndependentElementExisting)
            {
                // insert at end of schedule, just moved ahead over negatives and independents
                // TODO: if we can estimate condition overhead, it makes sense to move ahead over conditions, too
                int i = operations.Count - 1;
                while ((operations[i].Type == SearchOperationType.NegativePattern ||
                        operations[i].Type == SearchOperationType.IndependentPattern) && i > 0)
                {
                    --i;
                }

                SearchOperation so = new SearchOperation(SearchOperationType.InlinedIndependentCheckForDuplicateMatch,
                                                         null, null, operations[i].CostToEnd);
                operations.Insert(i + 1, so);
            }
        }
예제 #3
0
        /// <summary>
        /// Non- is-matched-flag-based isomorphy checking for nested alternative cases/iterateds
        /// </summary>
        private static void ParallelizeAlternativeIterated(PatternGraph patternGraph)
        {
            foreach (Alternative alt in patternGraph.alternativesPlusInlined)
            {
                foreach (PatternGraph altCase in alt.alternativeCases)
                {
                    ScheduledSearchPlan ssp = altCase.schedulesIncludingNegativesAndIndependents[0];
                    altCase.parallelizedSchedule = new ScheduledSearchPlan[1];
                    List <SearchOperation> operations = new List <SearchOperation>(ssp.Operations.Length);
                    for (int i = 0; i < ssp.Operations.Length; ++i)
                    {
                        SearchOperation so    = ssp.Operations[i];
                        SearchOperation clone = (SearchOperation)so.Clone();
                        clone.Isomorphy.Parallel = true;
                        operations.Add(clone);
                        if (clone.Element is PatternCondition)
                        {
                            SetNeedForParallelizedVersion((clone.Element as PatternCondition).ConditionExpression);
                        }
                    }
                    ScheduledSearchPlan clonedSsp = new ScheduledSearchPlan(
                        altCase, operations.ToArray(), operations.Count > 0 ? operations[0].CostToEnd : 0);
                    altCase.parallelizedSchedule[0] = clonedSsp;

                    ParallelizeNegativeIndependent(clonedSsp);
                    ParallelizeAlternativeIterated(altCase);
                    ParallelizeYielding(altCase);
                }
            }
            foreach (Iterated iter in patternGraph.iteratedsPlusInlined)
            {
                ScheduledSearchPlan ssp = iter.iteratedPattern.schedulesIncludingNegativesAndIndependents[0];
                iter.iteratedPattern.parallelizedSchedule = new ScheduledSearchPlan[1];
                List <SearchOperation> operations = new List <SearchOperation>(ssp.Operations.Length);
                for (int i = 0; i < ssp.Operations.Length; ++i)
                {
                    SearchOperation so    = ssp.Operations[i];
                    SearchOperation clone = (SearchOperation)so.Clone();
                    clone.Isomorphy.Parallel = true;
                    operations.Add(clone);
                    if (clone.Element is PatternCondition)
                    {
                        SetNeedForParallelizedVersion((clone.Element as PatternCondition).ConditionExpression);
                    }
                }
                ScheduledSearchPlan clonedSsp = new ScheduledSearchPlan(
                    iter.iteratedPattern, operations.ToArray(), operations.Count > 0 ? operations[0].CostToEnd : 0);
                iter.iteratedPattern.parallelizedSchedule[0] = clonedSsp;

                ParallelizeNegativeIndependent(clonedSsp);
                ParallelizeAlternativeIterated(iter.iteratedPattern);
                ParallelizeYielding(iter.iteratedPattern);
            }
        }
예제 #4
0
        public static bool IsOperationAnInlinedIndependentElement(SearchOperation so)
        {
            if (so.Element is SearchPlanNode)
            {
                if (((SearchPlanNode)so.Element).PatternElement.OriginalIndependentElement != null)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #5
0
        /// <summary>
        /// Non- is-matched-flag-based isomorphy checking for nested negatives/independents,
        /// patch into already cloned parallel ssp
        /// </summary>
        private static void ParallelizeNegativeIndependent(ScheduledSearchPlan ssp)
        {
            foreach (SearchOperation so in ssp.Operations)
            {
                so.Isomorphy.Parallel = true;

                if (so.Type == SearchOperationType.NegativePattern ||
                    so.Type == SearchOperationType.IndependentPattern)
                {
                    ScheduledSearchPlan    nestedSsp  = (ScheduledSearchPlan)so.Element;
                    List <SearchOperation> operations = new List <SearchOperation>(nestedSsp.Operations.Length);
                    for (int i = 0; i < nestedSsp.Operations.Length; ++i)
                    {
                        SearchOperation nestedSo = nestedSsp.Operations[i];
                        SearchOperation clone    = (SearchOperation)nestedSo.Clone();
                        operations.Add(clone);
                        if (clone.Element is PatternCondition)
                        {
                            SetNeedForParallelizedVersion((clone.Element as PatternCondition).ConditionExpression);
                        }
                    }
                    Debug.Assert(nestedSsp.PatternGraph.parallelizedSchedule == null); // may fire in case explain was used before, ignore it then
                    nestedSsp.PatternGraph.parallelizedSchedule = new ScheduledSearchPlan[1];
                    ScheduledSearchPlan clonedSsp = new ScheduledSearchPlan(
                        nestedSsp.PatternGraph, operations.ToArray(), operations.Count > 0 ? operations[0].CostToEnd : 0);
                    nestedSsp.PatternGraph.parallelizedSchedule[0] = clonedSsp;
                    so.Element = clonedSsp;

                    ParallelizeNegativeIndependent(clonedSsp);
                    ParallelizeAlternativeIterated(nestedSsp.PatternGraph);
                    if (so.Type == SearchOperationType.IndependentPattern)
                    {
                        ParallelizeYielding(nestedSsp.PatternGraph);
                    }
                }
            }
        }
예제 #6
0
 private static void InsertInlinedElementIdentityCheckIntoSchedule(PatternGraph patternGraph, List <SearchOperation> operations)
 {
     for (int i = 0; i < operations.Count; ++i)
     {
         PatternElement assignmentSource = null;
         if (operations[i].Element is SearchPlanNode)
         {
             assignmentSource = ((SearchPlanNode)operations[i].Element).PatternElement.AssignmentSource;
         }
         if (assignmentSource != null && operations[i].Type != SearchOperationType.Identity)
         {
             for (int j = 0; j < operations.Count; ++j)
             {
                 SearchPlanNode binder = null;
                 if (operations[j].Element is SearchPlanNode)
                 {
                     binder = (SearchPlanNode)operations[j].Element;
                 }
                 if (binder != null &&
                     binder.PatternElement == assignmentSource &&
                     operations[j].Type != SearchOperationType.Identity)
                 {
                     if (operations[i].Type != SearchOperationType.Assign &&
                         operations[j].Type != SearchOperationType.Assign)
                     {
                         int             indexOfSecond = Math.Max(i, j);
                         SearchOperation so            = new SearchOperation(SearchOperationType.Identity,
                                                                             operations[i].Element, binder, operations[indexOfSecond].CostToEnd);
                         operations.Insert(indexOfSecond + 1, so);
                         break;
                     }
                 }
             }
         }
     }
 }
예제 #7
0
        public static void Explain(SearchOperation so, SourceBuilder sb, IGraphModel model)
        {
            SearchPlanNode src = so.SourceSPNode as SearchPlanNode;
            SearchPlanNode tgt = so.Element as SearchPlanNode;
            String         connectednessCheck = "";

            if (so.ConnectednessCheck.PatternElementName != null)
            {
                connectednessCheck = " check " + so.ConnectednessCheck.PatternNodeName
                                     + (so.ConnectednessCheck.TheOtherPatternNodeName != null ? " or " + so.ConnectednessCheck.TheOtherPatternNodeName : "")
                                     + " connected to " + so.ConnectednessCheck.PatternEdgeName;
            }

            switch (so.Type)
            {
            case SearchOperationType.Outgoing:
                sb.AppendFront("from " + src.PatternElement.UnprefixedName + " outgoing -" + tgt.PatternElement.UnprefixedName + ":" + model.EdgeModel.Types[tgt.PatternElement.TypeID].Name + "->" + connectednessCheck + "\n");
                break;

            case SearchOperationType.Incoming:
                sb.AppendFront("from " + src.PatternElement.UnprefixedName + " incoming <-" + tgt.PatternElement.UnprefixedName + ":" + model.EdgeModel.Types[tgt.PatternElement.TypeID].Name + "-" + connectednessCheck + "\n");
                break;

            case SearchOperationType.Incident:
                sb.AppendFront("from " + src.PatternElement.UnprefixedName + " incident <-" + tgt.PatternElement.UnprefixedName + ":" + model.EdgeModel.Types[tgt.PatternElement.TypeID].Name + "->" + connectednessCheck + "\n");
                break;

            case SearchOperationType.ImplicitSource:
                sb.AppendFront("from <-" + src.PatternElement.UnprefixedName + "- get source " + tgt.PatternElement.UnprefixedName + ":" + model.NodeModel.Types[tgt.PatternElement.TypeID].Name + connectednessCheck + "\n");
                break;

            case SearchOperationType.ImplicitTarget:
                sb.AppendFront("from -" + src.PatternElement.UnprefixedName + "-> get target " + tgt.PatternElement.UnprefixedName + ":" + model.NodeModel.Types[tgt.PatternElement.TypeID].Name + connectednessCheck + "\n");
                break;

            case SearchOperationType.Implicit:
                sb.AppendFront("from <-" + src.PatternElement.UnprefixedName + "-> get implicit " + tgt.PatternElement.UnprefixedName + ":" + model.NodeModel.Types[tgt.PatternElement.TypeID].Name + connectednessCheck + "\n");
                break;

            case SearchOperationType.Lookup:
                if (tgt.PatternElement is PatternNode)
                {
                    sb.AppendFront("lookup " + tgt.PatternElement.UnprefixedName + ":" + model.NodeModel.Types[tgt.PatternElement.TypeID].Name + " in graph" + connectednessCheck + "\n");
                }
                else
                {
                    sb.AppendFront("lookup -" + tgt.PatternElement.UnprefixedName + ":" + model.EdgeModel.Types[tgt.PatternElement.TypeID].Name + "-> in graph" + connectednessCheck + "\n");
                }
                break;

            case SearchOperationType.ActionPreset:
                sb.AppendFront("(preset: " + tgt.PatternElement.UnprefixedName + connectednessCheck + ")\n");
                break;

            case SearchOperationType.NegIdptPreset:
                sb.AppendFront("(preset: " + tgt.PatternElement.UnprefixedName + (tgt.PatternElement.PresetBecauseOfIndependentInlining ? " after independent inlining" : "") + connectednessCheck + ")\n");
                break;

            case SearchOperationType.SubPreset:
                sb.AppendFront("(preset: " + tgt.PatternElement.UnprefixedName + connectednessCheck + ")\n");
                break;

            case SearchOperationType.Condition:
                sb.AppendFront("if { depending on " + String.Join(",", ((PatternCondition)so.Element).NeededNodeNames)
                               + (((PatternCondition)so.Element).NeededNodeNames.Length != 0 && ((PatternCondition)so.Element).NeededEdgeNames.Length != 0 ? "," : "")
                               + String.Join(",", ((PatternCondition)so.Element).NeededEdgeNames) + " }\n");
                break;

            case SearchOperationType.NegativePattern:
                sb.AppendFront("negative {\n");
                sb.Indent();
                Explain(((ScheduledSearchPlan)so.Element), sb, model);
                sb.Append("\n");
                ((ScheduledSearchPlan)so.Element).PatternGraph.ExplainNested(sb, model);
                sb.Unindent();
                sb.AppendFront("}\n");
                break;

            case SearchOperationType.IndependentPattern:
                sb.AppendFront("independent {\n");
                sb.Indent();
                Explain(((ScheduledSearchPlan)so.Element), sb, model);
                sb.Append("\n");
                ((ScheduledSearchPlan)so.Element).PatternGraph.ExplainNested(sb, model);
                sb.Unindent();
                sb.AppendFront("}\n");
                break;

            case SearchOperationType.PickFromStorage:
            case SearchOperationType.PickFromStorageDependent:
                sb.AppendFront(tgt.PatternElement.UnprefixedName + "{" + so.Storage.ToString() + "}" + connectednessCheck + "\n");
                break;

            case SearchOperationType.MapWithStorage:
            case SearchOperationType.MapWithStorageDependent:
                sb.AppendFront(tgt.PatternElement.UnprefixedName + "{" + so.Storage.ToString() + "[" + so.StorageIndex.ToString() + "]}" + connectednessCheck + "\n");
                break;

            case SearchOperationType.PickFromIndex:
            case SearchOperationType.PickFromIndexDependent:
                sb.AppendFront(tgt.PatternElement.UnprefixedName + "{" + so.IndexAccess.ToString() + "}" + connectednessCheck + "\n");
                break;

            case SearchOperationType.PickByName:
            case SearchOperationType.PickByNameDependent:
                sb.AppendFront(tgt.PatternElement.UnprefixedName + "{" + so.NameLookup.ToString() + "}" + connectednessCheck + "\n");
                break;

            case SearchOperationType.PickByUnique:
            case SearchOperationType.PickByUniqueDependent:
                sb.AppendFront(tgt.PatternElement.UnprefixedName + "{" + so.UniqueLookup.ToString() + "}" + connectednessCheck + "\n");
                break;

            case SearchOperationType.Cast:
                sb.AppendFront(tgt.PatternElement.UnprefixedName + "<" + src.PatternElement.UnprefixedName + ">" + connectednessCheck + "\n");
                break;

            case SearchOperationType.Assign:
                sb.AppendFront("(" + tgt.PatternElement.UnprefixedName + " = " + src.PatternElement.UnprefixedName + ")\n");
                break;

            case SearchOperationType.Identity:
                sb.AppendFront("(" + tgt.PatternElement.UnprefixedName + " == " + src.PatternElement.UnprefixedName + ")\n");
                break;

            case SearchOperationType.AssignVar:
                sb.AppendFront("(" + tgt.PatternElement.UnprefixedName + " = expr" + ")\n");
                break;

            case SearchOperationType.LockLocalElementsForPatternpath:
                sb.AppendFront("lock for patternpath\n");
                break;

            case SearchOperationType.DefToBeYieldedTo:
                if (so.Element is PatternVariable)
                {
                    sb.AppendFront("def " + ((PatternVariable)so.Element).Name + "\n");
                }
                else
                {
                    sb.AppendFront("def " + ((SearchPlanNode)so.Element).PatternElement.Name + "\n");
                }
                break;

            case SearchOperationType.ParallelLookup:
                if (tgt.PatternElement is PatternNode)
                {
                    sb.AppendFront("parallelized lookup " + tgt.PatternElement.UnprefixedName + ":" + model.NodeModel.Types[tgt.PatternElement.TypeID].Name + " in graph\n");
                }
                else
                {
                    sb.AppendFront("parallelized lookup -" + tgt.PatternElement.UnprefixedName + ":" + model.EdgeModel.Types[tgt.PatternElement.TypeID].Name + "-> in graph\n");
                }
                break;

            case SearchOperationType.ParallelPickFromStorage:
            case SearchOperationType.ParallelPickFromStorageDependent:
                sb.AppendFront("parallelized " + tgt.PatternElement.UnprefixedName + "{" + so.Storage.ToString() + "}\n");
                break;

            case SearchOperationType.ParallelOutgoing:
                sb.AppendFront("parallelized from " + src.PatternElement.UnprefixedName + " outgoing -" + tgt.PatternElement.UnprefixedName + ":" + model.EdgeModel.Types[tgt.PatternElement.TypeID].Name + "->\n");
                break;

            case SearchOperationType.ParallelIncoming:
                sb.AppendFront("parallelized from " + src.PatternElement.UnprefixedName + " incoming <-" + tgt.PatternElement.UnprefixedName + ":" + model.EdgeModel.Types[tgt.PatternElement.TypeID].Name + "-\n");
                break;

            case SearchOperationType.ParallelIncident:
                sb.AppendFront("parallelized from " + src.PatternElement.UnprefixedName + " incident <-" + tgt.PatternElement.UnprefixedName + ":" + model.EdgeModel.Types[tgt.PatternElement.TypeID].Name + "->\n");
                break;

            case SearchOperationType.WriteParallelPreset:
            case SearchOperationType.ParallelPreset:
            case SearchOperationType.WriteParallelPresetVar:
            case SearchOperationType.ParallelPresetVar:
            case SearchOperationType.SetupParallelLookup:
            case SearchOperationType.SetupParallelPickFromStorage:
            case SearchOperationType.SetupParallelPickFromStorageDependent:
            case SearchOperationType.SetupParallelOutgoing:
            case SearchOperationType.SetupParallelIncoming:
            case SearchOperationType.SetupParallelIncident:
                break; // uninteresting to the user
            }
        }
예제 #8
0
        /// <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));
        }
예제 #9
0
        /// <summary>
        /// Inserts inlined variable assignments into the schedule given by the operations list at their earliest possible position
        /// </summary>
        private static void InsertInlinedVariableAssignmentsIntoSchedule(PatternGraph patternGraph, List <SearchOperation> operations)
        {
            // compute the number of inlined parameter variables
            int numInlinedParameterVariables = 0;

            foreach (PatternVariable var in patternGraph.variablesPlusInlined)
            {
                if (var.AssignmentSource != null && patternGraph.WasInlinedHere(var.originalSubpatternEmbedding))
                {
                    ++numInlinedParameterVariables;
                }
            }

            if (numInlinedParameterVariables == 0)
            {
                return;
            }

            // get the inlined parameter variables and the elements needed in order to compute their defining expression
            Dictionary <String, PatternElement>[] neededElements = new Dictionary <String, PatternElement> [numInlinedParameterVariables];
            PatternVariable[] inlinedParameterVariables          = new PatternVariable[numInlinedParameterVariables];
            int curInlParamVar = 0;

            foreach (PatternVariable var in patternGraph.variablesPlusInlined)
            {
                if (var.AssignmentSource == null)
                {
                    continue;
                }
                if (!patternGraph.WasInlinedHere(var.originalSubpatternEmbedding))
                {
                    continue;
                }

                neededElements[curInlParamVar] = new Dictionary <string, PatternElement>();
                for (int i = 0; i < var.AssignmentDependencies.neededNodeNames.Length; ++i)
                {
                    String      neededNodeName = var.AssignmentDependencies.neededNodeNames[i];
                    PatternNode neededNode     = var.AssignmentDependencies.neededNodes[i];
                    neededElements[curInlParamVar][neededNodeName] = neededNode;
                }
                for (int i = 0; i < var.AssignmentDependencies.neededEdgeNames.Length; ++i)
                {
                    String      neededEdgeName = var.AssignmentDependencies.neededEdgeNames[i];
                    PatternEdge neededEdge     = var.AssignmentDependencies.neededEdges[i];
                    neededElements[curInlParamVar][neededEdgeName] = neededEdge;
                }
                inlinedParameterVariables[curInlParamVar] = var;

                ++curInlParamVar;
            }

            // iterate over all inlined parameter variables
            for (int i = 0; i < inlinedParameterVariables.Length; ++i)
            {
                int   j;
                float costToEnd = 0;

                // find leftmost place in scheduled search plan for current assignment
                // by search from end of schedule forward until the first element the expression assigned is dependent on is found
                for (j = operations.Count - 1; j >= 0; --j)
                {
                    SearchOperation op = operations[j];
                    if (op.Type == SearchOperationType.Condition ||
                        op.Type == SearchOperationType.Assign ||
                        op.Type == SearchOperationType.AssignVar ||
                        op.Type == SearchOperationType.NegativePattern ||
                        op.Type == SearchOperationType.IndependentPattern ||
                        op.Type == SearchOperationType.DefToBeYieldedTo)
                    {
                        continue;
                    }

                    if (neededElements[i].ContainsKey(((SearchPlanNode)op.Element).PatternElement.Name))
                    {
                        costToEnd = op.CostToEnd;
                        break;
                    }
                }

                SearchOperation so = new SearchOperation(SearchOperationType.AssignVar,
                                                         inlinedParameterVariables[i], null, costToEnd);
                so.Expression = inlinedParameterVariables[i].AssignmentSource;
                operations.Insert(j + 1, so);
            }
        }
예제 #10
0
        /// <summary>
        /// Inserts conditions into the schedule given by the operations list at their earliest possible position
        /// todo: set/map operations are potentially expensive, they shouldn't be insertes asap, but depending an weight,
        /// derived from statistics over set/map size for graph elements, quiet well known for anonymous rule sets
        /// </summary>
        private static void InsertConditionsIntoSchedule(PatternCondition[] conditions, List <SearchOperation> operations, bool lazyNegativeIndependentConditionEvaluation)
        {
            // get needed (in order to evaluate it) elements of each condition
            Dictionary <String, object>[] neededElements = new Dictionary <String, object> [conditions.Length];
            for (int i = 0; i < conditions.Length; ++i)
            {
                neededElements[i] = new Dictionary <string, object>();
                for (int j = 0; j < conditions[i].NeededNodeNames.Length; ++j)
                {
                    String      neededNodeName = conditions[i].NeededNodeNames[j];
                    PatternNode neededNode     = conditions[i].NeededNodes[j];
                    neededElements[i][neededNodeName] = neededNode;
                }
                for (int j = 0; j < conditions[i].NeededEdgeNames.Length; ++j)
                {
                    String      neededEdgeName = conditions[i].NeededEdgeNames[j];
                    PatternEdge neededEdge     = conditions[i].NeededEdges[j];
                    neededElements[i][neededEdgeName] = neededEdge;
                }
                for (int j = 0; j < conditions[i].NeededVariableNames.Length; ++j)
                {
                    String          neededVariableName = conditions[i].NeededVariableNames[j];
                    PatternVariable neededVariable     = conditions[i].NeededVariables[j];
                    neededElements[i][neededVariableName] = neededVariable;
                }
            }

            // iterate over all conditions
            for (int i = 0; i < conditions.Length; ++i)
            {
                int   j;
                float costToEnd = 0;

                // find leftmost place in scheduled search plan for current condition
                // by search from end of schedule forward until the first element the condition is dependent on is found
                for (j = operations.Count - 1; j >= 0; --j)
                {
                    SearchOperation op = operations[j];
                    if (op.Type == SearchOperationType.Condition ||
                        op.Type == SearchOperationType.NegativePattern ||
                        op.Type == SearchOperationType.IndependentPattern ||
                        op.Type == SearchOperationType.DefToBeYieldedTo)
                    {
                        continue;
                    }

                    if (lazyNegativeIndependentConditionEvaluation)
                    {
                        break;
                    }

                    if (op.Type == SearchOperationType.AssignVar)
                    {
                        if (neededElements[i].ContainsKey(((PatternVariable)op.Element).Name))
                        {
                            costToEnd = op.CostToEnd;
                            break;
                        }
                        continue;
                    }

                    if (neededElements[i].ContainsKey(((SearchPlanNode)op.Element).PatternElement.Name))
                    {
                        costToEnd = op.CostToEnd;
                        break;
                    }
                }

                operations.Insert(j + 1, new SearchOperation(SearchOperationType.Condition,
                                                             conditions[i], null, costToEnd));
            }
        }
예제 #11
0
        /// <summary>
        /// Recursively assembles interpretation plan from scheduled search plan, beginning at index 0.
        /// Decides which specialized build procedure is to be called.
        /// The specialized build procedure then calls this procedure again,
        /// in order to process the next search plan operation at the following index.
        /// The insertionPoint is the lastly built operation;
        /// the next operation built is inserted into the next link of it,
        /// then it becomes the current insertionPoint.
        /// </summary>
        private void BuildInterpretationPlan(InterpretationPlan insertionPoint, int index)
        {
            if (index >= ssp.Operations.Length)
            { // end of scheduled search plan reached, stop recursive iteration
                buildMatchComplete(insertionPoint);
                return;
            }

            SearchOperation op = ssp.Operations[index];

            // for current scheduled search plan operation
            // insert corresponding interpretation plan operations into interpretation plan
            switch (op.Type)
            {
            case SearchOperationType.Lookup:
                if (((SearchPlanNode)op.Element).NodeType == PlanNodeType.Node)
                {
                    buildLookup(insertionPoint, index, (SearchPlanNodeNode)op.Element);
                }
                else
                {
                    buildLookup(insertionPoint, index, (SearchPlanEdgeNode)op.Element);
                }
                break;

            case SearchOperationType.ImplicitSource:
                buildImplicit(insertionPoint, index,
                              (SearchPlanEdgeNode)op.SourceSPNode,
                              (SearchPlanNodeNode)op.Element,
                              ImplicitNodeType.Source);
                break;

            case SearchOperationType.ImplicitTarget:
                buildImplicit(insertionPoint, index,
                              (SearchPlanEdgeNode)op.SourceSPNode,
                              (SearchPlanNodeNode)op.Element,
                              ImplicitNodeType.Target);
                break;

            case SearchOperationType.Implicit:
                buildImplicit(insertionPoint, index,
                              (SearchPlanEdgeNode)op.SourceSPNode,
                              (SearchPlanNodeNode)op.Element,
                              ImplicitNodeType.SourceOrTarget);
                break;

            case SearchOperationType.Incoming:
                buildIncident(insertionPoint, index,
                              (SearchPlanNodeNode)op.SourceSPNode,
                              (SearchPlanEdgeNode)op.Element,
                              IncidentEdgeType.Incoming);
                break;

            case SearchOperationType.Outgoing:
                buildIncident(insertionPoint, index,
                              (SearchPlanNodeNode)op.SourceSPNode,
                              (SearchPlanEdgeNode)op.Element,
                              IncidentEdgeType.Outgoing);
                break;

            case SearchOperationType.Incident:
                buildIncident(insertionPoint, index,
                              (SearchPlanNodeNode)op.SourceSPNode,
                              (SearchPlanEdgeNode)op.Element,
                              IncidentEdgeType.IncomingOrOutgoing);
                break;

            case SearchOperationType.Condition:
                buildCondition(insertionPoint, index,
                               (PatternCondition)op.Element);
                break;

            default:
                throw new Exception("Unknown or unsupported search operation");
            }
        }
예제 #12
0
        /// <summary>
        /// Parallelize the scheduled search plan to the branching factor,
        /// splitting it at the first loop into a header part and a body part
        /// </summary>
        public static void ParallelizeHeadBody(LGSPRulePattern rulePattern)
        {
            Debug.Assert(rulePattern.patternGraph.schedulesIncludingNegativesAndIndependents.Length == 1);
            ScheduledSearchPlan ssp = rulePattern.patternGraph.schedulesIncludingNegativesAndIndependents[0];

            int indexToSplitAt = 0;

            for (int i = 0; i < ssp.Operations.Length; ++i)
            {
                SearchOperation so = ssp.Operations[i];
                if (so.Type == SearchOperationType.Lookup || so.Type == SearchOperationType.Incident ||
                    so.Type == SearchOperationType.Incoming || so.Type == SearchOperationType.Outgoing ||
                    so.Type == SearchOperationType.PickFromStorage || so.Type == SearchOperationType.PickFromStorageDependent ||
                    so.Type == SearchOperationType.PickFromIndex || so.Type == SearchOperationType.PickFromIndexDependent)
                {
                    indexToSplitAt = i;
                    break;
                }
            }

            rulePattern.patternGraph.parallelizedSchedule = new ScheduledSearchPlan[2];
            List <SearchOperation> headOperations = new List <SearchOperation>();
            List <SearchOperation> bodyOperations = new List <SearchOperation>();

            for (int i = 0; i < rulePattern.Inputs.Length; ++i)
            {
                if (rulePattern.Inputs[i] is VarType) // those don't appear in the schedule, they are only extracted into the search program
                {
                    VarType         varType = (VarType)rulePattern.Inputs[i];
                    String          varName = rulePattern.InputNames[i];
                    PatternVariable dummy   = new PatternVariable(varType, varName, varName, i, false, null);
                    headOperations.Add(new SearchOperation(SearchOperationType.WriteParallelPresetVar,
                                                           dummy, null, 0));
                    bodyOperations.Add(new SearchOperation(SearchOperationType.ParallelPresetVar,
                                                           dummy, null, 0));
                }
            }
            for (int i = 0; i < ssp.Operations.Length; ++i)
            {
                SearchOperation so = ssp.Operations[i];
                if (i < indexToSplitAt)
                {
                    SearchOperation clone = (SearchOperation)so.Clone();
                    clone.Isomorphy.Parallel          = true;
                    clone.Isomorphy.LockForAllThreads = true;
                    headOperations.Add(clone);
                    switch (so.Type)
                    {
                    // the target binding looping operations can't appear in the header, so we don't treat them here
                    // the non-target binding operations are completely handled by just adding them, happended already above
                    // the target binding non-looping operations are handled below,
                    // by parallel preset writing in the header and reading in the body
                    // with exception of def, its declaration and initializion is just re-executed in the body
                    // some presets can't appear in an action header, they are thus not taken care of
                    case SearchOperationType.ActionPreset:
                    case SearchOperationType.MapWithStorage:
                    case SearchOperationType.MapWithStorageDependent:
                    case SearchOperationType.Cast:
                    case SearchOperationType.Assign:
                    case SearchOperationType.Identity:
                    case SearchOperationType.ImplicitSource:
                    case SearchOperationType.ImplicitTarget:
                    case SearchOperationType.Implicit:
                        headOperations.Add(new SearchOperation(SearchOperationType.WriteParallelPreset,
                                                               (SearchPlanNode)so.Element, so.SourceSPNode, 0));
                        bodyOperations.Add(new SearchOperation(SearchOperationType.ParallelPreset,
                                                               (SearchPlanNode)so.Element, so.SourceSPNode, 0));
                        break;

                    case SearchOperationType.AssignVar:
                        headOperations.Add(new SearchOperation(SearchOperationType.WriteParallelPresetVar,
                                                               (PatternVariable)so.Element, so.SourceSPNode, 0));
                        bodyOperations.Add(new SearchOperation(SearchOperationType.ParallelPresetVar,
                                                               (PatternVariable)so.Element, so.SourceSPNode, 0));
                        break;

                    case SearchOperationType.DefToBeYieldedTo:
                        bodyOperations.Add((SearchOperation)so.Clone());
                        break;
                    }
                }
                else if (i == indexToSplitAt)
                {
                    SearchOperation cloneHead;
                    SearchOperation cloneBody;
                    switch (so.Type)
                    {
                    case SearchOperationType.Lookup:
                        cloneHead = (SearchOperation)so.Clone(SearchOperationType.SetupParallelLookup);
                        cloneBody = (SearchOperation)so.Clone(SearchOperationType.ParallelLookup);
                        break;

                    case SearchOperationType.Incident:
                        cloneHead = (SearchOperation)so.Clone(SearchOperationType.SetupParallelIncident);
                        cloneBody = (SearchOperation)so.Clone(SearchOperationType.ParallelIncident);
                        break;

                    case SearchOperationType.Incoming:
                        cloneHead = (SearchOperation)so.Clone(SearchOperationType.SetupParallelIncoming);
                        cloneBody = (SearchOperation)so.Clone(SearchOperationType.ParallelIncoming);
                        break;

                    case SearchOperationType.Outgoing:
                        cloneHead = (SearchOperation)so.Clone(SearchOperationType.SetupParallelOutgoing);
                        cloneBody = (SearchOperation)so.Clone(SearchOperationType.ParallelOutgoing);
                        break;

                    case SearchOperationType.PickFromStorage:
                        cloneHead = (SearchOperation)so.Clone(SearchOperationType.SetupParallelPickFromStorage);
                        cloneBody = (SearchOperation)so.Clone(SearchOperationType.ParallelPickFromStorage);
                        break;

                    case SearchOperationType.PickFromStorageDependent:
                        cloneHead = (SearchOperation)so.Clone(SearchOperationType.SetupParallelPickFromStorageDependent);
                        cloneBody = (SearchOperation)so.Clone(SearchOperationType.ParallelPickFromStorageDependent);
                        break;

                    case SearchOperationType.PickFromIndex:
                        cloneHead = (SearchOperation)so.Clone(SearchOperationType.SetupParallelPickFromIndex);
                        cloneBody = (SearchOperation)so.Clone(SearchOperationType.ParallelPickFromIndex);
                        break;

                    case SearchOperationType.PickFromIndexDependent:
                        cloneHead = (SearchOperation)so.Clone(SearchOperationType.SetupParallelPickFromIndexDependent);
                        cloneBody = (SearchOperation)so.Clone(SearchOperationType.ParallelPickFromIndexDependent);
                        break;

                    default: // failure, operation at this index cannot be parallelized/parallelization not supported
                        cloneHead = null;
                        cloneBody = null;
                        break;
                    }
                    headOperations.Add(cloneHead);
                    cloneBody.Isomorphy.Parallel = true;
                    bodyOperations.Add(cloneBody);
                }
                else
                {
                    SearchOperation clone = (SearchOperation)so.Clone();
                    clone.Isomorphy.Parallel = true;
                    bodyOperations.Add(clone);
                    if (clone.Element is PatternCondition)
                    {
                        SetNeedForParallelizedVersion((clone.Element as PatternCondition).ConditionExpression);
                    }
                }
            }
            ScheduledSearchPlan headSsp = new ScheduledSearchPlan(
                rulePattern.patternGraph, headOperations.ToArray(), headOperations.Count > 0 ? headOperations[0].CostToEnd : 0);

            rulePattern.patternGraph.parallelizedSchedule[0] = headSsp;
            ScheduledSearchPlan bodySsp = new ScheduledSearchPlan(
                rulePattern.patternGraph, bodyOperations.ToArray(), bodyOperations.Count > 0 ? bodyOperations[0].CostToEnd : 0);

            rulePattern.patternGraph.parallelizedSchedule[1] = bodySsp;
            ParallelizeNegativeIndependent(bodySsp);
            ParallelizeAlternativeIterated(rulePattern.patternGraph);
            ParallelizeYielding(rulePattern.patternGraph);
        }
예제 #13
0
        /// <summary>
        /// Inserts schedules of negative and independent pattern graphs into the schedule of the enclosing pattern graph
        /// for the schedule with the given array index
        /// </summary>
        private static void InsertNegativesAndIndependentsIntoSchedule(PatternGraph patternGraph, int index, bool lazyNegativeIndependentConditionEvaluation)
        {
            // todo: erst implicit node, dann negative/independent, auch wenn negative/independent mit erstem implicit moeglich wird
            patternGraph.schedulesIncludingNegativesAndIndependents[index] = null; // an explain might have filled this

            List <SearchOperation> operations = new List <SearchOperation>();

            for (int i = 0; i < patternGraph.schedules[index].Operations.Length; ++i)
            {
                operations.Add(patternGraph.schedules[index].Operations[i]);
            }

            // nested patterns on the way to an enclosed patternpath modifier
            // must get matched after all local nodes and edges, because they require
            // all outer elements to be known in order to lock them for patternpath processing
            if (patternGraph.patternGraphsOnPathToEnclosedPatternpath
                .Contains(patternGraph.pathPrefix + patternGraph.name))
            {
                operations.Add(new SearchOperation(SearchOperationType.LockLocalElementsForPatternpath, null, null,
                                                   patternGraph.schedules[index].Operations.Length != 0 ? patternGraph.schedules[index].Operations[patternGraph.schedules[index].Operations.Length - 1].CostToEnd : 0));
            }

            // iterate over all negative scheduled search plans (TODO: order?)
            for (int i = 0; i < patternGraph.negativePatternGraphsPlusInlined.Length; ++i)
            {
                ScheduledSearchPlan negSchedule = patternGraph.negativePatternGraphsPlusInlined[i].schedulesIncludingNegativesAndIndependents[0];
                int   bestFitIndex     = operations.Count;
                float bestFitCostToEnd = 0;

                // find best place in scheduled search plan for current negative pattern
                // during search from end of schedule forward until the first element the negative pattern is dependent on is found
                for (int j = operations.Count - 1; j >= 0; --j)
                {
                    SearchOperation op = operations[j];
                    if (op.Type == SearchOperationType.Condition ||
                        op.Type == SearchOperationType.NegativePattern ||
                        op.Type == SearchOperationType.IndependentPattern ||
                        op.Type == SearchOperationType.AssignVar)
                    {
                        continue;
                    }

                    if (lazyNegativeIndependentConditionEvaluation)
                    {
                        break;
                    }

                    if (op.Type == SearchOperationType.LockLocalElementsForPatternpath ||
                        op.Type == SearchOperationType.DefToBeYieldedTo)
                    {
                        break; // LockLocalElementsForPatternpath and DefToBeYieldedTo are barriers for neg/idpt
                    }

                    if (patternGraph.negativePatternGraphsPlusInlined[i].neededNodes.ContainsKey(((SearchPlanNode)op.Element).PatternElement.Name) ||
                        patternGraph.negativePatternGraphsPlusInlined[i].neededEdges.ContainsKey(((SearchPlanNode)op.Element).PatternElement.Name))
                    {
                        break;
                    }

                    if (negSchedule.Cost <= op.CostToEnd)
                    {
                        // best fit as CostToEnd is monotonously growing towards operation[0]
                        bestFitIndex     = j;
                        bestFitCostToEnd = op.CostToEnd;
                    }
                }

                // insert pattern at best position
                operations.Insert(bestFitIndex, new SearchOperation(SearchOperationType.NegativePattern,
                                                                    negSchedule, null, bestFitCostToEnd + negSchedule.Cost));

                // update costs of operations before best position
                for (int j = 0; j < bestFitIndex; ++j)
                {
                    operations[j].CostToEnd += negSchedule.Cost;
                }
            }

            // iterate over all independent scheduled search plans (TODO: order?)
            for (int i = 0; i < patternGraph.independentPatternGraphsPlusInlined.Length; ++i)
            {
                ScheduledSearchPlan idptSchedule = patternGraph.independentPatternGraphsPlusInlined[i].schedulesIncludingNegativesAndIndependents[0];
                int   bestFitIndex     = operations.Count;
                float bestFitCostToEnd = 0;

                IDictionary <PatternElement, SetValueType> presetsFromIndependentInlining = ExtractOwnElements(patternGraph.schedules[index], patternGraph.independentPatternGraphsPlusInlined[i]);

                // find best place in scheduled search plan for current independent pattern
                // during search from end of schedule forward until the first element the independent pattern is dependent on is found
                for (int j = operations.Count - 1; j >= 0; --j)
                {
                    SearchOperation op = operations[j];
                    if (op.Type == SearchOperationType.Condition ||
                        op.Type == SearchOperationType.NegativePattern ||
                        op.Type == SearchOperationType.IndependentPattern ||
                        op.Type == SearchOperationType.AssignVar)
                    {
                        continue;
                    }

                    if (lazyNegativeIndependentConditionEvaluation)
                    {
                        break;
                    }

                    if (op.Type == SearchOperationType.LockLocalElementsForPatternpath ||
                        op.Type == SearchOperationType.DefToBeYieldedTo)
                    {
                        break; // LockLocalElementsForPatternpath and DefToBeYieldedTo are barriers for neg/idpt
                    }

                    PatternElement pe = ((SearchPlanNode)op.Element).PatternElement;
                    if (patternGraph.independentPatternGraphsPlusInlined[i].neededNodes.ContainsKey(pe.Name) ||
                        patternGraph.independentPatternGraphsPlusInlined[i].neededEdges.ContainsKey(pe.Name))
                    {
                        break;
                    }

                    if (pe.OriginalIndependentElement != null &&
                        presetsFromIndependentInlining.ContainsKey(pe.OriginalIndependentElement))
                    {
                        break;
                    }

                    if (idptSchedule.Cost <= op.CostToEnd)
                    {
                        // best fit as CostToEnd is monotonously growing towards operation[0]
                        bestFitIndex     = j;
                        bestFitCostToEnd = op.CostToEnd;
                    }
                }

                // insert pattern at best position
                operations.Insert(bestFitIndex, new SearchOperation(SearchOperationType.IndependentPattern,
                                                                    idptSchedule, null, bestFitCostToEnd + idptSchedule.Cost));

                // update costs of operations before best position
                for (int j = 0; j < bestFitIndex; ++j)
                {
                    operations[j].CostToEnd += idptSchedule.Cost;
                }
            }

            InsertInlinedIndependentCheckForDuplicateMatch(operations);

            float cost = operations.Count > 0 ? operations[0].CostToEnd : 0;

            patternGraph.schedulesIncludingNegativesAndIndependents[index] =
                new ScheduledSearchPlan(patternGraph, operations.ToArray(), cost);
        }