def packet_in(self, packet): self.exception = None self.is_success = False if self.condition[HC.GUID] in packet.match_sets: matchSet = packet.match_sets[self.condition[HC.GUID]] else: matchSet = MatchSet() # Find the matches try: i = 1 if i <= self.max: for mapping in self._match(packet.graph, packet.global_pivots): # Convert the mapping to a Match object match = Match() match.from_mapping(mapping, packet.graph, self.condition) matchSet.matches.append(match) i += 1 if i > self.max: # We don't need any more matches break except Exception, e: self.is_success = False self.exception = TransformationException(e) self.exception.packet = packet self.exception.transformation_unit = self return packet
def _match(self, graph, pivots): def getSourceNodeFromLabel(label, mapping, pattern_graph): vs = pattern_graph.vs(MT_label__=label) if len(vs) == 0: #TODO: This should be a TransformationLanguageSpecificException raise Exception('Label %d does not exist in the pattern' % label) elif len(vs) > 1: #TODO: This should be a TransformationLanguageSpecificException raise Exception('Duplicate label %d in the pattern' % label) elif not vs[0].index in mapping: #TODO: This should be a TransformationLanguageSpecificException raise Exception('Node with label %d was not matched' % label) else: return graph.vs[mapping[vs[0].index]] ''' Matcher with pivots and (possibly) multiple NACs 1. Verify that no unbound NAC has a match 2. Let the "bridge" denote the biggest graph that is the intersection of the LHS and a NAC, among all NACs 3. Match the common part between the LHS & the NAC, i.e., the "bridge" 3.1 Continue the matching ensuring no occurrence of the NAC 3.2. If a NAC is found, ignore the current bridge mapping 3.3. Continue to find complete matches of the LHS, given each partial match found in 3.1. 3.4. For each valid match, verify that no occurrence of any remaining bound NAC is found, given the mapping found in 3.3. ''' bound_NACs = [ ] # Keep track of which NACs to look for after the LHS matching pred1 = { } # To optimize the matcher, since otherwise matcher will compute the predecessors of the source graph many times succ1 = { } # To optimize the matcher, since otherwise matcher will compute the successors of the source graph many times # Cache the pivot nodes of the source graph pivots = deepcopy(pivots) pivots.to_source_node_indices(graph) for NAC in self.condition.NACs: # Delay the case where the NAC has some nodes bound to the LHS if NAC.bridge.vcount() > 0: bound_NACs.append(NAC) #=================================================================== # First process the NACs that are not bound to the LHS #=================================================================== else: # Look for a NAC match nacMatcher = HimesisMatcher(source_graph=graph, pattern_graph=NAC) # Convert the pivots nac_pivots = pivots.to_mapping(graph, NAC) try: for mapping in nacMatcher.match_iter(context=nac_pivots): if NAC.constraint( lambda i: getSourceNodeFromLabel( i, mapping, self.condition), graph): # An unbound NAC has been found: this pattern can never match return except: raise finally: nacMatcher.reset_recursion_limit() # For further matching optimizations pred1 = nacMatcher.pred1 succ1 = nacMatcher.succ1 # Either there are no NACs, or there were only unbound NACs that do not match, so match the LHS now bound_NACs.sort(key=lambda nac: nac.bridge.vcount(), reverse=True) if not bound_NACs: lhsMatcher = HimesisMatcher(source_graph=graph, pattern_graph=self.condition, pred1=pred1, succ1=succ1) # Convert the pivots lhs_pivots = pivots.to_mapping(graph, self.condition) try: for mapping in lhsMatcher.match_iter(context=lhs_pivots): if self.condition.constraint( lambda i: getSourceNodeFromLabel( i, mapping, self.condition), graph): yield mapping except: raise finally: lhsMatcher.reset_recursion_limit() # The matching is complete return #=================================================================== # Now process the NACs that have some nodes bound to the LHS #=================================================================== # Continue the matching looking for the LHS now lhsMatcher = HimesisMatcher(source_graph=graph, pattern_graph=self.condition, pred1=pred1, succ1=succ1) # Augment the bridge mapping with the pivot mappings lhs_pivots = pivots.to_mapping(graph, self.condition) try: for mapping in lhsMatcher.match_iter(context=lhs_pivots): if self.condition.constraint( lambda i: getSourceNodeFromLabel( i, mapping, self.condition), graph): # A match of the LHS is found: ensure that no remaining NAC do match invalid = False for NAC in bound_NACs: # This mapping represents the mapping of the bridge of this NAC with the LHS match = Match() match.from_mapping(mapping, graph, self.condition) bridgeMapping = match.to_mapping(graph, NAC) # Now continue the matching looking for a match of the corresponding NAC nacMatcher = HimesisMatcher(source_graph=graph, pattern_graph=NAC, pred1=pred1, succ1=succ1) for nac_mapping in nacMatcher.match_iter( context=bridgeMapping): if NAC.constraint( lambda i: getSourceNodeFromLabel( i, nac_mapping, NAC), graph): # An occurrence of the NAC is found: current mapping is not valid invalid = True break if invalid: # An occurrence of the NAC was found: current mapping is not valid break else: # Either there are no bound NACs or no occurrence of any bound NAC was found: current mapping is valid yield mapping except: raise finally: lhsMatcher.reset_recursion_limit()
def _match(self, graph, pivots) : def getSourceNodeFromLabel(label, mapping, pattern_graph): vs = pattern_graph.vs(MT_label__ = label) if len(vs) == 0: #TODO: This should be a TransformationLanguageSpecificException raise Exception('Label %d does not exist in the pattern' % label) elif len(vs) > 1: #TODO: This should be a TransformationLanguageSpecificException raise Exception('Duplicate label %d in the pattern' % label) elif not vs[0].index in mapping: #TODO: This should be a TransformationLanguageSpecificException raise Exception('Node with label %d was not matched' % label) else: return graph.vs[mapping[vs[0].index]] ''' Matcher with pivots and (possibly) multiple NACs 1. Verify that no unbound NAC has a match 2. Let the "bridge" denote the biggest graph that is the intersection of the LHS and a NAC, among all NACs 3. Match the common part between the LHS & the NAC, i.e., the "bridge" 3.1 Continue the matching ensuring no occurrence of the NAC 3.2. If a NAC is found, ignore the current bridge mapping 3.3. Continue to find complete matches of the LHS, given each partial match found in 3.1. 3.4. For each valid match, verify that no occurrence of any remaining bound NAC is found, given the mapping found in 3.3. ''' bound_NACs = [] # Keep track of which NACs to look for after the LHS matching pred1 = {} # To optimize the matcher, since otherwise matcher will compute the predecessors of the source graph many times succ1 = {} # To optimize the matcher, since otherwise matcher will compute the successors of the source graph many times # Cache the pivot nodes of the source graph pivots = deepcopy(pivots) pivots.to_source_node_indices(graph) for NAC in self.condition.NACs: # Delay the case where the NAC has some nodes bound to the LHS if NAC.bridge.vcount() > 0: bound_NACs.append(NAC) #=================================================================== # First process the NACs that are not bound to the LHS #=================================================================== else: # Look for a NAC match nacMatcher = HimesisMatcher(source_graph=graph, pattern_graph=NAC) # Convert the pivots nac_pivots = pivots.to_mapping(graph, NAC) try: for mapping in nacMatcher.match_iter(context=nac_pivots): if NAC.constraint(lambda i: getSourceNodeFromLabel(i, mapping, self.condition), graph): # An unbound NAC has been found: this pattern can never match return except: raise finally: nacMatcher.reset_recursion_limit() # For further matching optimizations pred1 = nacMatcher.pred1 succ1 = nacMatcher.succ1 # Either there are no NACs, or there were only unbound NACs that do not match, so match the LHS now bound_NACs.sort(key=lambda nac: nac.bridge.vcount(), reverse=True) if not bound_NACs: lhsMatcher = HimesisMatcher(source_graph=graph, pattern_graph=self.condition, pred1=pred1, succ1=succ1) # Convert the pivots lhs_pivots = pivots.to_mapping(graph, self.condition) try: for mapping in lhsMatcher.match_iter(context=lhs_pivots): if self.condition.constraint(lambda i: getSourceNodeFromLabel(i, mapping, self.condition), graph): yield mapping except: raise finally: lhsMatcher.reset_recursion_limit() # The matching is complete return #=================================================================== # Now process the NACs that have some nodes bound to the LHS #=================================================================== # Continue the matching looking for the LHS now lhsMatcher = HimesisMatcher(source_graph=graph, pattern_graph=self.condition, pred1=pred1, succ1=succ1) # Augment the bridge mapping with the pivot mappings lhs_pivots = pivots.to_mapping(graph, self.condition) try: for mapping in lhsMatcher.match_iter(context=lhs_pivots): if self.condition.constraint(lambda i: getSourceNodeFromLabel(i, mapping, self.condition), graph): # A match of the LHS is found: ensure that no remaining NAC do match invalid = False for NAC in bound_NACs: # This mapping represents the mapping of the bridge of this NAC with the LHS match = Match() match.from_mapping(mapping, graph, self.condition) bridgeMapping = match.to_mapping(graph, NAC) # Now continue the matching looking for a match of the corresponding NAC nacMatcher = HimesisMatcher(source_graph=graph, pattern_graph=NAC, pred1=pred1, succ1=succ1) for nac_mapping in nacMatcher.match_iter(context=bridgeMapping): if NAC.constraint(lambda i: getSourceNodeFromLabel(i, nac_mapping, NAC), graph): # An occurrence of the NAC is found: current mapping is not valid invalid = True break if invalid: # An occurrence of the NAC was found: current mapping is not valid break else: # Either there are no bound NACs or no occurrence of any bound NAC was found: current mapping is valid yield mapping except: raise finally: lhsMatcher.reset_recursion_limit()