示例#1
0
def call_planner_sp(planner, domain, problem, args, pwd, verbose):
    '''
    Call an external deterministic planner in single processing.
    Arguments:
    @domain : path to a given domain 
    @problem : path to a given problem 
    @planner : the name of the external planner  
    @args : the default args of the external planner 
    @pwd : the current working directory 
    @verbose : if True, prints statistics before returning
    '''
    ## FF planner ##
    if 'ff' in planner.lower():
        return call_ff(domain, problem, args, pwd, verbose)

    ## Madagascar (M) planner ##
    elif 'm' in planner.lower():
        return call_m(domain, problem, args, pwd, verbose)

    ## PROBE planner ##
    elif 'probe' in planner.lower():
        return call_probe(domain, problem, args, pwd, verbose)

    ## optic-clp planner ##
    elif 'optic-clp' in planner.lower() or 'optic' in planner.lower():
        return call_optic_clp(domain, problem, args, pwd, verbose)

    ## optic-clp planner ##
    elif 'vhpop' in planner.lower():
        return call_vhpop(domain, problem, args, pwd, verbose)

    ## lpg-td planner ##
    elif 'lpg-td' in planner.lower():
        return call_lpg_td(domain, problem, args, pwd, verbose)

    ## lpg-td planner ##
    elif 'lpg' in planner.lower():
        return call_lpg(domain, problem, args, pwd, verbose)

    ## lpg-td planner ##
    elif 'fd' in planner.lower():
        return call_fd(domain, problem, args, pwd, verbose)

    ## no planner ##
    print(color.fg_red("\n[There is not yet a function for parsing the outputs of '{0}'!]\n".format(planner)))
    # exit()
    return -1
