'Return a single rule.
The search is guided by search heuristics (evaluators) and
controlled by over-fitting avoidance heuristics (validators).
Search strategy creates and refines rules, whereas search
algorithm maneuvers through the search space towards a better
solution.
Parameters
X, Y, W : ndarray
Learning data.
target_class : int
Index of the class to model.
base_rules : list of Rule
An optional list of initial rules to constrain the search.
domain : Orange.data.domain.Domain
Data domain, used to calculate class distributions.
initial_class_dist : ndarray
Data class distribution in regard to the whole learning set.
existing_rules : list of Rule
Rules found in previous iterations (to avoid duplicates).
Returns
best_rule : Rule
Highest quality rule discovered.'

def __call__(self, X, Y, W, target_class, base_rules, domain, initial_class_dist, existing_rules):

    def rcmp(rule):
        return (rule.quality, rule.complexity)
    prior_class_dist = get_dist(Y, W, domain)
    rules = self.search_strategy.initialise_rule(X, Y, W, target_class, base_rules, domain, initial_class_dist, prior_class_dist, self.quality_evaluator, self.complexity_evaluator, self.significance_validator, self.general_validator)
    if (not rules):
        return None
    rules = sorted(rules, key=rcmp, reverse=True)
    best_rule = rules[0]
    while (len(rules) > 0):
        (candidates, rules) = self.search_algorithm.select_candidates(rules)
        for candidate_rule in candidates:
            new_rules = self.search_strategy.refine_rule(X, Y, W, candidate_rule)
            rules.extend(new_rules)
            for new_rule in new_rules:
                if ((new_rule.quality > best_rule.quality) and new_rule.is_significant() and (new_rule not in existing_rules)):
                    best_rule = new_rule
        rules = sorted(rules, key=rcmp, reverse=True)
        rules = self.search_algorithm.filter_rules(rules)
    best_rule.create_model()
    return (best_rule if (best_rule not in existing_rules) else None)
