Beispiel #1
0
    def request(self, state):
        tup = Tuplizer()
        flt = Flattener()
        state = flt.transform(tup.transform(state))

        knowledge_base = FoPlanner([(self.ground(a), state[a].replace(
            '?', 'QM') if isinstance(state[a], str) else state[a])
                                    for a in state], self.feature_set)
        knowledge_base.fc_infer(depth=1, epsilon=self.epsilon)
        ostate = {
            self.unground(a): v.replace("QM", "?") if isinstance(v, str) else v
            for a, v in knowledge_base.facts
        }

        knowledge_base = FoPlanner([(self.ground(a), state[a].replace(
            '?', 'QM') if isinstance(state[a], str) else state[a])
                                    for a in state], self.function_set)
        knowledge_base.fc_infer(depth=self.search_depth, epsilon=self.epsilon)

        state = {
            self.unground(a): v.replace("QM", "?") if isinstance(v, str) else v
            for a, v in knowledge_base.facts
        }

        actions = [{
            'skill_label': 'NO_LABEL',
            'foci_of_attention': [],
            'selection': vm['?selection'],
            'action': vm['?action'],
            'inputs': {e[0]: e[1]
                       for e in vm['?inputs']}
        } for vm in knowledge_base.fc_query([(('sai', '?selection', '?action',
                                               '?inputs'), True)],
                                            max_depth=0,
                                            epsilon=0)]

        actions = [(self.Q.evaluate(ostate,
                                    self.get_action_key(a)), random(), a)
                   for a in actions]

        actions.sort(reverse=True)
        # print(actions)

        self.last_state = ostate
        self.last_action = self.get_action_key(actions[0][2])
        self.reward = 0

        return actions[0][2]
    def explanations_from_how_search(self, state, sai, input_args):
        explanations = []

        _, selection, action, inputs = sai
        knowledge_base = FoPlanner([(ground(a), state[a].replace('?', 'QM') if
                                     isinstance(state[a], str) else state[a])
                                    for a in state], self.function_set)
        knowledge_base.fc_infer(depth=self.search_depth, epsilon=self.epsilon)

        #Danny: these lines figure out what property holds the selection
        selection_exp = selection
        for sel_match in knowledge_base.fc_query([('?selection', selection)],
                                                 max_depth=0,
                                                 epsilon=self.epsilon):

            selection_exp = sel_match['?selection']
            # print("selection_exp", selection_exp)
            #selection_exp: ('id', 'QMele-done')
            break

        input_exps = []

        for arg in input_args:
            input_exp = input_val = inputs[arg]
            # print('trying to explain', [((a, '?input'), iv)])

            # TODO not sure what the best approach is for choosing among
            # the possible explanations. Perhaps we should choose more than
            # one. Maybe the shortest (less deep).

            # f = False

            #Danny: This populates a list of explanations found earlier in How search that work"
            possible = []
            for iv_m in knowledge_base.fc_query([((arg, '?input'), input_val)],
                                                max_depth=0,
                                                epsilon=self.epsilon):

                # print("iv_m:", iv_m)

                possible.append((arg, iv_m['?input']))

            possible = [(compute_exp_depth(p), random(), p) for p in possible]
            possible.sort()

            if len(possible) > 0:
                _, _, input_exp = possible[0]

            input_exps.append(input_exp)
            print("input_exp:", input_exp)

        explanations.append(
            unground(('sai', selection_exp, action, *input_exps)))
        print("EXPLANATIONS:", explanations)
        return explanations
    def train(self, state, selection, action, inputs, reward, skill_label,
              foci_of_attention):
        """
        Doc String
        """

        # print('\n'*5)
        # print('state', skill_label)
        # print('skill_label', skill_label)
        # print('selection', selection)
        # print('action', action)
        # print('inputs', inputs)
        # print('reward', reward)
        # print('state')
        # pprint(state)

        # label = 'math'

        # create example dict
        example = {}
        example['state'] = state
        example['skill_label'] = skill_label
        example['selection'] = selection
        example['action'] = action
        example['inputs'] = inputs
        example['reward'] = float(reward)

        tup = Tuplizer()
        flt = Flattener()
        example['flat_state'] = flt.transform(tup.transform(state))

        knowledge_base = FoPlanner(
            [(ground(a),
              example['flat_state'][a].replace('?', 'QM') if isinstance(
                  example['flat_state'][a], str) else example['flat_state'][a])
             for a in example['flat_state']], self.feature_set)

        knowledge_base.fc_infer(depth=1, epsilon=self.epsilon)

        example['flat_state'] = {
            unground(a): v.replace("QM", "?") if isinstance(v, str) else v
            for a, v in knowledge_base.facts
        }

        if skill_label not in self.skills:
            self.skills[skill_label] = {}

        explanations = []
        secondary_explanations = []

        # the base explaination (the constants)
        input_args = tuple(sorted([arg for arg in inputs]))
        sai = ('sai', selection, action, *[inputs[a] for a in input_args])

        # Need to do stuff with features here too.

        # used for grounding out plans, don't need to build up each time.
        # print(function_sets[self.action_set])

        # knowledge_base = FoPlanner([(ground(a),
        #                              example['flat_state'][a].replace('?', 'QM')
        #                              if isinstance(example['flat_state'][a], str)
        #                              else example['flat_state'][a])
        #                             for a in example['flat_state']],
        #                            self.function_set)
        # knowledge_base.fc_infer(depth=self.search_depth, epsilon=self.epsilon)

        # FACTS AFTER USING FUNCTIONS.
        # pprint(knowledge_base.facts)

        #DANNY: The gist of this is to find_ applicable_skills (explanations because the inputs/outputs are literals)
        for skill, learner_dict in self.skills[skill_label].items():
            exp, iargs = skill
            for match in self.explain_sai(skill, learner_dict, sai,
                                          knowledge_base,
                                          example['flat_state']):

                # print("MATCH", match)
                # print("COVERED", exp, m)

                #DANNY NOTES:
                #sai = ('sai', 'JCommTable5.R0C0', 'UpdateTextArea', '16')
                #exp  =  ('sai', ('id', '?foa0'), 'UpdateTextArea', ('value', ('Multiply', ('value', '?foa1'), ('value', '?foa2'))))
                #r_exp  =  the explanation renamed with the match literals
                #ARGS = A list of input arguements to the explanations
                #IARGS: = A tuple of outputs? Or maybe a set of property names (i.e. 'value').
                #Match = A dictionary mapping from ?foas to element strings (the element names have QM instead of ?)

                r_exp = unground(list(rename_flat({exp: True}, match))[0])
                args = get_vars(exp)

                # print("sai:", sai)
                # print("exp:", exp)
                # print("r_exp:", r_exp)
                # print("ARGS:", args)
                # print("IARGS:", iargs, type(iargs))
                # print("match", match)

                # Need to check if it would have been actully generated
                # under where and when.
                # Danny: Makes sure that there is a match for every arguement
                if len(args) != len(match):
                    continue

                # print("HERE1")

                #DANNY: Checks that the match resolves to string elements
                grounded = True
                for ele in match:
                    if not isinstance(match[ele], str):
                        grounded = False
                        break
                if not grounded:
                    #DANNY: Doesn't really happen... not sure in what circumstances this would happen
                    # print("BAD MATCH: ", match)
                    continue

                # print("HERE2")

                tup = tuple([
                    match["?foa%s" % i].replace("QM", "?")
                    for i in range(len(match))
                ])

                # print("tup:", tup)

                #tup = a tuple of the matches
                #Danny: Makes sure that the explanation hasn't used an foa twice
                if len(tup) != len(set(tup)):
                    continue

                # print("HERE3")

                secondary_explanations.append(r_exp)

                #Danny: Check that the where learner approves of the match
                #       It seems like the where learner should have just generated this if it was going to check it anyway
                #       This is only at the end it seems to allow for secondary explanations which the where learner is not yet aware of
                # print("A", self.skills[skill_label])
                # print("B", self.skills[skill_label][(exp, iargs)])
                skill_where = self.skills[skill_label][(exp, iargs)]['where']
                if not skill_where.check_match(tup, example['flat_state']):
                    continue

                # print("ADDING", r_exp)
                explanations.append(r_exp)

        if len(explanations) == 0 and len(secondary_explanations) > 0:
            explanations.append(choice(secondary_explanations))

        elif len(explanations) == 0:

            explanations = self.explanations_from_how_search(
                example['flat_state'], ('sai', selection, action, inputs),
                input_args)

        #Danny: Do the training for all the applicable explanations
        # print("EXPLAINS", explanations)
        for exp in explanations:
            args = get_vars(exp)
            foa_vmapping = {
                field: '?foa%s' % j
                for j, field in enumerate(args)
            }
            foa_mapping = {field: 'foa%s' % j for j, field in enumerate(args)}
            r_exp = (list(rename_flat({exp: True},
                                      foa_vmapping))[0], input_args)

            if r_exp not in self.skills[skill_label]:

                # TODO - Hack for specific action set
                # if self.action_set == "tutor knowledge":
                #     constraints = self.generate_tutor_constraints(r_exp[0])
                # else:
                #     constraints = self.extract_mg_h(r_exp[0])
                # constraints = extract_mg_h(r_exp[0])
                constraints = generate_html_tutor_constraints(r_exp[0])

                # print("CONSTRAINTS")
                # print(constraints)

                w_args = tuple(['?foa%s' % j for j, _ in enumerate(args)])

                self.skills[skill_label][r_exp] = {}
                where_inst = self.where(args=w_args, constraints=constraints)
                self.skills[skill_label][r_exp]['where'] = where_inst
                self.skills[skill_label][r_exp]['when'] = self.when()

            self.skills[skill_label][r_exp]['where'].ifit(
                args, example['flat_state'], example['reward'])
            # print('done where learning')

            # TODO
            # Need to add computed features.
            # need to rename example with foa's that are not variables
            r_flat = rename_flat(example['flat_state'], foa_mapping)

            self.skills[skill_label][r_exp]['when'].ifit(
                r_flat, example['reward'])
    def request(self, state):
        """
        Doc String
        TODO - several Linter problems with this one
        """
        tup = Tuplizer()
        flt = Flattener()
        state = flt.transform(tup.transform(state))

        knowledge_base = FoPlanner([(ground(a), state[a].replace('?', 'QM') if
                                     isinstance(state[a], str) else state[a])
                                    for a in state], self.feature_set)
        knowledge_base.fc_infer(depth=1, epsilon=self.epsilon)
        state = {
            unground(a): v.replace("QM", "?") if isinstance(v, str) else v
            for a, v in knowledge_base.facts
        }

        skillset = []

        # pprint(self.skills)

        for skill_label in self.skills:
            for exp in self.skills[skill_label]:
                pos = self.skills[skill_label][exp]['where'].num_pos()
                neg = self.skills[skill_label][exp]['where'].num_neg()

                skillset.append(
                    (pos / (pos + neg), pos + neg, random(), skill_label, exp,
                     self.skills[skill_label][exp]))
        skillset.sort(reverse=True)

        # used for grounding out plans, don't need to build up each time.
        # knowledge_base = FoPlanner([(ground(a), state[a].replace('?', 'QM')
        #                              if isinstance(state[a], str)
        #                              else state[a])
        #                             for a in state],
        #                            self.function_set)
        # knowledge_base.fc_infer(depth=self.search_depth, epsilon=self.epsilon)

        # TODO - would it be too expensive to make skillset contain some kind of Skill object?
        # because this for loop is ridiculous
        for _, _, _, skill_label, (exp, input_args), skill in skillset:

            # print("STATE")
            # pprint(state)
            # print("--------")
            # print(exp)
            # print("contentEditable: ",state.get( ('contentEditable',"?ele-" + exp[1]) ,True) )
            # if(state.get( ('contentEditable',"?ele-" + exp[1]) ,True) == False):
            #     continue
            # print("")
            # print("REQUEST_EXPLAINS", exp)

            # Continue until we either do something with the rule. For example,
            # generate an SAI or determine that the rule doesn't match. If we
            # get some kind of failure, such as being unable to execute an
            # action sequence, then we want to learn from that and try again.
            failed = True

            # print("SKILL: ",exp, input_args)

            while failed:

                failed = False

                # print("STATE")
                # pprint(state)
                # print("--------")

                for match in skill['where'].get_matches(state,
                                                        epsilon=self.epsilon):
                    # print("REE1")
                    if len(match) != len(set(match)):
                        continue

                    # print("MATCH FOUND", skill_label, exp, match)
                    vmapping = {
                        '?foa' + str(i): ele
                        for i, ele in enumerate(match)
                    }
                    mapping = {
                        'foa' + str(i): ele
                        for i, ele in enumerate(match)
                    }

                    # print("VMAP")
                    # pprint(vmapping)
                    # print("MAP")
                    # pprint(mapping)

                    r_exp = list(rename_flat({exp: True}, vmapping))[0]
                    r_state = rename_flat(state,
                                          {mapping[a]: a
                                           for a in mapping})

                    # print("KB", knowledge_base)
                    rg_exp = eval_expression(r_exp, knowledge_base,
                                             self.function_set, self.epsilon)
                    # for ele in r_exp:
                    #     if isinstance(ele, tuple):
                    #         # print("THIS HAPPENED", ele, ground(ele), execute_functions(ground(ele)))

                    #                 # execute_functions(subt(u))
                    #                 # rg_exp.append()

                    #             # print("BLEHH:", operator.effects)

                    #         for var_match in knowledge_base.fc_query([(ground(ele), '?v')],
                    #                                                  max_depth=0,
                    #                                                   epsilon=self.epsilon):
                    #             # print("VARM:",var_match, ground(ele))
                    #             if var_match['?v'] != '':
                    #                 rg_exp.append(var_match['?v'])
                    #                 # print("HERE_A",rg_exp[-1])
                    #             break

                    #         operator_output = apply_operators(ele,self.function_set,knowledge_base,self.epsilon)
                    #         # print(operator_output)
                    #         if(operator_output != None and operator_output != ""):
                    #             rg_exp.append(operator_output)
                    #             # print("HERE_B",operator_output)

                    #         # if(operator_output != None):
                    #         #     rg_exp.append(operator_output)

                    #     else:
                    #         rg_exp.append(ele)

                    # print("REE2")

                    # print("rg_exp:", rg_exp)
                    # print("r_exp:", r_exp)

                    if len(rg_exp) != len(r_exp):
                        continue

                    # print("EXP:", r_exp)
                    # print("RSTATE ---------------")
                    # pprint(r_state)
                    # print("---------------")

                    # print("REE3")
                    prediction = skill['when'].predict([r_state])[0]

                    # print("when", skill['when'])

                    # print("PREDICTION:", type(prediction), prediction)

                    if prediction <= 0:
                        continue
                    # print("REE4")
                    response = {}
                    response['skill_label'] = skill_label
                    response['selection'] = rg_exp[1]
                    response['action'] = rg_exp[2]
                    response['inputs'] = {
                        a: rg_exp[3 + i]
                        for i, a in enumerate(input_args)
                    }
                    # response['inputs'] = list(rg_exp[3:])
                    response['foci_of_attention'] = []
                    # pprint(response)
                    return response

        return {}
