Beispiel #1
0
        public static IDictionary <PatternElement, SetValueType> ExtractOwnElements(ScheduledSearchPlan nestingScheduledSearchPlan, PatternGraph patternGraph)
        {
            Dictionary <PatternElement, SetValueType> ownElements = new Dictionary <PatternElement, SetValueType>();

            // elements contained in the schedule of the nesting pattern, that are declared in the current pattern graph
            // stem from inlining an indepent, extract them to treat them specially in search plan building (preset from nesting pattern)
            if (nestingScheduledSearchPlan != null)
            {
                for (int i = 0; i < nestingScheduledSearchPlan.Operations.Length; ++i)
                {
                    if (nestingScheduledSearchPlan.Operations[i].Type == SearchOperationType.Condition ||
                        nestingScheduledSearchPlan.Operations[i].Type == SearchOperationType.AssignVar ||
                        nestingScheduledSearchPlan.Operations[i].Type == SearchOperationType.DefToBeYieldedTo)
                    {
                        continue;
                    }

                    SearchPlanNode spn = (SearchPlanNode)nestingScheduledSearchPlan.Operations[i].Element;
                    if (spn.PatternElement.pointOfDefinition == patternGraph)
                    {
                        ownElements.Add(spn.PatternElement.OriginalIndependentElement, null);
                    }
                }
            }

            return(ownElements);
        }
Beispiel #2
0
        private static void DumpEdge(StreamWriter sw, SearchOperationType opType, SearchPlanNode source, SearchPlanNode target, float cost, bool markRed)
        {
            String typeStr = " #";

            switch (opType)
            {
            case SearchOperationType.Outgoing: typeStr = "--"; break;

            case SearchOperationType.Incoming: typeStr = "->"; break;

            case SearchOperationType.Incident: typeStr = "<->"; break;

            case SearchOperationType.ImplicitSource: typeStr = "IS"; break;

            case SearchOperationType.ImplicitTarget: typeStr = "IT"; break;

            case SearchOperationType.Implicit: typeStr = "IM"; break;

            case SearchOperationType.Lookup: typeStr = " *"; break;

            case SearchOperationType.ActionPreset: typeStr = " p"; break;

            case SearchOperationType.NegIdptPreset: typeStr = "np"; break;

            case SearchOperationType.SubPreset: typeStr = "sp"; break;
            }

            sw.WriteLine("edge:{{sourcename:\"{0}\" targetname:\"{1}\" label:\"{2} / {3:0.00}\"{4}}}",
                         GetDumpName(source), GetDumpName(target), typeStr, cost, markRed ? " color:red" : "");
        }
Beispiel #3
0
 public SearchPlanGraph(SearchPlanNode root, SearchPlanNode[] nodes, SearchPlanEdge[] edges)
 {
     Root              = root;
     Nodes             = nodes;
     Edges             = edges;
     NumPresetElements = 0;
     foreach (SearchPlanNode node in nodes)
     {
         if (node.IsPreset)
         {
             ++NumPresetElements;
         }
     }
     foreach (SearchPlanEdge edge in edges)
     {
         if (edge.Type == SearchOperationType.PickFromStorage ||
             edge.Type == SearchOperationType.MapWithStorage ||
             edge.Type == SearchOperationType.PickFromIndex ||
             edge.Type == SearchOperationType.PickByName ||
             edge.Type == SearchOperationType.PickByUnique)
         {
             ++NumIndependentStorageIndexElements;
         }
     }
 }
Beispiel #4
0
        public float LocalCost; // only used in benchmarking

        public SearchPlanEdge(SearchOperationType type, SearchPlanNode source, SearchPlanNode target, float cost)
        {
            Target = target;
            Cost   = cost;
            Source = source;
            Type   = type;
        }
 public SearchOperation(SearchOperationType type, object elem,
                        SearchPlanNode srcSPNode, float costToEnd)
 {
     Type         = type;
     Element      = elem;
     SourceSPNode = srcSPNode;
     CostToEnd    = costToEnd;
 }
