def _is_action_valid_sim(self, string: str, observable_object_ids):

        script = read_script_from_string(string)

        valid = True
        for object_and_id in script.obtain_objects():
            id = object_and_id[1]
            if id not in observable_object_ids:
                valid = False
                break

        return valid
    def _is_action_valid(self, string: str, char_index):

        script = read_script_from_string(string)

        valid = True
        for object_and_id in script.obtain_objects():
            id = object_and_id[1]
            if id not in self.observable_object_ids_n[char_index]:
                valid = False
                break

        return valid
def render_script(comm, script, init_graph, scene_num, render_args):
    comm.reset(scene_num)
    if type(script) == list:
        script_content = scripts.read_script_from_list_string(script)
    else:
        script_content = scripts.read_script_from_string(script)

    script_content, _ = check_programs.modify_objects_unity2script(
        helper, script_content)
    success, message = comm.expand_scene(init_graph)

    if type(message) != dict:
        comm.reset()
        return {
            'success_expand': False,
            'message': ('There was an error expanding the scene.', message)
        }
    else:
        objects_missing = obtain_objects_from_message(message)
        objects_script = [
            x[0].replace('_', '') for x in script_content.obtain_objects()
        ]
        intersection_objects = list(
            set(objects_script).intersection(objects_missing))
        message_missing = 'Some objects appearing in the script were not properly initialized'
        if len(intersection_objects) > 0:
            return {
                'succes_expand': False,
                'message': (message_missing, intersection_objects)
            }
        else:
            render_args[
                'skip_execution'] = render_args['image_synthesis'] is None
            success, message_exec = comm.render_script(script, **render_args)

            if success:
                return {'success_expand': True, 'success_exec': True}
            else:
                return {
                    'success_expand': True,
                    'success_exec': False,
                    'message': (message_exec, None)
                }
