def __init__(self,
                 mdpsim_path='mdpsim-1.23/mdpsim',
                 mgpt_path='mini-gpt/planner',
                 planner: Planner = Planner.LRTDP,
                 heuristic: Heuristic = Heuristic.FF,
                 port=2323,
                 max_time=10,
                 **kwargs):
        """
        Create a new PDDL planner object
        :param mgpt_path: the path to the mGPT executable
        :param planner: the type of planner to use. Default is LRTDP
        :param heuristic: the heuristic to use. Default is FF
        :param port: the port to run mdpsim on. It can be anything that is free
        :param max_time: the maximum time in seconds the planner is allowed. Default is 10
        :param kwargs: allows user to specify additional mGPT settings
        """
        if not exists(mgpt_path):
            raise ValueError("Could not find executable file at {}".format(mgpt_path))
        if not exists(mdpsim_path):
            raise ValueError("Could not find executable file at {}".format(mdpsim_path))

        # for item in kwargs:
        #     if item != 'wsl' and item not in 'acdeimnprswz':
        #         raise ValueError("Invalid argument {} for mGPT".format(item))

        self._mdpsim_port = port
        self._use_wsl = kwargs.get('wsl', False)  # use the windows subsystem for linux?
        self._mdpsim_path = mdpsim_path
        self._planner_path = mgpt_path
        self._planner = planner
        self._heuristic = heuristic
        self._max_time = max_time
Exemple #2
0
    def _create_temp_file(self,
                          domain: Any,
                          problem: Any,
                          verbose=False) -> Tuple[str, str]:

        name = next(tempfile._get_candidate_names())
        show("Generating temp PDDL file {}".format(name), verbose)
        if isinstance(domain, str):

            # it's a path to a file!
            if not exists(domain):
                raise ValueError(
                    "Could not find PDDL file at {}".format(domain))
            if not exists(problem):
                raise ValueError(
                    "Could not find PDDL file at {}".format(problem))

            with open(name, 'w') as temp_file, open(domain,
                                                    'r') as domain_file, open(
                                                        problem,
                                                        'r') as problem_file:
                temp_file.write('{}\n\n{}'.format(domain_file.read(),
                                                  problem_file.read()))
            problem_name = self._extract_problem_name(problem)
            return name, problem_name

        else:

            # it's the objects!
            with open(name, 'w') as temp_file:
                temp_file.write('{}\n\n{}'.format(domain, problem))

            return name, problem.name
    def find_plan(self, domain: Any, problem: Any, verbose=False) -> Tuple[bool, Any]:
        """
        Given a path to the PDDL domain and problem file, determine if a plan can be found. We do this by spinning up
        mdpsim, then running mGPT, then shutting it all down!
        :param domain: the domain file
        :param problem: the problem file
        :param verbose: the verbosity level
        :return: the first boolean represents whether the files were valid PDDL, the second represents whether a plan
        could be found and a list of output from the planner
        """

        # first, create a new file that has both the domain and problem in it.
        temp_name, problem_name = self._create_temp_file(domain, problem, verbose=verbose)

        command = ('wsl' if self._use_wsl else 'bash')
        p = None
        p2 = None

        try:
            show("Starting mdpsim...", verbose)
            # now run mdpsim with the temp file as input
            p = Popen(
                [command,
                 self._mdpsim_path,
                 '--port',
                 '{}'.format(self._mdpsim_port),
                 '--log-dir=/dev/null',
                 '--warnings=1',
                 temp_name
                 ],
                stdout=PIPE, stderr=PIPE, universal_newlines=True
            )

            # give it a second necessary?
            sleep(1)

            if p.poll():
                # it finished! something bad must have happened
                std_out, std_err = p.communicate()
                if p.returncode != 0:
                    error = self._extract_error(std_err, domain, problem)
                    show("mdpsim failed to start with error: {}".format(error), verbose)
                    return False, error

            show("mdpsim started!", verbose)

            show("Starting mGPT...", verbose)
            # it's running well! now start planner
            p2 = Popen(
                [command,
                 self._planner_path,
                 '-v',
                 '100',
                 '-p',
                 self._planner.value,
                 '-h',
                 self._heuristic.value,
                 'localhost:{}'.format(self._mdpsim_port),
                 temp_name,
                 problem_name
                 ],
                stdout=PIPE, stderr=PIPE, universal_newlines=True
            )
            show("mGPT started! Waiting for output...", verbose)

            try:
                std_out, std_err = p2.communicate(timeout=self._max_time)
                output = PlanOutput(std_out)
                return True, output
            except subprocess.TimeoutExpired:
                return False, 'Timeout!'
        finally:
            os.remove(temp_name)
            if exists('last_id'):
                os.remove('last_id')  # created by the planner and mdpsim
            if p:
                p.terminate()
            if p2:
                p2.terminate()