Beispiel #6
0
 private static void DumpNode(StreamWriter sw, SearchPlanNode 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);
     }
 }
Beispiel #7
0
        public static void DumpScheduledSearchPlanAsVcg(ScheduledSearchPlan ssp, IGraphModel model, String dumpname)
        {
            StreamWriter sw = new StreamWriter(dumpname + "-scheduledsp.vcg", false);

            sw.WriteLine("graph:{\ninfoname 1: \"Attributes\"\ndisplay_edge_labels: no\nport_sharing: no\nsplines: no\n"
                         + "\nmanhattan_edges: no\nsmanhattan_edges: no\norientation: bottom_to_top\nedges: yes\nnodes: yes\nclassname 1: \"normal\"");
            sw.WriteLine("node:{title:\"root\" label:\"ROOT\"}\n");
            SearchPlanNode root = new SearchPlanNode("root");

            sw.WriteLine("graph:{{title:\"pattern\" label:\"{0}\" status:clustered color:lightgrey", dumpname);

            foreach (SearchOperation op in ssp.Operations)
            {
                switch (op.Type)
                {
                case SearchOperationType.Lookup:
                case SearchOperationType.Incoming:
                case SearchOperationType.Outgoing:
                case SearchOperationType.ImplicitSource:
                case SearchOperationType.ImplicitTarget:
                {
                    SearchPlanNode spnode = (SearchPlanNode)op.Element;
                    DumpNode(sw, spnode);
                    SearchPlanNode src;
                    switch (op.Type)
                    {
                    case SearchOperationType.Lookup:
                    case SearchOperationType.ActionPreset:
                    case SearchOperationType.NegIdptPreset:
                        src = root;
                        break;

                    default:
                        src = op.SourceSPNode;
                        break;
                    }
                    DumpEdge(sw, op.Type, src, spnode, op.CostToEnd, false);
                    break;
                }

                case SearchOperationType.Condition:
                    sw.WriteLine("node:{title:\"Condition\" label:\"CONDITION\"}\n");
                    break;

                case SearchOperationType.NegativePattern:
                    sw.WriteLine("node:{title:\"NAC\" label:\"NAC\"}\n");
                    break;
                }
            }
        }
Beispiel #8
0
 private static String GetDumpName(SearchPlanNode 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);
     }
 }
Beispiel #9
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;
                     }
                 }
             }
         }
     }
 }
Beispiel #10
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
            }
        }
Beispiel #11
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));
        }
Beispiel #12
0
        /// <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));
        }