示例#4
0
def check_executability(input):

    script, graph_dict = input
    if len(script.split(', ')) == 1:
        final_state = graph_dict
        return True, True, final_state

    string = modify_script(script)

    able_to_be_parsed = False
    able_to_be_executed = False
    try:
        script = read_script_from_string(string)
        able_to_be_parsed = True
    except ScriptParseException:
        return able_to_be_parsed, able_to_be_executed, None

    graph = EnvironmentGraph(graph_dict)
    name_equivalence = utils.load_name_equivalence()
    executor = ScriptExecutor(graph, name_equivalence)
    try:
        executable, final_state, _ = executor.execute(script)
    except AttributeError:
        print("Attribute error")
        print("Program:")
        programs = string.split(', ')
        for p in programs:
            print(p)
        return able_to_be_parsed, able_to_be_executed, None
    except:
        print("Unexpected error:", sys.exc_info()[0])
        print("Program:")
        programs = string.split(', ')
        for p in programs:
            print(p)
        return able_to_be_parsed, able_to_be_executed, None

    if executable:
        able_to_be_executed = True
        return able_to_be_parsed, able_to_be_executed, final_state.to_dict()
    else:
        return able_to_be_parsed, able_to_be_executed, None
    def transition(self, vh_state, scripts, do_assert=False):
        # print(scripts, self.observable_object_ids_n[0])
        if do_assert:
            if self.pomdp:
                for i in range(self.n_chars):
                    observable_nodes = self._mask_state(vh_state.to_dict(),
                                                        i)['nodes']
                    observable_object_ids = [
                        node['id'] for node in observable_nodes
                    ]
                    assert self._is_action_valid_sim(scripts.get(i),
                                                     observable_object_ids)

        for i in range(self.n_chars):
            script = read_script_from_string(scripts.get(i, ""))
            succeed, next_vh_state = self.executor_n[i].execute_one_step(
                script, vh_state)

        # state = next_vh_state.to_dict()
        return next_vh_state
    def get_action_space(self,
                         vh_state=None,
                         char_index=0,
                         action=None,
                         obj1=None,
                         obj2=None,
                         structured_actions=False):
        # TODO: this could probably just go into virtualhome

        if vh_state is None:
            vh_state = self.vh_state
            nodes = self.observable_state_n[char_index]['nodes']
        else:
            nodes = self._mask_state(vh_state.to_dict(), char_index)['nodes']
        node_ids = [x['id'] for x in nodes]

        action_executors = self.executor_n[char_index]._action_executors

        if obj1 is not None and obj1['id'] not in node_ids: return []

        action_list = []
        action_candidates = self.actions if action is None else [action]
        action_list_sep = []

        for action in action_candidates:
            curr_action = Action[action.upper()]
            num_params = curr_action.value[1]
            objects = [[] for _ in range(num_params)]
            for param in range(num_params):
                properties_params = curr_action.value[2][param]
                if param == 0:
                    node_candidates = nodes if obj1 not in nodes else [obj1]
                elif param == 1:
                    node_candidates = nodes if obj2 not in nodes else [obj2]
                else:
                    node_candidates = nodes
                # if param == 0:
                #     node_candidates = nodes if obj1 is None else [obj1]
                # elif param == 1:
                #     node_candidates = nodes if obj2 is None else [obj2]
                # else:
                #     node_candidates = nodes

                # remove character from candidates
                node_candidates = [
                    x for x in node_candidates
                    if x['class_name'] != 'character'
                ]

                # if obj1 is not None and obj1['id'] == 2038:
                #     print('node candidates:', [node['id'] for node in node_candidates])

                for node in node_candidates:
                    if (len(properties_params) == 0 or len(
                            set(node['properties']).intersection(
                                properties_params)) > 0):
                        objects[param].append(node)

            if any([len(x) == 0 for x in objects]):
                continue
            prod = list(itertools.product(*objects))
            for obj_candidates in prod:
                obj_cand_list = list(obj_candidates)
                string_instr = self.obtain_formatted_action(
                    action, obj_cand_list)
                action_list_tuple = [action] + obj_cand_list
                if action in ['Walk', 'Find', 'Run']:
                    succeed = True
                else:
                    script = read_script_from_string(string_instr)
                    # This fails, it is modifyng the graph
                    succeed = self.executor_n[char_index].check_one_step(
                        script, vh_state)
                    self.executor_n[char_index].info = ExecutionInfo()
                if succeed:
                    action_list.append(string_instr.lower())
                    action_list_sep.append(action_list_tuple)

        if structured_actions:
            return action_list_sep
        else:
            return action_list
    def step(self, scripts):
        obs_n = []
        info_n = {'n': []}
        reward_n = []

        if self.pomdp:
            for i in range(self.n_chars):
                if i not in scripts:
                    continue
                assert self._is_action_valid(scripts.get(i), i)

        # State transition: Sequentially performing actions
        # TODO: Detect action conflicts
        # convert action to a single action script
        objs_in_use = []
        for i in range(self.n_chars):
            if i not in scripts:
                continue
            script = read_script_from_string(scripts.get(i, ""))

            is_executable, msg = self._is_action_executable(
                script, i, objs_in_use)
            if (is_executable):
                objs_in_use += script.obtain_objects()
                succeed, self.vh_state = self.executor_n[i].execute_one_step(
                    script, self.vh_state)
                info_n['n'].append({
                    "succeed": succeed,
                    "error_message": {
                        i: self.executor_n[i].info.get_error_string()
                        for i in range(self.n_chars)
                    }
                })
            else:
                info_n['n'].append({
                    "succeed": False,
                    "error_message": {
                        i: msg
                    }
                })

        state = self.vh_state.to_dict()
        self.state = state

        for i in range(self.n_chars):
            observable_state = self._mask_state(state,
                                                i) if self.pomdp else state
            self.observable_state_n[i] = observable_state
            self.observable_object_ids_n[i] = [
                node["id"] for node in observable_state["nodes"]
            ]
            obs_n.append(observable_state)
            # Reward Calculation

            # progress = self.tasks_n[i].measure_progress(self.observable_state_n[i], i)
            #progress_per_task = [task.measure_progress(self.observable_state_n[i], i) for task in self.tasks_n[i]]
            #progress = sum(progress_per_task) / float(len(progress_per_task))
            progress = 0
            reward_n.append(progress - self.prev_progress_n[i])
            self.prev_progress_n[i] = progress

            # if abs(progress - 1.0) < 1e-6:
            #     info_n['n'][i].update({'terminate': True})
            # else:
            #     info_n['n'][i].update({'terminate': False})

        # Information

        return reward_n, obs_n, info_n