示例#2
0
def json_ma_plan(policy, agents=[], full=False, verbose=False):
    '''
    Convert given plan into a concurrent plan for execution by multi-robot.
    The output is partial parallel plan iff the given plan is partial-order.
    '''
    # get the first pre-order path
    try:
        if full:
            path = policy.plan()
        else:
            path = policy.get_paths(policy.plan())[0]
    except:
        return None

    if verbose:
        print(color.fg_red('[EXPERIMENTAL JSON PLAN!]'))
        print(
            color.fg_red(
                '[APPLIED ONLY TO THE FIRST PRE-ORDER PATH OF THE PLAN]'))
        policy.print_plan(path)

    # get concurrent executions in concurrent clusters
    concurrent_subplans_lists = concurrent_subplans(policy, path, agents)

    main_list = OrderedDict()

    # temporary: ignore outcomes of every step in subplans
    for key, subplans in concurrent_subplans_lists.items():
        new_subplans = []
        for subplan in subplans:
            new_subplan = OrderedDict()
            for k, (actions, outcomes) in subplan.items():
                new_subplan[k] = list(actions)
            new_subplans.append(new_subplan)
        main_list[key] = new_subplans

    plan_json = OrderedDict()
    action_descriptions_json = OrderedDict()
    plan_json['main'] = OrderedDict({'list': [], 'ordering': 'total'})

    for n, (key, subplans) in enumerate(main_list.items()):
        # -------------------------------------------------------------------------------
        if len(subplans) == 1:  # there is only one parallel subplan
            # ----------------------------------------------------
            if len(subplans[0]) == 1:  # there is only one step in this subplan
                # ----------------------------------------------------
                if len(subplans[0]
                       [key]) == 1:  # there is only one action in this step
                    # make a reference to action (key+i)
                    action_ref = 'action_{}'.format(n)
                    action_ref = '_'.join(subplans[0][key][0].sig)
                    # add ref to main list of the plan
                    plan_json['main']['list'].append(action_ref)
                    # add ref and its description into the action_descriptions_json
                    action_descriptions_json[action_ref] = action_json(
                        subplans[0][key][0])
                # ----------------------------------------------------
                else:  # there are more actions in this step
                    # make a reference to subplan (n)
                    subplan_ref = 'subplan_{}'.format(n)
                    plan_json['main']['list'].append(subplan_ref)
                    plan_json[subplan_ref] = OrderedDict({
                        'list': [],
                        'ordering': 'partial'
                    })
                    for i, action in enumerate(subplans[0][key]):
                        # make a reference to action (n+i+j)
                        action_ref = 'action_{}_{}'.format(n, i)
                        action_ref = '_'.join(action.sig)
                        # add ref to main list of the plan
                        plan_json[subplan_ref]['list'].append(action_ref)
                        # add ref and its description into the action_descriptions_json
                        action_descriptions_json[action_ref] = action_json(
                            action)
            # ----------------------------------------------------
            else:  # there are more steps in this subplan
                # make a reference to subplan (n)
                subplan_ref = 'subplan_{}'.format(n)
                plan_json['main']['list'].append(subplan_ref)
                plan_json[subplan_ref] = OrderedDict({
                    'list': [],
                    'ordering': 'total'
                })
                for i, (k, step) in enumerate(subplans[0].items()):
                    # ----------------------------------------------------
                    if len(step) == 1:  # there is only one action in this step
                        # make a reference to action (key+i)
                        action_ref = 'action_{}_{}'.format(n, i)
                        action_ref = '_'.join(step[0].sig)
                        # add ref to main list of the plan
                        plan_json[subplan_ref]['list'].append(action_ref)
                        # add ref and its description into the action_descriptions_json
                        action_descriptions_json[action_ref] = action_json(
                            step[0])
                    # ----------------------------------------------------
                    else:  # there are more actions in this step
                        # make a reference to subplan (n)
                        subsubplan_ref = 'subplan_{}_{}'.format(n, i)
                        plan_json[subplan_ref]['list'].append(subsubplan_ref)
                        plan_json[subsubplan_ref] = OrderedDict({
                            'list': [],
                            'ordering':
                            'partial'
                        })
                        for j, action in enumerate(step):
                            # make a reference to action (n+i+j)
                            action_ref = 'action_{}_{}_{}'.format(n, i, j)
                            action_ref = '_'.join(action.sig)
                            # add ref to main list of the plan
                            plan_json[subsubplan_ref]['list'].append(
                                action_ref)
                            # add ref and its description into the action_descriptions_json
                            action_descriptions_json[action_ref] = action_json(
                                action)
        # -------------------------------------------------------------------------------
        else:  # there are more parallel subplans
            # make a reference to subplan (n)
            subplan_ref = 'subplan_{}'.format(n)
            plan_json['main']['list'].append(subplan_ref)
            plan_json[subplan_ref] = OrderedDict({
                'list': [],
                'ordering': 'partial'
            })
            for i, subplan in enumerate(subplans):
                # ----------------------------------------------------
                if len(subplan) == 1:  # there is one step in this subplan
                    # ----------------------------------------------------
                    if len(list(subplan.values())
                           [0]) == 1:  # there is only one action in this step
                        # make a reference to action (key+i)
                        action_ref = 'action_{}_{}'.format(n, i)
                        action_ref = '_'.join(list(subplan.values())[0][0].sig)
                        # add ref to main list of the plan
                        plan_json[subplan_ref]['list'].append(action_ref)
                        # add ref and its description into the action_descriptions_json
                        action_descriptions_json[action_ref] = action_json(
                            list(subplan.values())[0][0])
                    # ----------------------------------------------------
                    else:  # there are more actions in this step
                        # make a reference to subplan (n)
                        subsubplan_ref = 'subplan_{}_{}'.format(n, i)
                        plan_json[subplan_ref]['list'].append(subsubplan_ref)
                        plan_json[subsubplan_ref] = OrderedDict({
                            'list': [],
                            'ordering':
                            'partial'
                        })
                        for j, action in enumerate(list(subplan.values())[0]):
                            # make a reference to action (n+i+j)
                            action_ref = 'action_{}_{}_{}'.format(n, i, j)
                            action_ref = '_'.join(action.sig)
                            # add ref to main list of the plan
                            plan_json[subsubplan_ref]['list'].append(
                                action_ref)
                            # add ref and its description into the action_descriptions_json
                            action_descriptions_json[action_ref] = action_json(
                                action)
                # ----------------------------------------------------
                else:  # there are more steps in this subplan
                    # make a reference to subplan (n+i)
                    subsubplan_ref = 'subplan_{}_{}'.format(n, i)
                    plan_json[subplan_ref]['list'].append(subsubplan_ref)
                    plan_json[subsubplan_ref] = OrderedDict({
                        'list': [],
                        'ordering': 'total'
                    })
                    for j, (k, step) in enumerate(subplan.items()):
                        # ----------------------------------------------------
                        if len(step
                               ) == 1:  # there is only one action in this step
                            # make a reference to action (key+i)
                            action_ref = 'action_{}_{}_{}'.format(n, i, j)
                            action_ref = '_'.join(step[0].sig)
                            # add ref to main list of the plan
                            plan_json[subsubplan_ref]['list'].append(
                                action_ref)
                            # add ref and its description into the action_descriptions_json
                            action_descriptions_json[action_ref] = action_json(
                                step[0])
                        # ----------------------------------------------------
                        else:  # there are more actions in this step
                            # make a reference to subplan (n)
                            subsubsubplan_ref = 'subplan_{}_{}_{}'.format(
                                n, i, j)
                            plan_json[subsubplan_ref]['list'].append(
                                subsubsubplan_ref)
                            plan_json[subsubsubplan_ref] = OrderedDict({
                                'list': [],
                                'ordering':
                                'partial'
                            })
                            for l, action in enumerate(step):
                                # make a reference to action (n+i+j)
                                action_ref = 'action_{}_{}_{}_{}'.format(
                                    n, i, j, l)
                                action_ref = '_'.join(action.sig)
                                # add ref to main list of the plan
                                plan_json[subsubsubplan_ref]['list'].append(
                                    action_ref)
                                # add ref and its description into the action_descriptions_json
                                action_descriptions_json[
                                    action_ref] = action_json(action)

    plan_json['actions'] = list(action_descriptions_json.keys())

    # make json files for plan and actions descriptions
    plan_json_str = json.dumps(plan_json, indent=4)
    action_json_str = json.dumps(action_descriptions_json, indent=4)

    if policy.problem_file is not None:
        problem_file = policy.problem_file
    else:
        problem_file = policy.domain_file

    plan_json_file = '{}.plan.json'.format(os.path.splitext(problem_file)[0])
    actions_json_file = '{}.actions.json'.format(
        os.path.splitext(problem_file)[0])

    with open(plan_json_file, 'w') as outfile:
        json.dump(json.loads(plan_json_str, object_pairs_hook=OrderedDict),
                  outfile,
                  sort_keys=False,
                  indent=4)

    with open(actions_json_file, 'w') as outfile:
        json.dump(json.loads(action_json_str, object_pairs_hook=OrderedDict),
                  outfile,
                  sort_keys=False,
                  indent=4)

    return plan_json_file, actions_json_file