Beispiel #5
0
    def request(self, state):
        tup = Tuplizer()
        flt = Flattener()
        state = flt.transform(tup.transform(state))

        new = {}
        for attr in state:
            if (isinstance(attr, tuple) and attr[0] == 'value'):
                new[('editable', attr[1])] = state[attr] == ''
                for attr2 in state:
                    if (isinstance(attr2, tuple) and attr2[0] == 'value'):
                        if (attr2 == attr or attr < attr2
                                or (state[attr] == "" or state[attr2] == "")):
                            continue
                        if (state[attr] == state[attr2]):
                            new[('eq', attr, attr2)] = True
        state.update(new)
        # pprint(state)

        # for episode in range(self.max_episodes):
        while True:

            print("#########")
            print("NEW TRACE")
            print("#########")
            kb = FoPlanner([(self.ground(a), state[a].replace('?', 'QM')
                             if isinstance(state[a], str) else state[a])
                            for a in state], functionsets[self.action_set])

            curr_state = {x[0]: x[1] for x in kb.facts}
            next_actions = [a for a in kb.fc_get_actions(epsilon=epsilon)]
            trace_actions = []
            depth = 0

            while depth < search_depth:
                actions = [(self.Q.evaluate(curr_state, get_action_key(a)), a)
                           for a in next_actions]

                print("NEXT ACTION WEIGHTS")
                print(
                    sorted([(w, a[0].name[0]) for w, a in actions],
                           reverse=True))

                # operator, mapping, effects = weighted_choice(actions)
                operator, mapping, effects = max_choice(actions)
                # operator, mapping, effects = choice(action_space)

                self.last_state = curr_state
                self.last_action = get_action_key((operator, mapping, effects))
                trace_actions.append(subst(mapping, operator.name))

                for f in effects:
                    kb.add_fact(f)

                # if not termainal, then decrease reward
                # self.reward = -1
                self.reward = 0
                curr_state = {x[0]: x[1] for x in kb.facts}
                depth += 1

                # check if we're in a terminal state
                # if so, query oracle
                for f in effects:
                    f = self.unground(f)
                    if f[0] == 'sai':
                        response = {}
                        response['label'] = str(trace_actions)
                        response['selection'] = f[1]
                        response['action'] = f[2]
                        response['inputs'] = {'value': f[3]}
                        # {a: rg_exp[3+i] for i, a in
                        #                       enumerate(input_args)}
                        # response['inputs'] = list(rg_exp[3:])
                        response['foas'] = []
                        # pprint(response)
                        print("EXECUTING ACTION", self.last_action)
                        print("Requesting oracle feedback")

                        return response

                # punish for failed search
                if depth >= search_depth:
                    # self.reward -= 3 * search_depth
                    curr_state = None
                    next_actions = []
                else:
                    # because we're not terminal we can compute next_actions
                    next_actions = [
                        a for a in kb.fc_get_actions(epsilon=epsilon,
                                                     must_match=effects)
                    ]

                self.Q.update(self.last_state, self.last_action, self.reward,
                              curr_state, next_actions)
    def request(self, state):
        # print(state)
        # print("REQUEST RECEIVED")
        tup = Tuplizer()
        flt = Flattener()

        state = flt.transform(tup.transform(state))

        # new = {}
        # for attr in state:
        #     if (isinstance(attr, tuple) and attr[0] == 'value'):
        #         new[('editable', attr[1])] = state[attr] == ''
        #         for attr2 in state:
        #             if (isinstance(attr2, tuple) and attr2[0] == 'value'):
        #                 if (attr2 == attr or attr < attr2 or
        #                     (state[attr] == "" or state[attr2] == "")):
        #                     continue
        #                 if (state[attr] == state[attr2]):
        #                     new[('eq', attr, attr2)] = True
        # state.update(new)

        kb = FoPlanner([(self.ground(a),
                         state[a].replace('?', 'QM') if
                         isinstance(state[a], str) else
                         state[a])
                        for a in state], featuresets[self.action_set])
        kb.fc_infer(depth=1, epsilon=epsilon)
        state = {self.unground(a): v.replace("QM", "?") if isinstance(v, str)
                 else v for a, v in kb.facts}

        # pprint(state)

        # compute features

        # for attr, value in self.compute_features(state):
        #     state[attr] = value

        skillset = []
        for label in self.skills:
            for exp in self.skills[label]:
                pos = self.skills[label][exp]['where'].num_pos()
                neg = self.skills[label][exp]['where'].num_neg()

                skillset.append((pos / (pos + neg), pos + neg,
                                 random(), label, exp,
                                 self.skills[label][exp]))
        skillset.sort(reverse=True)

        # print('####SKILLSET####')
        pprint(skillset)
        # print('####SKILLSET####')

        # used for grounding out plans, don't need to build up each time.
        kb = FoPlanner([(self.ground(a),
                         state[a].replace('?', 'QM') if
                         isinstance(state[a], str) else
                         state[a])
                        for a in state], functionsets[self.action_set])
        kb.fc_infer(depth=search_depth, epsilon=epsilon)

        # print(kb)

        for _, _, _, label, (exp, input_args), skill in skillset:

            # print()
            # print("TRYING:", label, exp)

            # print("Conditions:")
            # pprint(skill['where'].operator.conditions)

            # Continue until we either do something with the rule. For example,
            # generate an SAI or determine that the rule doesn't match. If we
            # get some kind of failure, such as being unable to execute an
            # action sequence, then we want to learn from that and try again.
            failed = True

            while failed:

                failed = False
                for m in skill['where'].get_matches(state, epsilon=epsilon):
                    if len(m) != len(set(m)):
                        # print("GENERATED MATCH WITH TWO VARS BOUND TO ",
                        #       "SAME THING")
                        continue

                    # print("MATCH FOUND", label, exp, m)
                    vmapping = {'?foa' + str(i): ele
                                for i, ele in enumerate(m)}
                    mapping = {'foa' + str(i): ele
                               for i, ele in enumerate(m)}

                    r_exp = list(rename_flat({exp: True}, vmapping))[0]
                    r_state = rename_flat(state,
                                          {mapping[a]: a for a in mapping})

                    # pprint(r_state)

                    # pprint(r_state)

                    rg_exp = []
                    for ele in r_exp:
                        if isinstance(ele, tuple):
                            # kb = FoPlanner([(self.ground(a),
                            #                  state[a].replace('?', 'QM') if
                            #                  isinstance(state[a], str) else
                            #                  state[a])
                            #                 for a in state],
                            #                functionsets[self.action_set])
                            for vm in kb.fc_query([(self.ground(ele), '?v')],
                                                  max_depth=0,
                                                  epsilon=epsilon):
                                # if vm['?v'] == '':
                                #     raise Exception("Should not be an"
                                #                     " empty str")
                                if vm['?v'] != '':
                                    rg_exp.append(vm['?v'])
                                break
                        else:
                            rg_exp.append(ele)

                    if len(rg_exp) != len(r_exp):
                        # print("FAILED TO FIRE RULE")
                        # print(rg_exp, 'from', r_exp)
                        continue

                        # # add neg to where
                        # skill['where'].ifit(m, state, 0)

                        # # add neg to when
                        # foa_mapping = {field: 'foa%s' % j for j, field in
                        #                enumerate(m)}
                        # neg_x = rename_flat(state, foa_mapping)
                        # skill['when'].ifit(neg_x)

                        # failed = True
                        # break

                    # print("predicting")
                    # pprint(r_state)

                    # c = skill['when'].categorize(r_state)
                    p = skill['when'].predict([r_state])[0]

                    # print("###CATEGORIZED CONCEPT###")
                    # print(c)
                    # pprint(c.av_counts)
                    # print(c.predict('correct'))

                    if p == 0:
                        # print("predicting FAIL")
                        continue
                    # print("predicting FIRE")

                    # if not c.predict('correct'):
                    #     print("predicting FAIL")
                    #     continue
                    # print("predicting FIRE")

                    # print("###TREE###")
                    # print(skill['when'])

                    # pprint(r_exp)
                    # pprint(rg_exp)

                    # assert self.explains_sai(kb, r_exp, rg_exp)

                    response = {}
                    response['label'] = label
                    response['selection'] = rg_exp[1]
                    response['action'] = rg_exp[2]
                    response['inputs'] = {a: rg_exp[3+i] for i, a in
                                          enumerate(input_args)}
                    # response['inputs'] = list(rg_exp[3:])
                    response['foas'] = []
                    # pprint(response)
                    return response

        return {}
    def train(self, state, label, foas, selection, action, inputs, correct):
        print('label', label)
        print('selection', selection)
        print('action', action)
        print('input', inputs)
        print('correct', correct)

        # label = 'math'

        # create example dict
        example = {}
        example['state'] = state
        example['label'] = label
        example['selection'] = selection
        example['action'] = action
        example['inputs'] = inputs
        example['correct'] = correct

        tup = Tuplizer()
        flt = Flattener()
        example['flat_state'] = flt.transform(tup.transform(state))
        # print('SAI:', selection, action, inputs)

        # print('State:')
        # pprint(example['state'])
        # print('Flat State:')
        # pprint(example['flat_state'])

        # new = {}
        # for attr in example['flat_state']:
        #     if (isinstance(attr, tuple) and attr[0] == 'value'):
        #         new[('editable', attr[1])] =
        #           example['flat_state'][attr] == ''

        #         for attr2 in example['flat_state']:
        #             if (isinstance(attr2, tuple) and attr2[0] == 'value'):
        #                 if (attr2 == attr or attr < attr2 or
        #                     (example['flat_state'][attr] == "" or
        #                      example['flat_state'][attr2] == "")):
        #                     continue
        #                 if ((example['flat_state'][attr] ==
        #                      example['flat_state'][attr2])):
        #                     new[('eq', attr, attr2)] = True

        # example['flat_state'].update(new)

        kb = FoPlanner([(self.ground(a),
                         example['flat_state'][a].replace('?', 'QM') if
                         isinstance(example['flat_state'][a], str) else
                         example['flat_state'][a])
                        for a in example['flat_state']],
                       featuresets[self.action_set])
        kb.fc_infer(depth=1, epsilon=epsilon)
        example['flat_state'] = {self.unground(a): v.replace("QM", "?") if
                                 isinstance(v, str) else v for a, v in
                                 kb.facts}

        # pprint(example['flat_state'])

        if label not in self.skills:
            self.skills[label] = {}

        explainations = []
        secondary_explainations = []

        # the base explaination (the constants)
        input_args = tuple(sorted([arg for arg in inputs]))
        sai = ('sai', selection, action, *[inputs[a] for a in input_args])

        # Need to do stuff with features here too.

        # used for grounding out plans, don't need to build up each time.
        # print(functionsets[self.action_set])
        kb = FoPlanner([(self.ground(a),
                         example['flat_state'][a].replace('?', 'QM') if
                         isinstance(example['flat_state'][a], str) else
                         example['flat_state'][a])
                        for a in example['flat_state']],
                       functionsets[self.action_set])
        kb.fc_infer(depth=search_depth, epsilon=epsilon)
        # FACTS AFTER USING FUNCTIONS.
        # pprint(kb.facts)

        for exp, iargs in self.skills[label]:
            # kb = FoPlanner([(self.ground(a),
            #                  example['flat_state'][a].replace('?', 'QM') if
            #                  isinstance(example['flat_state'][a], str) else
            #                  example['flat_state'][a])
            #                 for a in example['flat_state']],
            #                functionsets[self.action_set])
            for m in self.explains_sai(kb, exp, sai):
                # print("COVERED", exp, m)

                # Need to check if it would have been actully generated
                # under where and when.

                r_exp = self.unground(list(rename_flat({exp: True}, m))[0])

                args = self.get_vars(exp)

                if len(args) != len(m):
                    # print("EXP not same length")
                    continue

                grounded = True
                for ele in m:
                    if not isinstance(m[ele], str):
                        grounded = False
                        break
                if not grounded:
                    # print("Pattern not fully grounded")
                    continue

                # foa_vmapping = {field: '?foa%s' % j
                #                 for j, field in enumerate(args)}
                # foa_mapping = {field: 'foa%s' % j for j, field in
                #                enumerate(args)}

                t = tuple([m["?foa%s" % i].replace("QM", "?") for i in
                           range(len(m))])

                if len(t) != len(set(t)):
                    # print("TWO VARS BOUND TO SAME")
                    continue

                secondary_explainations.append(r_exp)

                # print("This is my T:", t)

                skill_where = self.skills[label][(exp, iargs)]['where']
                if not skill_where.check_match(t, example['flat_state']):
                    continue

                # print("####### SUCCESSFUL WHERE MATCH########")

                # x = rename_flat(example['flat_state'], foa_mapping)
                # c = self.skills[label][(exp, iargs)]['when'].categorize(x)
                # if not c.predict('correct'):
                #     continue

                # print("ADDING", r_exp)
                explainations.append(r_exp)

        if len(explainations) == 0 and len(secondary_explainations) > 0:
            explainations.append(choice(secondary_explainations))
            # explainations.append(secondary_explanation)

        elif len(explainations) == 0:
            # kb = FoPlanner([(self.ground(a),
            #                  example['flat_state'][a].replace('?', 'QM') if
            #                  isinstance(example['flat_state'][a], str) else
            #                  example['flat_state'][a])
            #                 for a in example['flat_state']],
            #                functionsets[self.action_set])

            selection_exp = selection
            for sel_match in kb.fc_query([('?selection', selection)],
                                         max_depth=0,
                                         epsilon=epsilon):
                selection_exp = sel_match['?selection']
                break

            input_exps = []

            for a in input_args:
                iv = inputs[a]
                # kb = FoPlanner([(self.ground(a),
                #         example['flat_state'][a].replace('?', 'QM') if
                #         isinstance(example['flat_state'][a], str) else
                #         example['flat_state'][a])
                #        for a in example['flat_state']],
                # functionsets[self.action_set])
                input_exp = iv
                # print('trying to explain', [((a, '?input'), iv)])

                # TODO not sure what the best approach is for choosing among
                # the possible explanations. Perhaps we should choose more than
                # one. Maybe the shortest (less deep).

                # f = False
                possible = []
                for iv_m in kb.fc_query([((a, '?input'), iv)],
                                        max_depth=0,
                                        epsilon=epsilon):

                    # input_exp = (a, iv_m['?input'])
                    possible.append((a, iv_m['?input']))
                    # print("FOUND!", input_exp)
                    # f = True
                    # break

                possible = [(self.compute_exp_depth(p), random(), p) for p in
                            possible]
                possible.sort()
                # print("FOUND!")
                # pprint(possible)

                if len(possible) > 0:
                    _, _, input_exp = possible[0]
                    # input_exp = choice(possible)

                # if not f:
                #     print()
                #     print("FAILED TO EXPLAIN INPUT PRINTING GOAL AND FACTS")
                #     print("GOAL:", ((a, '?input'), iv))

                #     for f in kb.facts:
                #         if f[0][0] == 'value':
                #             print(f)
                #     from time import sleep
                #     sleep(30)

                #     # pprint(kb.facts)

                input_exps.append(input_exp)

            explainations.append(self.unground(('sai', selection_exp, action,
                                                *input_exps)))

        for exp in explainations:
            args = self.get_vars(exp)
            foa_vmapping = {field: '?foa%s' % j
                            for j, field in enumerate(args)}
            foa_mapping = {field: 'foa%s' % j for j, field in enumerate(args)}
            x = rename_flat({exp: True}, foa_vmapping)
            r_exp = (list(x)[0], input_args)
            # r_exp = self.replace_vars(exp)
            # print("REPLACED")
            # print(exp)
            # print(r_exp)

            if r_exp not in self.skills[label]:
                # mg_h = self.extract_mg_h(r_exp[0])

                if self.action_set == "tutor knowledge":
                    constraints = self.generate_tutor_constraints(r_exp[0])
                else:
                    constraints = self.extract_mg_h(r_exp[0])

                # print("ACTIONSET")
                # print(self.action_set)

                # print("SAI")
                # print(r_exp[0])

                print("CONSTRAINTS")
                print(constraints)

                w_args = tuple(['?foa%s' % j for j, _ in enumerate(args)])

                self.skills[label][r_exp] = {}
                where_inst = self.where(args=w_args, constraints=constraints)
                self.skills[label][r_exp]['where'] = where_inst
                # initial_h=mg_h)
                self.skills[label][r_exp]['when'] = when_learners[self.when]()

            # print('where learning for ', exp)
            self.skills[label][r_exp]['where'].ifit(args,
                                                    example['flat_state'],
                                                    example['correct'])
            # print('done where learning')

            # TODO
            # Need to add computed features.
            # need to rename example with foa's that are not variables
            x = rename_flat(example['flat_state'], foa_mapping)
            # x['correct'] = example['correct']

            # print('ifitting')
            # pprint(x)
            # self.skills[label][r_exp]['when'].ifit(x)
            self.skills[label][r_exp]['when'].ifit(x, example['correct'])
Beispiel #8
0
              (('x', ('pos','check3')),3),
              (('y', ('pos','check3')),1),

              (('x', ('pos','check4')),3),
              (('y', ('pos','check4')),3),

              ]


    # kb = FoPlanner(facts, [string_subtract_rule])
    # kb.fc_infer()
    # print(kb.facts)

    # facts = [(('value', 'x'), '17'),
    #          (('value', 'y'), '7')]
    kb = FoPlanner(facts, rb_rules)
    from pprint import pprint
    

    print('X')
    i = 0
    for sol in kb.fc_query([(('x', '?a'),3)], 2):
      if i % 5 == 0:
        pprint(sol)
      if i > 5 * 10:
        break
      i += 1


    print('Y')
    i = 0