/////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Inserts code to get an implicit node from an edge /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan insertImplicitNodeFromEdge( InterpretationPlan insertionPoint, SearchPlanEdgeNode edge, SearchPlanNodeNode currentNode, ImplicitNodeType nodeType) { int targetType = currentNode.PatternElement.TypeID; if (nodeType == ImplicitNodeType.Source) { currentNode.nodeMatcher = new InterpretationPlanImplicitSource(targetType, edge.edgeMatcher, currentNode); } else if(nodeType == ImplicitNodeType.Target) { currentNode.nodeMatcher = new InterpretationPlanImplicitTarget(targetType, edge.edgeMatcher, currentNode); } else { Debug.Assert(nodeType != ImplicitNodeType.TheOther); if (currentNodeIsSecondIncidentNodeOfEdge(currentNode, edge)) { currentNode.nodeMatcher = new InterpretationPlanImplicitTheOther(targetType, edge.edgeMatcher, edge.PatternEdgeSource == currentNode ? edge.PatternEdgeTarget.nodeMatcher : edge.PatternEdgeSource.nodeMatcher, currentNode); } else // edge connects to first incident node { if (edge.PatternEdgeSource == edge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches currentNode.nodeMatcher = new InterpretationPlanImplicitSource(targetType, edge.edgeMatcher, currentNode); } else { edge.directionVariable = new InterpretationPlanBothDirections(); insertionPoint.next = edge.directionVariable; insertionPoint = insertionPoint.next; currentNode.nodeMatcher = new InterpretationPlanImplicitSourceOrTarget(targetType, edge.edgeMatcher, edge.directionVariable, currentNode); } } } currentNode.nodeMatcher.prev = insertionPoint; insertionPoint.next = currentNode.nodeMatcher; insertionPoint = insertionPoint.next; return insertionPoint; }
/// <summary> /// returns true if both incident nodes of the edge which gets currently determined in the schedule /// were already computed; only of interest for edges of unfixed direction /// </summary> private bool currentEdgeConnectsToSecondIncidentNode(SearchPlanEdgeNode currentEdge) { //Debug.Assert(!currentEdge.Visited); Debug.Assert(!((PatternEdge)currentEdge.PatternElement).fixedDirection); if (currentEdge.PatternEdgeSource == null || currentEdge.PatternEdgeTarget == null) return false; if (currentEdge.PatternEdgeSource.Visited && currentEdge.PatternEdgeTarget.Visited) return true; return false; }
public InterpretationPlanOutgoing(int targetType, InterpretationPlanNodeMatcher source, SearchPlanEdgeNode planEdgeNode) { this.targetType = targetType; this.source = source; this.planEdgeNode = planEdgeNode; AssignId(); }
/// <summary> /// Decides which check connectedness operations are needed for the given edge of fixed direction /// and inserts them into the interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( InterpretationPlan insertionPoint, SearchPlanEdgeNode edge, CheckCandidateForConnectednessType connectednessType) { Debug.Assert(connectednessType == CheckCandidateForConnectednessType.Source || connectednessType == CheckCandidateForConnectednessType.Target); // check whether source/target-nodes of the candidate edge // are the same as the already found nodes to which the edge must be incident // don't need to, if that node is not matched by now (signaled by visited) SearchPlanNodeNode nodeRequiringCheck = connectednessType == CheckCandidateForConnectednessType.Source ? edge.PatternEdgeSource : edge.PatternEdgeTarget; if (nodeRequiringCheck.Visited) { if(connectednessType == CheckCandidateForConnectednessType.Source) { insertionPoint.next = new InterpretationPlanCheckConnectednessSource( nodeRequiringCheck.nodeMatcher, edge.edgeMatcher); insertionPoint = insertionPoint.next; } else //if(connectednessType == CheckCandidateForConnectednessType.Target) { insertionPoint.next = new InterpretationPlanCheckConnectednessTarget( nodeRequiringCheck.nodeMatcher, edge.edgeMatcher); insertionPoint = insertionPoint.next; } } return insertionPoint; }
/// <summary> /// returns true if the node which gets currently determined in the schedule /// is the second incident node of the edge which gets connected to it /// only of interest for edges of unfixed direction /// </summary> private bool currentNodeIsSecondIncidentNodeOfEdge( SearchPlanNodeNode currentNode, SearchPlanEdgeNode edge) { //Debug.Assert(!currentNode.Visited); Debug.Assert(!((PatternEdge)edge.PatternElement).fixedDirection); if (!edge.Visited) return false; if (edge.PatternEdgeSource == null || edge.PatternEdgeTarget == null) return false; if (currentNode == edge.PatternEdgeSource) return edge.PatternEdgeTarget.Visited; else return edge.PatternEdgeSource.Visited; }
/// <summary> /// Decides which check connectedness operations are needed for the given node and edge of fixed direction /// and inserts them into the interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfNodeFixedDirection( InterpretationPlan insertionPoint, SearchPlanNodeNode currentNode, SearchPlanEdgeNode edge, CheckCandidateForConnectednessType connectednessType) { Debug.Assert(connectednessType == CheckCandidateForConnectednessType.Source || connectednessType == CheckCandidateForConnectednessType.Target); // check whether the pattern edges which must be incident to the candidate node (according to the pattern) // are really incident to it // only if edge is already matched by now (signaled by visited) if (edge.Visited) { if(connectednessType == CheckCandidateForConnectednessType.Source) { insertionPoint.next = new InterpretationPlanCheckConnectednessSource( currentNode.nodeMatcher, edge.edgeMatcher); insertionPoint = insertionPoint.next; } else //if(connectednessType == CheckCandidateForConnectednessType.Target) { insertionPoint.next = new InterpretationPlanCheckConnectednessTarget( currentNode.nodeMatcher, edge.edgeMatcher); insertionPoint = insertionPoint.next; } } return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given edge determined by lookup /// and inserts them into the interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfEdgeFromLookup( InterpretationPlan insertionPoint, SearchPlanEdgeNode edge) { if (((PatternEdge)edge.PatternElement).fixedDirection) { // don't need to check if the edge is not required by the pattern to be incident to some given node if (edge.PatternEdgeSource != null) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection(insertionPoint, edge, CheckCandidateForConnectednessType.Source); } if (edge.PatternEdgeTarget != null) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection(insertionPoint, edge, CheckCandidateForConnectednessType.Target); } } else { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeBothDirections(insertionPoint, edge, false); } return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given node and edge of fixed direction /// and inserts them into the search program /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfNodeFixedDirection( SearchProgramOperation insertionPoint, SearchPlanNodeNode currentNode, SearchPlanEdgeNode edge, CheckCandidateForConnectednessType connectednessType) { Debug.Assert(connectednessType == CheckCandidateForConnectednessType.Source || connectednessType == CheckCandidateForConnectednessType.Target); // check whether the pattern edges which must be incident to the candidate node (according to the pattern) // are really incident to it // only if edge is already matched by now (signaled by visited) if (edge.Visited) { CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( currentNode.PatternElement.Name, currentNode.PatternElement.Name, edge.PatternElement.Name, connectednessType); 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 /// parallelized Extend Incoming|Outgoing|IncomingOrOutgoing search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildParallelIncident( 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; SearchProgramOperation continuationPoint; GetCandidateByIterationParallel incidentIteration; if(incidentType == IncidentEdgeType.Incoming || incidentType == IncidentEdgeType.Outgoing) { incidentIteration = new GetCandidateByIterationParallel( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, incidentType, 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 GetCandidateByIterationParallel( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.Incoming, emitProfiling, packagePrefixedActionName, !firstLoopPassed); firstLoopPassed = true; incidentIteration.NestedOperationsList = new SearchProgramList(incidentIteration); continuationPoint = insertionPoint.Append(incidentIteration); insertionPoint = incidentIteration.NestedOperationsList; } else { incidentIteration = new GetCandidateByIterationParallel( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.IncomingOrOutgoing, emitProfiling, packagePrefixedActionName, !firstLoopPassed); firstLoopPassed = true; incidentIteration.NestedOperationsList = new SearchProgramList(incidentIteration); continuationPoint = 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 = ""; if(isomorphy.CheckIsMatchedBit) { CheckCandidateForIsomorphy checkIsomorphy = new CheckCandidateForIsomorphy( target.PatternElement.Name, isomorphy.PatternElementsToCheckAgainstAsListOfStrings(), negativeIndependentNamePrefix, false, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); 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 after incident edges iteration insertionPoint = continuationPoint; return insertionPoint; }
/// <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 /// 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> /// Search program operations implementing the /// Implicit Source|Target|SourceOrTarget search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildImplicit( SearchProgramOperation insertionPoint, int currentOperationIndex, SearchPlanEdgeNode source, SearchPlanNodeNode target, IsomorphyInformation isomorphy, ImplicitNodeType nodeType) { // get candidate = demanded node from edge SearchProgramOperation continuationPoint; insertionPoint = insertImplicitNodeFromEdge(insertionPoint, source, target, nodeType, out continuationPoint); if (continuationPoint == insertionPoint) continuationPoint = null; // check type of candidate insertionPoint = decideOnAndInsertCheckType(insertionPoint, target); // check connectedness of candidate SearchProgramOperation continuationPointAfterConnectednessCheck; SearchPlanNodeNode otherNodeOfOriginatingEdge = null; if (nodeType == ImplicitNodeType.Source) otherNodeOfOriginatingEdge = source.PatternEdgeTarget; if (nodeType == ImplicitNodeType.Target) otherNodeOfOriginatingEdge = source.PatternEdgeSource; if (source.PatternEdgeTarget == source.PatternEdgeSource) // reflexive sign needed in unfixed direction case, too otherNodeOfOriginatingEdge = source.PatternEdgeSource; insertionPoint = decideOnAndInsertCheckConnectednessOfImplicitNodeFromEdge( insertionPoint, target, source, otherNodeOfOriginatingEdge, out continuationPointAfterConnectednessCheck); if (continuationPoint == null && continuationPointAfterConnectednessCheck != insertionPoint) continuationPoint = continuationPointAfterConnectednessCheck; // check candidate for isomorphy string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraphWithNestingPatterns.Peek()); if (isomorphy.CheckIsMatchedBit) { CheckCandidateForIsomorphy checkIsomorphy = new CheckCandidateForIsomorphy( target.PatternElement.Name, isomorphy.PatternElementsToCheckAgainstAsListOfStrings(), negativeIndependentNamePrefix, true, 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(), true, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel); insertionPoint = insertionPoint.Append(checkIsomorphy); } } // check candidate for pattern path isomorphy if(patternGraphWithNestingPatterns.Peek().isPatternGraphOnPathFromEnclosingPatternpath) { CheckCandidateForIsomorphyPatternPath checkIsomorphy = new CheckCandidateForIsomorphyPatternPath( target.PatternElement.Name, true, patternGraphWithNestingPatterns.Peek().isPatternpathLocked, getCurrentLastMatchAtPreviousNestingLevel()); insertionPoint = insertionPoint.Append(checkIsomorphy); } // accept candidate (write isomorphy information) if (isomorphy.SetIsMatchedBit) { AcceptCandidate acceptCandidate = new AcceptCandidate( target.PatternElement.Name, negativeIndependentNamePrefix, true, 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, true, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(abandonCandidate); } if (continuationPoint != null) insertionPoint = continuationPoint; return insertionPoint; }
public InterpretationPlanIncomingOrOutgoing(int targetType, InterpretationPlanNodeMatcher source, InterpretationPlanDirectionVariable directionVariable, SearchPlanEdgeNode planEdgeNode) { this.targetType = targetType; this.source = source; this.directionVariable = directionVariable; this.planEdgeNode = planEdgeNode; AssignId(); }
/// <summary> /// Inserts code to get an incident edge from some node /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan insertIncidentEdgeFromNode( InterpretationPlan insertionPoint, SearchPlanNodeNode node, SearchPlanEdgeNode currentEdge, IncidentEdgeType incidentType) { int targetType = currentEdge.PatternElement.TypeID; if (incidentType == IncidentEdgeType.Incoming) { currentEdge.edgeMatcher = new InterpretationPlanIncoming(targetType, node.nodeMatcher, currentEdge); } else if(incidentType == IncidentEdgeType.Outgoing) { currentEdge.edgeMatcher = new InterpretationPlanOutgoing(targetType, node.nodeMatcher, currentEdge); } else // IncidentEdgeType.IncomingOrOutgoing { if (currentEdge.PatternEdgeSource == currentEdge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches currentEdge.edgeMatcher = new InterpretationPlanIncoming(targetType, node.nodeMatcher, currentEdge); } else { currentEdge.directionVariable = new InterpretationPlanBothDirections(); insertionPoint.next = currentEdge.directionVariable; insertionPoint = insertionPoint.next; currentEdge.edgeMatcher = new InterpretationPlanIncomingOrOutgoing(targetType, node.nodeMatcher, currentEdge.directionVariable, currentEdge); } } currentEdge.edgeMatcher.prev = insertionPoint; insertionPoint.next = currentEdge.edgeMatcher; insertionPoint = insertionPoint.next; return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given edge determined by lookup /// 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 decideOnAndInsertCheckConnectednessOfEdgeFromLookupOrPickOrMap( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, out SearchProgramOperation continuationPoint) { continuationPoint = null; if (((PatternEdge)edge.PatternElement).fixedDirection) { // don't need to check if the edge is not required by the pattern to be incident to some given node if (edge.PatternEdgeSource != null) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( insertionPoint, edge, CheckCandidateForConnectednessType.Source); } if (edge.PatternEdgeTarget != null) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( insertionPoint, edge, CheckCandidateForConnectednessType.Target); } } else { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeBothDirections( insertionPoint, edge, false, out continuationPoint); } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given node just drawn from edge /// and inserts them into the interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfImplicitNodeFromEdge( InterpretationPlan insertionPoint, SearchPlanNodeNode node, SearchPlanEdgeNode originatingEdge, SearchPlanNodeNode otherNodeOfOriginatingEdge) { // check for edges required by the pattern to be incident to the given node // only if the node was not taken from the given originating edge // with the exception of reflexive edges, as these won't get checked thereafter foreach (SearchPlanEdgeNode edge in node.OutgoingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection(insertionPoint, node, edge, CheckCandidateForConnectednessType.Source); } } else { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections(insertionPoint, node, edge); } } } foreach (SearchPlanEdgeNode edge in node.IncomingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection(insertionPoint, node, edge, CheckCandidateForConnectednessType.Target); } } else { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections(insertionPoint, node, edge); } } } return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given edge of fixed direction /// and inserts them into the search program /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, CheckCandidateForConnectednessType connectednessType) { // check whether source/target-nodes of the candidate edge // are the same as the already found nodes to which the edge must be incident // don't need to, if that node is not matched by now (signaled by visited) SearchPlanNodeNode nodeRequiringCheck = connectednessType == CheckCandidateForConnectednessType.Source ? edge.PatternEdgeSource : edge.PatternEdgeTarget; if (nodeRequiringCheck.Visited) { CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( edge.PatternElement.Name, nodeRequiringCheck.PatternElement.Name, edge.PatternElement.Name, connectednessType); 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 interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfNodeBothDirections( InterpretationPlan insertionPoint, SearchPlanNodeNode currentNode, SearchPlanEdgeNode edge) { Debug.Assert(edge.PatternEdgeSource != edge.PatternEdgeTarget); // 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)) { edge.directionVariable = new InterpretationPlanBothDirections(); insertionPoint.next = edge.directionVariable; insertionPoint = insertionPoint.next; insertionPoint.next = new InterpretationPlanCheckConnectednessSourceOrTarget( currentNode.nodeMatcher, edge.edgeMatcher, edge.directionVariable); insertionPoint = insertionPoint.next; } if (currentNodeIsSecondIncidentNodeOfEdge(currentNode, edge)) { insertionPoint.next = new InterpretationPlanCheckConnectednessTheOther( currentNode.nodeMatcher, edge.edgeMatcher, edge.PatternEdgeSource == currentNode ? edge.PatternEdgeTarget.nodeMatcher : edge.PatternEdgeSource.nodeMatcher); insertionPoint = insertionPoint.next; } return insertionPoint; }
/// <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 edge determined from incident node /// and inserts them into the interpretation plan /// receives insertion point, returns new insertions point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfIncidentEdgeFromNode( InterpretationPlan insertionPoint, SearchPlanEdgeNode edge, SearchPlanNodeNode originatingNode, bool edgeIncomingAtOriginatingNode) { if (((PatternEdge)edge.PatternElement).fixedDirection) { // don't need to check if the edge is not required by the pattern to be incident to some given node // or if the edge was taken from the given originating node if (edge.PatternEdgeSource != null) { if (!(!edgeIncomingAtOriginatingNode && edge.PatternEdgeSource == originatingNode)) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection(insertionPoint, edge, CheckCandidateForConnectednessType.Source); } } if (edge.PatternEdgeTarget != null) { if (!(edgeIncomingAtOriginatingNode && edge.PatternEdgeTarget == originatingNode)) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection(insertionPoint, edge, CheckCandidateForConnectednessType.Target); } } } else { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeBothDirections(insertionPoint, edge, true); } return insertionPoint; }
/// <summary> /// Interpretation plan operations implementing the /// Lookup edge search plan operation /// are created and inserted into the interpretation plan at the insertion point /// </summary> private void buildLookup( InterpretationPlan insertionPoint, int index, SearchPlanEdgeNode target) { // get candidate = iterate available edges target.edgeMatcher = new InterpretationPlanLookupEdge(target.PatternElement.TypeID, target); target.edgeMatcher.prev = insertionPoint; insertionPoint.next = target.edgeMatcher; insertionPoint = insertionPoint.next; // check connectedness of candidate insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFromLookup(insertionPoint, target); // continue with next operation target.Visited = true; BuildInterpretationPlan(insertionPoint, index + 1); target.Visited = false; }
/// <summary> /// Decides which check connectedness operations are needed for the given edge in both directions /// and inserts them into the interpretation plan /// receives insertion point, returns new insertion point /// </summary> private InterpretationPlan decideOnAndInsertCheckConnectednessOfEdgeBothDirections( InterpretationPlan insertionPoint, SearchPlanEdgeNode edge, bool edgeDeterminationContainsFirstNodeLoop) { // 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)) { SearchPlanNodeNode nodeRequiringFirstNodeLoop = edge.PatternEdgeSource != null ? edge.PatternEdgeSource : edge.PatternEdgeTarget; // 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 insertionPoint.next = new InterpretationPlanCheckConnectednessSource( nodeRequiringFirstNodeLoop.nodeMatcher, edge.edgeMatcher); // might be Target as well insertionPoint = insertionPoint.next; } else { edge.directionVariable = new InterpretationPlanBothDirections(); insertionPoint.next = edge.directionVariable; insertionPoint = insertionPoint.next; insertionPoint.next = new InterpretationPlanCheckConnectednessSourceOrTarget( nodeRequiringFirstNodeLoop.nodeMatcher, edge.edgeMatcher, edge.directionVariable); insertionPoint = insertionPoint.next; } } if (currentEdgeConnectsToSecondIncidentNode(edge)) { // due to currentEdgeConnectsToSecondIncidentNode: both incident node available insertionPoint.next = new InterpretationPlanCheckConnectednessTheOther( edge.PatternEdgeTarget.nodeMatcher, edge.edgeMatcher, edge.PatternEdgeSource.nodeMatcher); insertionPoint = insertionPoint.next; } return insertionPoint; }
/// <summary> /// Interpretation plan operations implementing the /// Implicit Source|Target|SourceOrTarget search plan operation /// are created and inserted into the interpretation plan at the insertion point /// </summary> private void buildImplicit( InterpretationPlan insertionPoint, int index, SearchPlanEdgeNode source, SearchPlanNodeNode target, ImplicitNodeType nodeType) { // get candidate = demanded node from edge insertionPoint = insertImplicitNodeFromEdge(insertionPoint, source, target, nodeType); // check connectedness of candidate SearchPlanNodeNode otherNodeOfOriginatingEdge = null; if (nodeType == ImplicitNodeType.Source) otherNodeOfOriginatingEdge = source.PatternEdgeTarget; if (nodeType == ImplicitNodeType.Target) otherNodeOfOriginatingEdge = source.PatternEdgeSource; if (source.PatternEdgeTarget == source.PatternEdgeSource) // reflexive sign needed in unfixed direction case, too otherNodeOfOriginatingEdge = source.PatternEdgeSource; insertionPoint = decideOnAndInsertCheckConnectednessOfImplicitNodeFromEdge(insertionPoint, target, source, otherNodeOfOriginatingEdge); // continue with next operation target.Visited = true; BuildInterpretationPlan(insertionPoint, index + 1); target.Visited = false; }
/// <summary> /// returns true if only one incident node of the edge which gets currently determined in the schedule /// was already computed; only of interest for edges of unfixed direction /// </summary> private bool currentEdgeConnectsOnlyToFirstIncidentNode(SearchPlanEdgeNode currentEdge) { //Debug.Assert(!currentEdge.Visited); Debug.Assert(!((PatternEdge)currentEdge.PatternElement).fixedDirection); if (currentEdge.PatternEdgeSource != null && currentEdge.PatternEdgeSource.Visited && (currentEdge.PatternEdgeTarget == null || !currentEdge.PatternEdgeTarget.Visited)) { return true; } if (currentEdge.PatternEdgeTarget != null && currentEdge.PatternEdgeTarget.Visited && (currentEdge.PatternEdgeSource == null || !currentEdge.PatternEdgeSource.Visited)) { return true; } return false; }
/// <summary> /// Interpretation plan operations implementing the /// Extend Incoming|Outgoing|IncomingOrOutgoing search plan operation /// are created and inserted into the interpretation plan at the insertion point /// </summary> private void buildIncident( InterpretationPlan insertionPoint, int index, SearchPlanNodeNode source, SearchPlanEdgeNode target, IncidentEdgeType edgeType) { // get candidate = iterate available incident edges insertionPoint = insertIncidentEdgeFromNode(insertionPoint, source, target, edgeType); // check connectedness of candidate insertionPoint = decideOnAndInsertCheckConnectednessOfIncidentEdgeFromNode(insertionPoint, target, source, edgeType==IncidentEdgeType.Incoming); // continue with next operation target.Visited = true; BuildInterpretationPlan(insertionPoint, index + 1); target.Visited = false; }
/// <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 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); }
public InterpretationPlanLookupEdge(int targetType, SearchPlanEdgeNode planEdgeNode) { this.targetType = targetType; this.planEdgeNode = planEdgeNode; AssignId(); }