示例#3
0
def Plan(planners, domain, problem, pwd, verbose):
    '''
    calls multiple planners to solve a given problem and as soon as 
    the first planner finds a plan, terminates all other planners and returns 
    '''
    try:
        # if only one planner then no need multiprocessing
        if len(set(planners)) == 1:
            plan = call_planner_sp(planners[0], domain, problem, args_profiles[planners[0]][0], pwd, verbose)
            if plan == -1:
                if not verbose: 
                    print(color.fg_red('[some error by external planner -- run again with parameter \'-v 2\']'))
                sys.exit(0)
            return plan

        # create a shared Queue to store the output plan
        returned_plan = Queue()

        # a shared Array to store the failed planners
        failed_planners = Array('I', len(planners))

        # store the running processes
        process_lst = []

        # run in multiprocessing
        for pidx, planner in enumerate(planners):
            # proc = Process(target=call_planner_mp, \
            #     args=(planner, domain, problem, args_profiles[planner][0], pwd, returned_plan, failed_planners, verbose),
            #     daemon=True)
            proc = Process(target=call_planner_mp, \
                args=(planner, domain, problem, args_profiles[planner][0], pwd, returned_plan, failed_planners, verbose))
            proc.daemon = True
            process_lst.append(proc)
            proc.start()

        # wait until one process completes and returns a plan
        while returned_plan.empty():
            # if all processes (planners) failed to solve the problem
            if sum(failed_planners) == len(planners):
                print(color.fg_red('[error by all external planners: run with \'-v 2\''))
                sys.exit(0)

        # kill running planners (subprocesses) if they are running
        kill_jobs(pwd, planners)

        # make sure processes terminate gracefully
        while process_lst:
            proc = process_lst.pop()
            while proc.is_alive():
                try:
                    proc.terminate()
                    proc.join()
                except: pass

        # return the plan 
        return returned_plan.get()
    # make sure all processes are terminated when KeyboardInterrupt received
    except KeyboardInterrupt:
        if len(planners) > 1:
            kill_jobs(pwd, planners)
            print(color.bg_red('ALL JOBS TERMINATED'))
        raise
