/// <summary> /// Decides which check connectedness operations are needed for the given edge in both directions /// and inserts them into the search program /// returns new insertion point and continuation point /// for continuing buildup after the stuff nested within both directions iteration was built /// todo: if no direction iteration was needed, insertion point == continuation point ? /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfEdgeBothDirections( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, bool edgeDeterminationContainsFirstNodeLoop, out SearchProgramOperation continuationPoint) { continuationPoint = null; // check whether source/target-nodes of the candidate edge // are the same as the already found nodes to which the edge must be incident if (!edgeDeterminationContainsFirstNodeLoop && currentEdgeConnectsToFirstIncidentNode(edge)) { // due to currentEdgeConnectsToFirstIncidentNode: at least on incident node available if (edge.PatternEdgeSource == edge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches SearchPlanNodeNode nodeRequiringFirstNodeLoop = edge.PatternEdgeSource != null ? edge.PatternEdgeSource : edge.PatternEdgeTarget; CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( edge.PatternElement.Name, nodeRequiringFirstNodeLoop.PatternElement.Name, edge.PatternElement.Name, CheckCandidateForConnectednessType.Source); // might be Target as well insertionPoint = insertionPoint.Append(checkConnectedness); } else { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(edge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); continuationPoint = insertionPoint.Append(directionsIteration); insertionPoint = directionsIteration.NestedOperationsList; SearchPlanNodeNode nodeRequiringFirstNodeLoop = edge.PatternEdgeSource != null ? edge.PatternEdgeSource : edge.PatternEdgeTarget; CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( edge.PatternElement.Name, nodeRequiringFirstNodeLoop.PatternElement.Name, edge.PatternElement.Name, CheckCandidateForConnectednessType.SourceOrTarget); insertionPoint = insertionPoint.Append(checkConnectedness); } } if (currentEdgeConnectsToSecondIncidentNode(edge)) { // due to currentEdgeConnectsToSecondIncidentNode: both incident node available CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( edge.PatternElement.Name, edge.PatternEdgeTarget.PatternElement.Name, edge.PatternElement.Name, edge.PatternEdgeSource.PatternElement.Name, CheckCandidateForConnectednessType.TheOther); insertionPoint = insertionPoint.Append(checkConnectedness); } return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given node and edge in both directions /// and inserts them into the search program /// returns new insertion point and continuation point /// for continuing buildup after the stuff nested within both directions iteration was built /// if no direction iteration was needed, insertion point == continuation point /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfNodeBothDirections( SearchProgramOperation insertionPoint, SearchPlanNodeNode currentNode, SearchPlanEdgeNode edge, out SearchProgramOperation continuationPoint) { Debug.Assert(edge.PatternEdgeSource != edge.PatternEdgeTarget); continuationPoint = null; // check whether the pattern edges which must be incident to the candidate node (according to the pattern) // are really incident to it if (currentNodeIsFirstIncidentNodeOfEdge(currentNode, edge)) { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(edge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); continuationPoint = insertionPoint.Append(directionsIteration); CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( currentNode.PatternElement.Name, currentNode.PatternElement.Name, edge.PatternElement.Name, CheckCandidateForConnectednessType.SourceOrTarget); insertionPoint = directionsIteration.NestedOperationsList.Append(checkConnectedness); } if (currentNodeIsSecondIncidentNodeOfEdge(currentNode, edge)) { CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( currentNode.PatternElement.Name, currentNode.PatternElement.Name, edge.PatternElement.Name, edge.PatternEdgeSource == currentNode ? edge.PatternEdgeTarget.PatternElement.Name : edge.PatternEdgeSource.PatternElement.Name, CheckCandidateForConnectednessType.TheOther); insertionPoint = insertionPoint.Append(checkConnectedness); } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }
/// <summary> /// Search program operations implementing the /// setup parallelized Extend Incoming|Outgoing|IncomingOrOutgoing search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildParallelIncidentSetup( SearchProgramOperation insertionPoint, SearchPlanNodeNode source, SearchPlanEdgeNode target, IncidentEdgeType edgeType) { // iterate available incident edges SearchPlanNodeNode node = source; SearchPlanEdgeNode currentEdge = target; IncidentEdgeType incidentType = edgeType; GetCandidateByIterationParallelSetup incidentIteration; PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); if(incidentType == IncidentEdgeType.Incoming || incidentType == IncidentEdgeType.Outgoing) { incidentIteration = new GetCandidateByIterationParallelSetup( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, incidentType, rulePatternClassName, patternGraph.name, parameterNames, false, wasIndependentInlined(patternGraph, indexOfSchedule), emitProfiling, packagePrefixedActionName, !firstLoopPassed); return insertionPoint.Append(incidentIteration); } else // IncidentEdgeType.IncomingOrOutgoing { if(currentEdge.PatternEdgeSource == currentEdge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches incidentIteration = new GetCandidateByIterationParallelSetup( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.Incoming, rulePatternClassName, patternGraph.name, parameterNames, false, wasIndependentInlined(patternGraph, indexOfSchedule), emitProfiling, packagePrefixedActionName, !firstLoopPassed); return insertionPoint.Append(incidentIteration); } else { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(currentEdge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); SearchProgramOperation continuationPoint = insertionPoint.Append(directionsIteration); insertionPoint = directionsIteration.NestedOperationsList; incidentIteration = new GetCandidateByIterationParallelSetup( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.IncomingOrOutgoing, rulePatternClassName, patternGraph.name, parameterNames, true, wasIndependentInlined(patternGraph, indexOfSchedule), emitProfiling, packagePrefixedActionName, !firstLoopPassed); return insertionPoint.Append(incidentIteration); } } }
/// <summary> /// Inserts code to get an implicit node from an edge /// </summary> private SearchProgramOperation insertImplicitNodeFromEdge( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, SearchPlanNodeNode currentNode, ImplicitNodeType nodeType, out SearchProgramOperation continuationPoint) { continuationPoint = null; GetCandidateByDrawing nodeFromEdge; if (nodeType == ImplicitNodeType.Source || nodeType == ImplicitNodeType.Target) { nodeFromEdge = new GetCandidateByDrawing( GetCandidateByDrawingType.NodeFromEdge, currentNode.PatternElement.Name, TypesHelper.XgrsTypeToCSharpTypeNodeEdge(model.NodeModel.Types[currentNode.PatternElement.TypeID].PackagePrefixedName), edge.PatternElement.Name, nodeType); insertionPoint = insertionPoint.Append(nodeFromEdge); } else { Debug.Assert(nodeType != ImplicitNodeType.TheOther); if (currentNodeIsSecondIncidentNodeOfEdge(currentNode, edge)) { nodeFromEdge = new GetCandidateByDrawing( GetCandidateByDrawingType.NodeFromEdge, currentNode.PatternElement.Name, TypesHelper.XgrsTypeToCSharpTypeNodeEdge(model.NodeModel.Types[currentNode.PatternElement.TypeID].PackagePrefixedName), edge.PatternElement.Name, edge.PatternEdgeSource == currentNode ? edge.PatternEdgeTarget.PatternElement.Name : edge.PatternEdgeSource.PatternElement.Name, ImplicitNodeType.TheOther); insertionPoint = insertionPoint.Append(nodeFromEdge); } else // edge connects to first incident node { if (edge.PatternEdgeSource == edge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches nodeFromEdge = new GetCandidateByDrawing( GetCandidateByDrawingType.NodeFromEdge, currentNode.PatternElement.Name, TypesHelper.XgrsTypeToCSharpTypeNodeEdge(model.NodeModel.Types[currentNode.PatternElement.TypeID].PackagePrefixedName), edge.PatternElement.Name, ImplicitNodeType.Source); insertionPoint = insertionPoint.Append(nodeFromEdge); } else { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(edge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); continuationPoint = insertionPoint.Append(directionsIteration); insertionPoint = directionsIteration.NestedOperationsList; nodeFromEdge = new GetCandidateByDrawing( GetCandidateByDrawingType.NodeFromEdge, currentNode.PatternElement.Name, TypesHelper.XgrsTypeToCSharpTypeNodeEdge(model.NodeModel.Types[currentNode.PatternElement.TypeID].PackagePrefixedName), edge.PatternElement.Name, ImplicitNodeType.SourceOrTarget); insertionPoint = insertionPoint.Append(nodeFromEdge); } } } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }
/// <summary> /// Search program operations implementing the /// Extend Incoming|Outgoing|IncomingOrOutgoing search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildIncident( SearchProgramOperation insertionPoint, int currentOperationIndex, SearchPlanNodeNode source, SearchPlanEdgeNode target, IsomorphyInformation isomorphy, IncidentEdgeType edgeType) { #if RANDOM_LOOKUP_LIST_START // insert list heads randomization, thus randomized extend RandomizeListHeads randomizeListHeads = new RandomizeListHeads( RandomizeListHeadsTypes.IncidentEdges, target.PatternElement.Name, source.PatternElement.Name, getIncoming); insertionPoint = insertionPoint.Append(randomizeListHeads); #endif // iterate available incident edges SearchPlanNodeNode node = source; SearchPlanEdgeNode currentEdge = target; IncidentEdgeType incidentType = edgeType; GetCandidateByIteration incidentIteration; SearchProgramOperation continuationPoint; if(incidentType == IncidentEdgeType.Incoming || incidentType == IncidentEdgeType.Outgoing) { incidentIteration = new GetCandidateByIteration( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, incidentType, parallelized, emitProfiling, packagePrefixedActionName, !firstLoopPassed); firstLoopPassed = true; incidentIteration.NestedOperationsList = new SearchProgramList(incidentIteration); continuationPoint = insertionPoint.Append(incidentIteration); insertionPoint = incidentIteration.NestedOperationsList; } else // IncidentEdgeType.IncomingOrOutgoing { if(currentEdge.PatternEdgeSource == currentEdge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches incidentIteration = new GetCandidateByIteration( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.Incoming, parallelized, emitProfiling, packagePrefixedActionName, !firstLoopPassed); firstLoopPassed = true; incidentIteration.NestedOperationsList = new SearchProgramList(incidentIteration); continuationPoint = insertionPoint.Append(incidentIteration); insertionPoint = incidentIteration.NestedOperationsList; } else { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(currentEdge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); continuationPoint = insertionPoint.Append(directionsIteration); insertionPoint = directionsIteration.NestedOperationsList; incidentIteration = new GetCandidateByIteration( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.IncomingOrOutgoing, parallelized, emitProfiling, packagePrefixedActionName, !firstLoopPassed); firstLoopPassed = true; incidentIteration.NestedOperationsList = new SearchProgramList(incidentIteration); insertionPoint = insertionPoint.Append(incidentIteration); insertionPoint = incidentIteration.NestedOperationsList; } } // check type of candidate insertionPoint = decideOnAndInsertCheckType(insertionPoint, target); // check connectedness of candidate SearchProgramOperation continuationPointOfConnectednessCheck; insertionPoint = decideOnAndInsertCheckConnectednessOfIncidentEdgeFromNode( insertionPoint, target, source, edgeType==IncidentEdgeType.Incoming, out continuationPointOfConnectednessCheck); // check candidate for isomorphy string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraphWithNestingPatterns.Peek()); if (isomorphy.CheckIsMatchedBit) { CheckCandidateForIsomorphy checkIsomorphy = new CheckCandidateForIsomorphy( target.PatternElement.Name, isomorphy.PatternElementsToCheckAgainstAsListOfStrings(), negativeIndependentNamePrefix, false, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(checkIsomorphy); } // check candidate for global isomorphy if (programType == SearchProgramType.Subpattern || programType == SearchProgramType.AlternativeCase || programType == SearchProgramType.Iterated) { if(!isomorphy.TotallyHomomorph) { CheckCandidateForIsomorphyGlobal checkIsomorphy = new CheckCandidateForIsomorphyGlobal( target.PatternElement.Name, isomorphy.GloballyHomomorphPatternElementsAsListOfStrings(), false, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel); insertionPoint = insertionPoint.Append(checkIsomorphy); } } // check candidate for pattern path isomorphy if(patternGraphWithNestingPatterns.Peek().isPatternGraphOnPathFromEnclosingPatternpath) { CheckCandidateForIsomorphyPatternPath checkIsomorphy = new CheckCandidateForIsomorphyPatternPath( target.PatternElement.Name, false, patternGraphWithNestingPatterns.Peek().isPatternpathLocked, getCurrentLastMatchAtPreviousNestingLevel()); insertionPoint = insertionPoint.Append(checkIsomorphy); } // accept candidate (write isomorphy information) if (isomorphy.SetIsMatchedBit) { AcceptCandidate acceptCandidate = new AcceptCandidate( target.PatternElement.Name, negativeIndependentNamePrefix, false, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(acceptCandidate); } // mark element as visited target.Visited = true; //--------------------------------------------------------------------------- // build next operation insertionPoint = BuildScheduledSearchPlanOperationIntoSearchProgram( currentOperationIndex + 1, insertionPoint); //--------------------------------------------------------------------------- // unmark element for possibly following run target.Visited = false; // abandon candidate (restore isomorphy information) if (isomorphy.SetIsMatchedBit) { // only if isomorphy information was previously written AbandonCandidate abandonCandidate = new AbandonCandidate( target.PatternElement.Name, negativeIndependentNamePrefix, false, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(abandonCandidate); } // everything nested within incident iteration built by now - // continue at the end of the list handed in insertionPoint = continuationPoint; return insertionPoint; }