예제 #1
0
class AssertAggregate(Assert):
    def __init__(self, **kwargs):
        self.map_reduce_values = {}
        for key, value in kwargs.items():
            if isinstance(value, MapReduceFunc):
                del kwargs[key]
                subkeys = []
                for n, map_value in enumerate(value.map_values):
                    subkey = key if n == 0 else '{}_{}'.format(key, n+1)
                    kwargs[subkey] = map_value
                    subkeys.append(subkey)
                self.map_reduce_values[key] = (value, subkeys)
        super(AssertAggregate, self).__init__(**kwargs)
        
    def prepare_rule(self, rule):
        self.data.update({key : normalize_expr(value) for key, value in rule.groupby.iteritems()})
        self.data[UNIQUE_INDEX_FIELD] = gensym()  
        super(AssertAggregate, self).prepare_rule(rule)
        self._create_reduce_rule(rule)
        
    def _create_reduce_rule(self, map_rule):
        r1 = map_rule.target[0]
        r2 = map_rule.target[1]
        self.reduce_rule = Rule()
        self.reduce_rule.set_name('_Reduce')
        for field_name in map_rule.groupby:
            self.reduce_rule.add_variable(getattr(r1, field_name), getattr(r2, field_name))
        self.reduce_rule.add_condition(fact_index(r1) != fact_index(r2))
        
        reduce_kwargs = {}
        for field_name, (value, subfields) in self.map_reduce_values.iteritems():
            v1 = [getattr(r1, field_name) for field_name in subfields]
            v2 = [getattr(r2, field_name) for field_name in subfields]
            if len(subfields) == 1: 
                v1 = v1[0]
                v2 = v2[0]
            reduced = value._reduce(v1, v2)
            if len(subfields) == 1:
                reduced = [reduced]
            reduce_kwargs.update(dict(zip(subfields, reduced)))
        self.reduce_rule.add_action(Delete(r2))
        self.reduce_rule.add_action(Update(r1, **reduce_kwargs))
        self.reduce_rule.set_salience(map_rule.salience)
        map_rule.add_secondary_rule(self.reduce_rule)
예제 #2
0
    def test_add_condition(self):
        print(">> Rule.add_condition(self, variable, value)")

        # Empty rule
        for i in range(self.__nb_unit_test):
            var = random.randint(0, self.__var_size)
            val = random.randint(0, self.__val_size)
            r = Rule(var, val)

            var = random.randint(0, self.__var_size)
            val = random.randint(0, self.__val_size)

            self.assertFalse(r.has_condition(var))
            r.add_condition(var, val)
            self.assertEqual(r.get_condition(var), val)

        for i in range(self.__nb_unit_test):
            r = self.random_rule()

            if len(r.get_body()) == 0:
                i -= 1
                continue

            conditions = []
            for var, val in r.get_body():
                conditions.append(var)

            var = conditions[0]
            while var in conditions:
                var = random.randint(0, self.__var_size)

            val = random.randint(0, self.__val_size)

            self.assertFalse(r.has_condition(var))
            r.add_condition(var, val)
            self.assertEqual(r.get_condition(var), val)
예제 #3
0
파일: pride.py 프로젝트: atakemura/pylfit
    def fit_var_val(variable, value, positives, negatives):
        """
        Learn minimal rules that explain positive examples while consistent with negatives examples

        Args:
            variable: int
                variable id
            value: int
                variable value id
            positive: list of (list of int)
                States of the system where the variable takes this value in the next state
            negative: list of (list of int)
                States of the system where the variable does not take this value in the next state
        """
        #eprint("Start learning of var="+str(variable)+", val="+str(value))

        remaining = positives.copy()
        output = []

        # exausting covering loop
        while len(remaining) > 0:
            #eprint("Remaining positives: "+str(remaining))
            #eprint("Negatives: "+str(negatives))
            target = remaining[0]
            #eprint("new target: "+str(target))

            R = Rule(variable, value)
            #eprint(R.to_string())

            # 1) Consistency: against negatives examples
            #---------------------------------------------
            for neg in negatives:
                if R.matches(neg):  # Cover a negative example
                    #eprint(R.to_string() + " matches " + str(neg))
                    for var in range(0, len(target)):
                        if not R.has_condition(var) and neg[var] != target[
                                var]:  # free condition
                            #eprint("adding condition "+str(var)+":"+str(var)+"="+str(target[var]))
                            if target[
                                    var] > -1:  # Valid target value (-1 encode all value for partial state)
                                R.add_condition(
                                    var, target[var]
                                )  # add value of target positive example
                                break

            # 2) Minimalize: only necessary conditions
            #-------------------------------------------

            reductible = True

            conditions = R.get_body().copy()

            for (var, val) in conditions:
                R.remove_condition(var)  # Try remove condition

                conflict = False
                for neg in negatives:
                    if R.matches(neg):  # Cover a negative example
                        conflict = True
                        R.add_condition(var, val)  # Cancel removal
                        break

            # Add new minimal rule
            #eprint("New rule: "+R.to_string())
            output.append(R)
            remaining.pop(0)

            # 3) Clean new covered positives examples
            #------------------------------------------
            i = 0
            while i < len(remaining):
                if R.matches(remaining[i]):
                    #eprint("Covers "+str(remaining[i]))
                    remaining.pop(i)
                else:
                    i += 1

        return output
예제 #4
0
    def random(variables, values, rule_min_size, rule_max_size, delay=1):
        """
        Generate a deterministic complete logic program with a random dynamics.
        For each variable of the system, each possible state of the system is matched by at least one rule.

        Args:
            variables: list of String
                Labels of the program variables
            values: list of list of String
                Domain of values that each variable can take
            rule_min_size: int
                minimal number of conditions in each rule
            rule_max_size: int
                maximal number of conditions in each rule (can be exceeded for completeness)
            delay: int
                maximal delay of the conditions of each rule
        """
        extended_variables = variables.copy()
        extended_values = values.copy()

        # Delayed logic program: extend local herbrand base
        if delay > 1:
            for d in range(1, delay):
                extended_variables += [var + "_" + str(d) for var in variables]
                extended_values += values

        rules = []
        p = LogicProgram(extended_variables, extended_values, [])
        states = p.states()  # aggregated reversed time serie of size delay

        for s in states:
            for var in range(len(variables)):

                matching = False
                for r in rules:  # check if matched
                    if r.get_head_variable() == var and r.matches(s):
                        matching = True
                        break

                if not matching:  # need new rule
                    val = random.randint(0, len(values[var]) - 1)
                    body_size = random.randint(rule_min_size, rule_max_size)

                    new_rule = Rule(var, val, [])

                    # Prevent cross-match
                    for r in rules:
                        if r.get_head_variable() == var and r.cross_matches(
                                new_rule):
                            # Search an available variable
                            # Always exists since no rule matches s yet
                            while True:
                                (cond_var,
                                 cond_val) = random.choice(r.get_body())
                                if not new_rule.has_condition(
                                        cond_var) and cond_val != s[cond_var]:
                                    new_rule.add_condition(
                                        cond_var, s[cond_var])
                                    break

                    # Complete the rule body if needed
                    while (new_rule.size() < body_size):  # create body
                        cond_var = random.randint(0, len(s) - 1)
                        cond_val = s[cond_var]

                        if new_rule.has_condition(cond_var):
                            continue

                        new_rule.add_condition(cond_var, cond_val)

                    rules.append(new_rule)

        return LogicProgram(variables, values, rules)