示例#4
0
def call_optic_clp(domain, problem, args='-b -N', pwd='/tmp', verbose=0):
    '''
    Call an external planner
    @domain : path to a given domain 
    @problem : path to a given problem 
    @verbose : if True, prints statistics before returning

    @return plan : the output plan is a list of actions as tuples, 
                   e.g., [[('move_to_grasp', 'arm1', 'box1', 'base1', 'box2'), ('move_to_grasp', 'arm2', 'box2', 'cap1', 'box1')], 
                          [('vacuum_object', 'arm2', 'cap1', 'box1'), ('vacuum_object', 'arm1', 'base1', 'box2')],
                          ...]
    '''

    cmd = 'timeout 1800 ./planners/optic-clp {} {} {} & echo $! >> {}/optic-clp-pid.txt'.format(args, domain, problem, pwd)

    ## call command ##
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
     
    (output, err) = process.communicate()
    # try:
    #     (output, err) = process.communicate(timeout=1800)
    # except subprocess.TimeoutExpired:
    #     if verbose == 2: print(color.fg_red('\n-- planning timeout (30m)'))
    #     return -1

    ## Wait for cmd to terminate. Get return returncode ##
    if process.wait() < 0: return -1

    ## bytes to string ##
    # shell = ''.join(map(chr, output))
    shell = to_str(output)

    if verbose == 2: 
        print(color.fg_voilet('\n-- planner stdout'))
        print(shell)
        if to_str(err):
            print(color.fg_voilet('-- planner stderr'))
            print(to_str(err))

    # Permission denied
    if 'Permission denied' in to_str(err):
        print(to_str(err))
        print(color.fg_voilet('-- run \'chmod +x planners/optic-clp\''))
        return -1

    ## if solution already exists in the problem ##
    if "has to terminate" in to_str(err) \
       or "error while loading shared libraries" in to_str(err) \
       or "Segmentation Fault" in shell:
        # print(color.fg_yellow("[planning failed due to some error in the pddl description]"))
        # print(color.fg_voilet('\n-- planner stdout'))
        # print(shell)
        # if to_str(err):
        #     print(color.fg_voilet('-- planner stderr'))
        #     print(to_str(err))
        # # exit()
        return -1

    ## if problem is unsolvable by EHC remove -b (activate best-first search)
    if "Problem unsolvable by EHC, and best-first search has been disabled" in shell:
        ## calling 'optic-clp' again removing '-b' option ##
        cmd = 'timeout 1800 ./planners/optic-clp -N {0} {1}'.format(domain, problem)
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
        (output, err) = process.communicate()
    # try:
    #     (output, err) = process.communicate(timeout=1800)
    # except subprocess.TimeoutExpired:
    #     if verbose == 2: print(color.fg_red('\n-- planning timeout (30m)'))
    #     return -1
        # shell = ''.join(map(chr, output))
        shell = to_str(output)

    ## if no solution exists try the next domain ##
    if "problem has been deemed unsolvable" in shell or "Problem unsolvable" in shell:
        return None

    ## if no solution exists try the next domain ##
    if "file appear to violate part of the PDDL" in to_str(err) or\
       "problem has been encountered, and the planner has to terminate" in to_str(err):
        if not verbose == 2: 
            print(color.fg_red('[error by external planner: run with \'-v 2\''))
        return None

    ## if solution already exists in the problem ##
    if ("; Plan empty" in shell and "; Plan found" in shell) \
        or "The empty plan is optimal" in shell:
        return list()

    ## refine the output screen and build a plan of actions' signatures ##

    # extract plan from ';<problem_name>' to 'Time:<value>'
    shell = shell[shell.find('; Time'):].strip()

    # split shell into a list of actions and ignore ';<problem_name>'
    shell = shell.split('\n')[1:]
    plan = OrderedDict()

    for action in shell:
        action = re.split('[, ) (]+', action)[:-1]
        plan.setdefault(action[0], []).append(tuple(action[1:]))

    # print(list(plan.values()))
    return list(plan.values())