Beispiel #13
0
        /// <summary>
        /// Determines which homomorphy check operations are necessary
        /// at the operation of the given position within the scheduled search plan
        /// and appends them.
        /// </summary>
        private static void DetermineAndAppendHomomorphyChecks(IGraphModel model, ScheduledSearchPlan ssp, int j)
        {
            // take care of global homomorphy
            FillInGlobalHomomorphyPatternElements(ssp, j);

            ///////////////////////////////////////////////////////////////////////////
            // first handle special case pure homomorphy

            SearchPlanNode spn_j = (SearchPlanNode)ssp.Operations[j].Element;

            if (spn_j.ElementID == -1)
            {
                // inlined from independent for better matching, independent from the rest
                return;
            }

            bool homToAll = true;

            if (spn_j.NodeType == PlanNodeType.Node)
            {
                for (int i = 0; i < ssp.PatternGraph.nodesPlusInlined.Length; ++i)
                {
                    if (!ssp.PatternGraph.homomorphicNodes[spn_j.ElementID - 1, i])
                    {
                        homToAll = false;
                        break;
                    }
                }
            }
            else //(spn_j.NodeType == PlanNodeType.Edge)
            {
                for (int i = 0; i < ssp.PatternGraph.edgesPlusInlined.Length; ++i)
                {
                    if (!ssp.PatternGraph.homomorphicEdges[spn_j.ElementID - 1, i])
                    {
                        homToAll = false;
                        break;
                    }
                }
            }

            if (homToAll)
            {
                // operation is allowed to be homomorph with everything
                // no checks for isomorphy or restricted homomorphy needed at all
                return;
            }

            ///////////////////////////////////////////////////////////////////////////
            // no pure homomorphy, so we have restricted homomorphy or isomorphy
            // and need to inspect the operations before, together with the homomorphy matrix
            // for determining the necessary homomorphy checks

            GraphElementType[] types;
            bool[,] hom;

            if (spn_j.NodeType == PlanNodeType.Node)
            {
                types = model.NodeModel.Types;
                hom   = ssp.PatternGraph.homomorphicNodes;
            }
            else // (spn_j.NodeType == PlanNodeType.Edge)
            {
                types = model.EdgeModel.Types;
                hom   = ssp.PatternGraph.homomorphicEdges;
            }

            // order operation to check against all elements it's not allowed to be homomorph to

            // iterate through the operations before our position
            bool homomorphyPossibleAndAllowed = false;

            for (int i = 0; i < j; ++i)
            {
                // only check operations computing nodes or edges
                if (ssp.Operations[i].Type == SearchOperationType.Condition ||
                    ssp.Operations[i].Type == SearchOperationType.NegativePattern ||
                    ssp.Operations[i].Type == SearchOperationType.IndependentPattern ||
                    ssp.Operations[i].Type == SearchOperationType.Assign ||
                    ssp.Operations[i].Type == SearchOperationType.AssignVar ||
                    ssp.Operations[i].Type == SearchOperationType.DefToBeYieldedTo ||
                    ssp.Operations[i].Type == SearchOperationType.InlinedIndependentCheckForDuplicateMatch)
                {
                    continue;
                }

                SearchPlanNode spn_i = (SearchPlanNode)ssp.Operations[i].Element;

                if (spn_i.NodeType != spn_j.NodeType)
                {
                    // don't compare nodes with edges
                    continue;
                }

                if (spn_i.ElementID == -1)
                {
                    // inlined from independent for better matching, independent from the rest
                    continue;
                }

                // find out whether element types are disjoint
                GraphElementType type_i   = types[spn_i.PatternElement.TypeID];
                GraphElementType type_j   = types[spn_j.PatternElement.TypeID];
                bool             disjoint = true;
                foreach (GraphElementType subtype_i in type_i.SubOrSameTypes)
                {
                    if (type_j.IsA(subtype_i) || subtype_i.IsA(type_j)) // IsA==IsSuperTypeOrSameType
                    {
                        disjoint = false;
                        break;
                    }
                }

                if (disjoint)
                {
                    // don't check elements if their types are disjoint
                    continue;
                }

                // at this position we found out that spn_i and spn_j
                // might get matched to the same host graph element, i.e. homomorphy is possible

                // if that's ok we don't need to insert checks to prevent this from happening
                if (hom[spn_i.ElementID - 1, spn_j.ElementID - 1])
                {
                    homomorphyPossibleAndAllowed = true;
                    continue;
                }

                // otherwise the generated matcher code has to check
                // that pattern element j doesn't get bound to the same graph element
                // the pattern element i is already bound to
                if (ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst == null)
                {
                    ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst = new List <SearchPlanNode>();
                }
                ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst.Add(spn_i);

                // if spn_j might get matched to the same host graph element as spn_i and this is not allowed
                // make spn_i set the is-matched-bit so that spn_j can detect this situation
                ssp.Operations[i].Isomorphy.SetIsMatchedBit = true;
            }

            // only if elements, the operation must be isomorph to, were matched before
            // (otherwise there were only elements, the operation is allowed to be homomorph to,
            //  matched before, so no check needed here)
            if (ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst != null &&
                ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst.Count > 0)
            {
                // order operation to check whether the is-matched-bit is set
                ssp.Operations[j].Isomorphy.CheckIsMatchedBit = true;
            }

            // if no check for isomorphy was skipped due to homomorphy being allowed
            // pure isomorphy is to be guaranteed - simply check the is-matched-bit and be done
            // the pattern elements to check against are only needed
            // if spn_j is allowed to be homomorph to some elements but must be isomorph to some others
            if (ssp.Operations[j].Isomorphy.CheckIsMatchedBit && !homomorphyPossibleAndAllowed)
            {
                ssp.Operations[j].Isomorphy.PatternElementsToCheckAgainst = null;
            }
        }
