def are_semantically_feasible(self, src_node, patt_node): """ Determines whether the two nodes are syntactically feasible, i.e., it ensures that adding this candidate pair does not make it impossible to find a total mapping. @param src_node: The candidate from the source graph. @param patt_node: The candidate from the pattern graph. @return: True if they are semantically feasible, False otherwise. """ #======================================================================= # This feasibility check looks at the data stored in the pair of candidates. # It verifies that all attribute constraints are satisfied. #======================================================================= src_node = self.G1.vs[src_node] patt_node = self.G2.vs[patt_node] # Check for attributes value/constraint for attr in patt_node.attribute_names(): # Attribute constraints are stored as attributes in the pattern node. # The attribute must be prefixed by a specific keyword if not attr.startswith(Himesis.Constants.MT_PRECOND_PREFIX): continue # If the attribute does not "in theory" exist # because igraph actually stores all attribute names in all nodes. elif patt_node[attr] == None: continue methName = self.G2.get_attr_constraint_name(patt_node.index, attr) checkConstraint = getattr(self.G2, methName, None) # The following assumes that every attribute constraint is defined on the pattern graph # (and not on the pattern node itself) if callable(checkConstraint): try: # This is equivalent to: if not eval_attrLbl(attr_value, currNode) if not checkConstraint(src_node[Himesis.to_non_RAM_attribute(attr)], src_node): return False except Exception, e: #TODO: This should be a TransformationLanguageSpecificException raise Exception("An error has occurred while checking the constraint of the attribute '%s'" % Himesis.to_non_RAM_attribute(attr), e) else: raise Exception('The method %s was not found in the pattern graph' % methName)
def are_compatibile(self, src_node, patt_node): """ Verifies if a candidate pair is compatible. More specifically, verify degree and meta-model compatibility. @param src_node: The candidate from the source graph. @param patt_node: The candidate from the pattern graph. """ sourceNode = self.G1.vs[src_node] patternNode = self.G2.vs[patt_node] # First check if they are of the same type if sourceNode[Himesis.Constants.META_MODEL] == Himesis.to_non_RAM_attribute(patternNode[Himesis.Constants.META_MODEL]): # Then check for the degree compatibility return (self.pred2[patt_node][0] <= self.pred1[src_node][0] and self.succ2[patt_node][0] <= self.succ1[src_node][0]) # Otherwise, first check for the degree compatibility elif not (self.pred2[patt_node][0] <= self.pred1[src_node][0] and self.succ2[patt_node][0] <= self.succ1[src_node][0]): return False # Then check sub-types compatibility else: return (patternNode[Himesis.Constants.MT_SUBTYPE_MATCH] and sourceNode[Himesis.Constants.META_MODEL] in map(lambda x:Himesis.to_non_RAM_attribute(x), patternNode[Himesis.Constants.MT_SUBTYPES]))