示例#5
0
def call_planner_mp(planner, domain, problem, args, pwd, returned_plan, failed_planners, verbose):
    '''
    Call an external deterministic planner in multi processing.
    Arguments:
    @domain : path to a given domain 
    @problem : path to a given problem 
    @planner : the name of the external planner 
    @args : the default args of the external planner 
    @pwd : the current working directory 
    @returned_plan : is a shared queue and stores the returned plan for every planner
    @failed_planners : is a shared array and stores the failed result for every planner
    @verbose : if True, prints statistics before returning
    '''
    def return_plan(planner, plan=-1):
        if not plan == -1:
            returned_plan.put(plan)
        else:
            try: failed_planners[sum(failed_planners)] = 1
            except: pass
        return

    ## FF planner ##
    if 'ff' in planner.lower():
        plan = call_ff(domain, problem, args, pwd, verbose)
        return_plan(planner, plan)

    ## Madagascar (M) planner ##
    elif 'm' in planner.lower():
        plan = call_m(domain, problem, args, pwd, verbose)
        return_plan(planner, plan)

    ## PROBE planner ##
    elif 'probe' in planner.lower():
        plan = call_probe(domain, problem, args, pwd, verbose)
        return_plan(planner, plan)

    ## optic-clp planner ##
    elif 'optic-clp' in planner.lower() or 'optic' in planner.lower():
        plan = call_optic_clp(domain, problem, args, pwd, verbose)
        return_plan(planner, plan)

    ## optic-clp planner ##
    elif 'vhpop' in planner.lower():
        plan = call_vhpop(domain, problem, args, pwd, verbose)
        return_plan(planner, plan)

    ## lpg-td planner ##
    elif 'lpg-td' in planner.lower():
        plan = call_lpg_td(domain, problem, args, pwd, verbose)
        return_plan(planner, plan)

    ## lpg-td planner ##
    elif 'lpg' in planner.lower():
        plan = call_lpg(domain, problem, args, pwd, verbose)
        return_plan(planner, plan)

    ## lpg-td planner ##
    elif 'fd' in planner.lower():
        plan = call_fd(domain, problem, args, pwd, verbose)
        return_plan(planner, plan)

    ## no planner ##
    else:
        print(color.fg_red("\n[There is not yet a function for parsing the outputs of '{0}'!]\n".format(planner)))
        return_plan(planner)

    return
