/// <summary> /// Generates an LGSPAction object for the given scheduled search plan. /// </summary> /// <param name="action">Needed for the rule pattern and the name</param> /// <param name="sourceOutputFilename">null if no output file needed</param> public LGSPAction GenerateAction(ScheduledSearchPlan scheduledSearchPlan, LGSPAction action, String modelAssemblyLocation, String actionAssemblyLocation, String sourceOutputFilename) { SourceBuilder sourceCode = new SourceBuilder(CommentSourceCode); GenerateFileHeaderForActionsFile(sourceCode, model.GetType().Namespace, action.rulePattern.GetType().Namespace); // can't generate new subpattern matchers due to missing scheduled search plans for them / missing graph analyze data Debug.Assert(action.rulePattern.patternGraph.embeddedGraphsPlusInlined.Length == 0); GenerateActionAndMatcher(sourceCode, action.rulePattern, false); // close namespace sourceCode.Append("}"); // write generated source to file if requested if(sourceOutputFilename != null) { StreamWriter writer = new StreamWriter(sourceOutputFilename); writer.Write(sourceCode.ToString()); writer.Close(); } // set up compiler CSharpCodeProvider compiler = new CSharpCodeProvider(); CompilerParameters compParams = GetDynCompilerSetup(modelAssemblyLocation, actionAssemblyLocation); // Stopwatch compilerWatch = Stopwatch.StartNew(); // compile generated code CompilerResults compResults = compiler.CompileAssemblyFromSource(compParams, sourceCode.ToString()); if(compResults.Errors.HasErrors) { String errorMsg = compResults.Errors.Count + " Errors:"; foreach(CompilerError error in compResults.Errors) errorMsg += Environment.NewLine + "Line: " + error.Line + " - " + error.ErrorText; throw new ArgumentException("Illegal dynamic C# source code produced for actions \"" + action.Name + "\": " + errorMsg); } // create action instance Object obj = compResults.CompiledAssembly.CreateInstance("de.unika.ipd.grGen.lgspActions.DynAction_" + action.Name); // long compSourceTicks = compilerWatch.ElapsedTicks; // Console.WriteLine("GenMatcher: Compile source: {0} us", compSourceTicks / (Stopwatch.Frequency / 1000000)); return (LGSPAction) obj; }
/// <summary> /// Generates scheduled search plans needed for matcher code generation for action compilation /// out of graph with analyze information, /// The scheduled search plans are added to the main and the nested pattern graphs. /// </summary> public void GenerateScheduledSearchPlans(PatternGraph patternGraph, LGSPGraph graph, bool isSubpatternLike, bool isNegativeOrIndependent, ScheduledSearchPlan nestingScheduledSearchPlan) { for(int i=0; i<patternGraph.schedules.Length; ++i) { patternGraph.AdaptToMaybeNull(i); if(Profile) SetNeedForProfiling(patternGraph); PlanGraph planGraph = GeneratePlanGraph(graph.statistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, ExtractOwnElements(nestingScheduledSearchPlan, patternGraph)); MarkMinimumSpanningArborescence(planGraph, patternGraph.name); SearchPlanGraph searchPlanGraph = GenerateSearchPlanGraph(planGraph); ScheduledSearchPlan scheduledSearchPlan = ScheduleSearchPlan( searchPlanGraph, patternGraph, isNegativeOrIndependent); AppendHomomorphyInformation(scheduledSearchPlan); patternGraph.schedules[i] = scheduledSearchPlan; patternGraph.RevertMaybeNullAdaption(i); foreach(PatternGraph neg in patternGraph.negativePatternGraphsPlusInlined) { GenerateScheduledSearchPlans(neg, graph, isSubpatternLike, true, null); } foreach(PatternGraph idpt in patternGraph.independentPatternGraphsPlusInlined) { GenerateScheduledSearchPlans(idpt, graph, isSubpatternLike, true, patternGraph.schedules[i]); } foreach(Alternative alt in patternGraph.alternativesPlusInlined) { foreach (PatternGraph altCase in alt.alternativeCases) { GenerateScheduledSearchPlans(altCase, graph, true, false, null); } } foreach(Iterated iter in patternGraph.iteratedsPlusInlined) { GenerateScheduledSearchPlans(iter.iteratedPattern, graph, true, false, null); } } }
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; }
/// <summary> /// Non- is-matched-flag-based isomorphy checking for nested alternative cases/iterateds /// </summary> public 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); } }
/// <summary> /// Non- is-matched-flag-based isomorphy checking for nested negatives/independents, /// patch into already cloned parallel ssp /// </summary> public 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); } } }
/// <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 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)so.Clone(); headOperations.Add(cloneHead); SearchOperation cloneBody = (SearchOperation)so.Clone(); cloneBody.Isomorphy.Parallel = true; bodyOperations.Add(cloneBody); switch(so.Type) { case SearchOperationType.Lookup: cloneHead.Type = SearchOperationType.SetupParallelLookup; cloneBody.Type = SearchOperationType.ParallelLookup; break; case SearchOperationType.Incident: cloneHead.Type = SearchOperationType.SetupParallelIncident; cloneBody.Type = SearchOperationType.ParallelIncident; break; case SearchOperationType.Incoming: cloneHead.Type = SearchOperationType.SetupParallelIncoming; cloneBody.Type = SearchOperationType.ParallelIncoming; break; case SearchOperationType.Outgoing: cloneHead.Type = SearchOperationType.SetupParallelOutgoing; cloneBody.Type = SearchOperationType.ParallelOutgoing; break; case SearchOperationType.PickFromStorage: cloneHead.Type = SearchOperationType.SetupParallelPickFromStorage; cloneBody.Type = SearchOperationType.ParallelPickFromStorage; break; case SearchOperationType.PickFromStorageDependent: cloneHead.Type = SearchOperationType.SetupParallelPickFromStorageDependent; cloneBody.Type = SearchOperationType.ParallelPickFromStorageDependent; break; case SearchOperationType.PickFromIndex: cloneHead.Type = SearchOperationType.SetupParallelPickFromIndex; cloneBody.Type = SearchOperationType.ParallelPickFromIndex; break; case SearchOperationType.PickFromIndexDependent: cloneHead.Type = SearchOperationType.SetupParallelPickFromIndexDependent; cloneBody.Type = SearchOperationType.ParallelPickFromIndexDependent; break; } } 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); }
/// <summary> /// Parallelize the scheduled search plan for usage from a parallelized matcher /// (non- is-matched-flag-based isomorphy checking) /// </summary> public 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); }
/// <summary> /// fill in globally homomorphic elements as exception to global isomorphy check /// </summary> public 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; // don't compare nodes with edges if(spn_i.NodeType != spn_j.NodeType) { 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); } } }
/// <summary> /// Determines which homomorphy check operations are necessary /// at the operation of the given position within the scheduled search plan /// and appends them. /// </summary> public void DetermineAndAppendHomomorphyChecks(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 GrGenType[] 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; // don't compare nodes with edges if(spn_i.NodeType != spn_j.NodeType) { continue; } if(spn_i.ElementID == -1) { // inlined from independent for better matching, independent from the rest continue; } // find out whether element types are disjoint GrGenType type_i = types[spn_i.PatternElement.TypeID]; GrGenType type_j = types[spn_j.PatternElement.TypeID]; bool disjoint = true; foreach(GrGenType subtype_i in type_i.SubOrSameTypes) { if(type_j.IsA(subtype_i) || subtype_i.IsA(type_j)) // IsA==IsSuperTypeOrSameType { disjoint = false; break; } } // don't check elements if their types are disjoint if(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; } }
/// <summary> /// Appends homomorphy information to each operation of the scheduled search plan /// </summary> public void AppendHomomorphyInformation(ScheduledSearchPlan ssp) { // no operation -> nothing which could be homomorph if(ssp.Operations.Length == 0) { return; } // iterate operations of the search plan to append homomorphy checks for(int i = 0; i < ssp.Operations.Length; ++i) { if(ssp.Operations[i].Type == SearchOperationType.Condition || ssp.Operations[i].Type == SearchOperationType.AssignVar || ssp.Operations[i].Type == SearchOperationType.DefToBeYieldedTo || ssp.Operations[i].Type == SearchOperationType.InlinedIndependentCheckForDuplicateMatch) { continue; } if(ssp.Operations[i].Type == SearchOperationType.NegativePattern) { AppendHomomorphyInformation((ScheduledSearchPlan)ssp.Operations[i].Element); continue; } if(ssp.Operations[i].Type == SearchOperationType.IndependentPattern) { AppendHomomorphyInformation((ScheduledSearchPlan)ssp.Operations[i].Element); continue; } DetermineAndAppendHomomorphyChecks(ssp, i); } }
private void DumpScheduledSearchPlan(ScheduledSearchPlan ssp, String dumpname) { StreamWriter sw = new StreamWriter(dumpname + "-scheduledsp.txt", false); SourceBuilder sb = new SourceBuilder(); ssp.Explain(sb, model); sb.Append("\n"); sw.WriteLine(sb.ToString()); sw.Close(); /* 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.NegPreset: 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; } }*/ }
/// <summary> /// Creates an interpretation plan builder for the given scheduled search plan. /// Only a limited amount of search operations is supported, the ones needed for isomorphy checking. /// </summary> /// <param name="ssp">the scheduled search plan to build an interpretation plan for</param> /// <param name="spg">the search plan graph for determining the pattern element needed for attribute checking</param> /// <param name="model">the model over which the patterns are to be searched</param> public InterpretationPlanBuilder(ScheduledSearchPlan ssp, SearchPlanGraph spg, IGraphModel model) { this.ssp = ssp; this.spg = spg; this.model = model; }