Beispiel #14
0
        /// <summary>
        /// fill in globally homomorphic elements as exception to global isomorphy check
        /// </summary>
        private static void FillInGlobalHomomorphyPatternElements(ScheduledSearchPlan ssp, int j)
        {
            SearchPlanNode spn_j = (SearchPlanNode)ssp.Operations[j].Element;

            if (spn_j.NodeType == PlanNodeType.Node)
            {
                if (spn_j.ElementID == -1 || // inlined from independent for better matching, independent from the rest
                    ssp.PatternGraph.totallyHomomorphicNodes[spn_j.ElementID - 1])
                {
                    ssp.Operations[j].Isomorphy.TotallyHomomorph = true;
                    return; // iso-exceptions to totally hom are handled with non-global iso checks
                }
            }
            else
            {
                if (spn_j.ElementID == -1 || // inlined from independent for better matching, independent from the rest
                    ssp.PatternGraph.totallyHomomorphicEdges[spn_j.ElementID - 1])
                {
                    ssp.Operations[j].Isomorphy.TotallyHomomorph = true;
                    return; // iso-exceptions to totally hom are handled with non-global iso checks
                }
            }

            bool[,] homGlobal;
            if (spn_j.NodeType == PlanNodeType.Node)
            {
                homGlobal = ssp.PatternGraph.homomorphicNodesGlobal;
            }
            else // (spn_j.NodeType == PlanNodeType.Edge)
            {
                homGlobal = ssp.PatternGraph.homomorphicEdgesGlobal;
            }

            // iterate through the operations before our position
            for (int i = 0; i < j; ++i)
            {
                // only check operations computing nodes or edges
                if (ssp.Operations[i].Type == SearchOperationType.Condition ||
                    ssp.Operations[i].Type == SearchOperationType.NegativePattern ||
                    ssp.Operations[i].Type == SearchOperationType.IndependentPattern ||
                    ssp.Operations[i].Type == SearchOperationType.Assign ||
                    ssp.Operations[i].Type == SearchOperationType.AssignVar ||
                    ssp.Operations[i].Type == SearchOperationType.DefToBeYieldedTo ||
                    ssp.Operations[i].Type == SearchOperationType.InlinedIndependentCheckForDuplicateMatch)
                {
                    continue;
                }

                SearchPlanNode spn_i = (SearchPlanNode)ssp.Operations[i].Element;

                if (spn_i.NodeType != spn_j.NodeType)
                {
                    // don't compare nodes with edges
                    continue;
                }

                if (spn_i.ElementID == -1)
                {
                    // inlined from independent for better matching, independent from the rest
                    continue;
                }

                // in global isomorphy check at current position
                // allow globally homomorphic elements as exception
                // if they were already defined(preset)
                if (homGlobal[spn_j.ElementID - 1, spn_i.ElementID - 1])
                {
                    if (ssp.Operations[j].Isomorphy.GloballyHomomorphPatternElements == null)
                    {
                        ssp.Operations[j].Isomorphy.GloballyHomomorphPatternElements = new List <SearchPlanNode>();
                    }
                    ssp.Operations[j].Isomorphy.GloballyHomomorphPatternElements.Add(spn_i);
                }
            }
        }