示例#6
0
def action_execution_verification(action_msg):

    global args, domain, problem, state, plan, action_ids

    #############################
    ## simulate and execute the plan
    for level, step in plan.items():

        ## if all actions in the plan are visited
        if step == 'GOAL':
            ## check if goal is achieved then terminate planner
            if state.is_true(problem.goals):
                # goal state is achieved
                print(color.fg_voilet('@ GOAL'))
                sub_proc.unregister()
                rospy.signal_shutdown('finished')

        else:
            # unfold step into a tuple of actions and outcomes
            (actions, outcomes) = step

            for action in actions:
                ## find an action matching the received action
                if '_'.join(action.sig) == action_msg.id:

                    # if action was already visited
                    if '_'.join(action.sig) in action_ids: return

                    # add action's id to the visited action_ids
                    action_ids.append('_'.join(action.sig))

                    # check if action succeeded
                    if action_msg.succeed:
                        ## print out succeeded action
                        print(color.fg_yellow(' + ') + str(action))
                        # apply action to the state and update the state
                        state = state.apply(action)

                        ## check if goal is achieved then terminate planner
                        if state.is_true(problem.goals):
                            # goal state is achieved
                            print(color.fg_voilet('@ GOAL'))
                            sub_proc.unregister()
                            rospy.signal_shutdown('finished')
                    else:
                        ## print out failed action
                        print(color.fg_red(' - ') + str(action))
                        for monitor in action_msg.monitors:
                            print(
                                color.fg_red('   ---- {} {}'.format(
                                    monitor.predicate, monitor.arguments[0])))

                        ## update the state with the action violence and make a re-plane
                        ## convert the predicates frozenset to a list and update the state
                        ## i.e., remove ('collision_free', 'left_arm')
                        state_predicates = list(state.predicates)

                        for monitor in action_msg.monitors:
                            if 'collision' in monitor.predicate:
                                if ('collision_free', monitor.arguments[0]
                                    ) in state_predicates:
                                    state_predicates.remove(
                                        ('collision_free',
                                         monitor.arguments[0]))
                                if not ('collision_detected', monitor.
                                        arguments[0]) in state_predicates:
                                    state_predicates.append(
                                        ('collision_detected',
                                         monitor.arguments[0]))
                            elif 'admittance' in monitor.predicate:
                                if ('admittance_free', monitor.arguments[0]
                                    ) in state_predicates:
                                    state_predicates.remove(
                                        ('admittance_free',
                                         monitor.arguments[0]))
                                if not ('admittance_detected', monitor.
                                        arguments[0]) in state_predicates:
                                    state_predicates.append(
                                        ('admittance_detected',
                                         monitor.arguments[0]))

                        ## convert back to frozenset
                        state.predicates = frozenset(state_predicates)

                        #############################
                        ## create a new pddl problem file at /tmp/safe-planner
                        problem_pddl = pddl.pddl(problem, state=state)

                        ## call planner to make an initial policy given the domain, problem and planners
                        (policy, plan, plan_json_file, actions_json_file) = \
                            make_plan(domain = domain, \
                                      problem = problem_pddl, \
                                      planners = args.planners, \
                                      agents = args.agents, \
                                      temporal_actions = args.temporal_actions, \
                                      rank=False, \
                                      verbose=args.verbose)

                        #############################
                        ## call the execution engine giving the initial plan
                        # plan_json_file actions_json_file
                        send_json_plan(plan_json_file, actions_json_file)

                    return
    return
