def specialize(self, rule):
        '''
        Returns a list of all specializations of 'rule'.
        '''
        is_unary = lambda p: isinstance(p, UnaryPredicate)

        def specialize_optimal_subclass(rule):
            rules = []
            eligible_preds = rule.shared_var[rule.latest_var]
            for pred in filter(is_unary, eligible_preds):
                for sub_class in self.get_subclasses(pred):
                    logger.debug('Swapping with %s' % sub_class)
                    new_rule = rule.clone_swap_with_subclass(pred, sub_class)
                    if self.can_specialize(new_rule):
                        rules.append(new_rule)
                        rules.extend(specialize_optimal_subclass(new_rule))
            return rules

        logger.debug('Specializing rule: %s' % rule)
        specializations = []
        eligible_preds = rule.shared_var[rule.latest_var]

        # Swapping unary predicates with subclasses, swap only
        # the predicates with the latest variable
        if not self.optimal_subclass:
            for pred in filter(is_unary, eligible_preds):
                logger.debug('Predicate to swap: %s' % pred.label)
                for sub_class in self.get_subclasses(pred):
                    logger.debug('Swapping with %s' % sub_class)
                    new_rule = rule.clone_swap_with_subclass(pred, sub_class)
                    if self.can_specialize(new_rule):
                        specializations.append(new_rule)
        else:
            specializations.extend(specialize_optimal_subclass(rule))

        if self.use_negations:
            # Negate the last predicate
            for pred in filter(is_unary, eligible_preds):
                logger.debug('Predicate to negate: %s' % pred.label)
                new_rule = rule.clone_negate(pred)
                if self.can_specialize(new_rule):
                    specializations.append(new_rule)

        # This makes sure we are not specializing a default rule by appending,
        # this rule should instead be reached by the specialization step above.
        if not (len(eligible_preds) == 1 and
           (eligible_preds[0].label == self.kb.get_root().label or
           self.is_implicit_root(eligible_preds[0].label))):

            # Calculate the union of superclasses of each predicate
            supers = set()
            for pred in eligible_preds:
                supers.update(self.get_superclasses(pred.label))
                supers.add(pred)

            # Calculate the top-most left-most non-ancestor
            for lvl in sorted(self.kb.levels.keys()):

                level = self.kb.levels[lvl]
                diff = level.difference(supers)
                if diff:

                    # The next predicate to specialize with is the left-most
                    for pred in sorted(list(diff)):

                        # Appending a new predicate, the last predicate
                        # is always the producer
                        last_pred = rule.predicates[-1]
                        new_rule = rule.clone_append(pred,
                                                     producer_pred=last_pred)
                        if self.can_specialize(new_rule) and \
                           self.non_redundant(rule, new_rule):
                            specializations.append(new_rule)
                            break

        # Introduce new binary relation
        if isinstance(rule.predicates[-1], UnaryPredicate):
            specializations.extend(self.specialize_add_relation(rule))

        logger.debug('All specializations %s'
                     % [str(rule) for rule in specializations])

        return specializations
dataset/ETHPy150Open anzev/hedwig/hedwig/learners/learner.py/Learner.specialize/original