示例#7
0
def main():
    ## parse arguments
    parser = parse()
    args = parser.parse_args()
    if args.domain == None:
        parser.print_help()
        sys.exit()

    ## make a policy given domain and problem
    policy = planner.Planner(args.domain, args.problem, args.planners,
                             args.safe_planner, args.rank, args.all_outcome,
                             args.verbose)

    ## transform the produced policy into a contingency plan
    plan = policy.plan()

    ## print out the plan in a readable form
    policy.print_plan(del_effect_inc=True, det_effect_inc=False)

    ## print out sub-paths in the plan
    if args.path:
        paths = policy.get_paths(plan)
        policy.print_paths(paths=paths, del_effect_inc=True)
        # for path in paths:
        #     policy.print_plan(plan=path, del_effect_inc=True)
        ## generate graphs of sub-paths too
        if args.dot:
            for i, path in enumerate(paths):
                dot_file = dot_plan.gen_dot_plan(plan=path)
                print(
                    color.fg_yellow('-- path{} dot file: ').format(str(i +
                                                                       1)) +
                    dot_file)
                # os.system('xdot %s &' % dot_file)
            dot_file = dot_plan.gen_dot_plan(plan=paths[0])
            # os.system('xdot %s &' % dot_file)
            print('')

    ## generate a graph of the policy as a dot file in graphviz
    if args.dot:
        plan = policy.plan(tree=True)
        dot_file = dot_plan.gen_dot_plan(plan=plan,
                                         del_effect=True,
                                         domain_file=args.domain,
                                         problem_file=args.problem)
        print(color.fg_yellow('-- dot file: ') + dot_file + '\n')
        # os.system('xdot %s &' % dot_file)
        # os.system('dot -T pdf %s > %s.pdf &' % (dot_file, dot_file))
        # os.system('evince %s.pdf &' % dot_file)

    ## transform the policy into a json file
    if args.json:
        import json_ma_plan
        import dot_ma_plan
        json_output = json_ma_plan.json_ma_plan(policy, verbose=args.verbose)
        if json_output is not None:
            plan_json_file, actions_json_file = json_output
            print(
                color.fg_yellow('-- plan_json_file:') + plan_json_file +
                color.fg_red(' [EXPERIMENTAL!]'))
            print(
                color.fg_yellow('-- actions_json_file:') + actions_json_file +
                color.fg_red(' [EXPERIMENTAL!]'))
            os.system('cd lua && lua json_multiagent_plan.lua ../%s &' %
                      plan_json_file)
            print(
                color.fg_yellow('-- plan_json_dot_file:') +
                ('%s.dot' % plan_json_file) + color.fg_red(' [EXPERIMENTAL!]'))
            # transform the plan into a parallel plan
            dot_file, tred_dot_file = dot_ma_plan.parallel_plan(
                policy, verbose=args.verbose)
            print(color.fg_yellow('-- graphviz file: ') + dot_file)
            print(color.fg_yellow('-- transitive reduction: ') + tred_dot_file)
            # os.system('xdot %s.dot &' % plan_json_file)

    ## transform the policy into a json file
    if args.json:
        import json_plan
        plan = policy.plan(tree=False)
        json_file, plan_json = json_plan.json_plan(policy)
        print(
            color.fg_yellow('\n-- json file: ') + json_file +
            color.fg_red(' [EXPERIMENTAL!]'))
        print(
            color.fg_yellow('-- try: ') + 'lua json_plan.lua ' + json_file +
            color.fg_red(' [EXPERIMENTAL!]\n'))

    if args.store:
        stat_file = policy.log_performance(plan)
        print(color.fg_yellow('-- planner performance: ') + stat_file)

    # print out resulting info
    if args.problem is not None:
        print('\nPlanning domain: %s' % policy.domain_file)
        print('Planning problem: %s' % policy.problem_file)
        print('Arguments: %s' % ' '.join(sys.argv[3:]))
    else:
        print('Planning problem: %s' % policy.domain_file)
        print('Arguments: %s' % ' '.join(sys.argv[2:]))
    print('Policy length: %i' % len(policy.policy))
    print('Plan length: %i' % (len(plan) - 1))
    print('Compilation time: %.3f s' % policy.compilation_time)
    print('Planning time: %.3f s' % policy.planning_time)
    print('Planning iterations (all-outcome): %i' %
          policy.alloutcome_planning_call)
    print('Total number of replannings (single-outcome): %i' %
          policy.singleoutcome_planning_call)
    print('Total number of unsolvable states: %i' %
          len(policy.unsolvable_states))