示例#1
0
class primitive:  # pylint: disable=R0903,C0103
    """Namespace for primitive actions and their corresponding models"""
    alg_formulas = [[a] for a in cube.ACTIONS]
    actions = alg_formulas
    models = [
        cube.Cube().apply(sequence=a).summarize_effects() for a in actions
    ]
示例#2
0
class expert:  # pylint: disable=R0903,C0103
    """Namespace for expert macro-actions and their corresponding models"""
    alg_formulas = [
        formula.R_PERMUTATION,
        formula.SWAP_3_EDGES_FACE,
        formula.SWAP_3_EDGES_MID,
        formula.SWAP_3_CORNERS,
        formula.ORIENT_2_EDGES,
        formula.ORIENT_2_CORNERS,
    ]
    macros = [
        variation for f in alg_formulas for variation in formula.variations(f)
    ]
    models = [
        cube.Cube().apply(sequence=macro).summarize_effects()
        for macro in macros
    ]
示例#3
0
def load_learned_macros():
    """Load the set of learned macro-actions"""
    results_dir = 'results/macros/cube/'
    filename = results_dir + 'clean_macros.pickle'
    try:
        with open(filename, 'rb') as file:
            _macros = pickle.load(file)
    except FileNotFoundError:
        warnings.warn(
            'Failed to load learned macros from file {}'.format(filename))
        _macros = []

    _models = [
        cube.Cube().apply(sequence=macro).summarize_effects()
        for macro in _macros
    ]

    global learned  # pylint: disable=W0601,C0103
    learned.macros = _macros
    learned.models = _models
示例#4
0
def generate_random_macro_set(seed):
    """Generate a new set of random macro-actions using the given random seed"""
    old_state = pyrandom.getstate()
    pyrandom.seed(seed)
    random_formulas = [
        formula.random_formula(len(alg)) for alg in expert.alg_formulas
    ]
    pyrandom.setstate(old_state)

    _macros = [
        variation for formula_ in random_formulas
        for variation in formula.variations(formula.simplify(formula_))
    ]
    _models = [
        cube.Cube().apply(sequence=macro).summarize_effects()
        for macro in _macros
    ]

    global random  # pylint: disable=W0601,C0103
    random.seed = seed
    random.alg_formulas = random_formulas
    random.macros = _macros
    random.models = _models
示例#5
0
def test():
    """Test search functionality with Cube primitive actions and expert macro-actions"""
    # Set up the scramble
    newcube = cube.Cube()

    # Primitive action search
    print('Running primitive action search...')
    start = copy.deepcopy(newcube)
    start.apply(pattern.SCRAMBLE_1)

    macros_ = macros.primitive.actions
    models = macros.primitive.models

    is_goal = lambda node: node.state == newcube
    heuristic = lambda cube: len(cube.summarize_effects())
    max_transitions = 3e3

    def get_successors(cube_):
        return [(copy.deepcopy(cube_).apply(swap_list=model), macro)
                for (macro, model) in zip(macros_, models)]

    search_results = search.astar(start=start,
                                  is_goal=is_goal,
                                  step_cost=len,
                                  heuristic=heuristic,
                                  get_successors=get_successors,
                                  max_transitions=max_transitions)
    actions = search_results[1]

    testcube = copy.deepcopy(newcube)
    testcube.apply(pattern.SCRAMBLE_1)
    n_starting_errors = len(testcube.summarize_effects())
    for action in actions:
        testcube.apply(action)
    n_remaining_errors_primitive = len(testcube.summarize_effects())
    assert n_remaining_errors_primitive < n_starting_errors

    # Expert macro-action search
    print('Running expert macro-action search...')
    start = copy.deepcopy(newcube)
    start.apply(pattern.SCRAMBLE_1)

    macros_ = macros.primitive.actions + macros.expert.macros
    models = macros.primitive.models + macros.expert.models

    search_results = search.astar(start=start,
                                  is_goal=is_goal,
                                  step_cost=lambda _: 1,
                                  heuristic=heuristic,
                                  get_successors=get_successors,
                                  max_transitions=max_transitions)
    actions = search_results[1]

    testcube = copy.deepcopy(newcube)
    testcube.apply(pattern.SCRAMBLE_1)
    n_starting_errors = len(testcube.summarize_effects())
    for action in actions:
        testcube.apply(action)
    n_remaining_errors_expert = len(testcube.summarize_effects())
    assert n_remaining_errors_expert < n_remaining_errors_primitive

    print('All tests passed.')
示例#6
0
def solve():
    """Instantiate a Rubik's cube and solve with the specified macro-actions and search algorithm"""
    args = parse_args()

    # Set up the scramble
    if args.buchner2018:
        scramble = pattern.buchner2018pattern(args.seed)
    else:
        scramble = pattern.scramble(args.seed)

    start = cube.Cube()
    start.apply(sequence=scramble)
    print('Using scramble: {:03d}'.format(args.seed))
    print(' '.join(scramble))
    start.render()

    if args.random_goal:
        goal = cube.Cube().apply(sequence=pattern.scramble(args.seed + 1000))
        print('Using goal pattern: {:03d}'.format(args.seed + 1000))
        print(' '.join(pattern.scramble(args.seed + 1000)))
    else:
        goal = cube.Cube()

    # Define the macros and models
    if args.macro_type == 'random':
        macros.generate_random_macro_set(args.seed)

    macro_namespace = {
        'primitive': SimpleNamespace(macros=[], models=[]),
        'expert': macros.expert,
        'random': macros.random,
        'learned': macros.learned,
    }[args.macro_type]
    macro_list = macros.primitive.actions + macro_namespace.macros
    model_list = macros.primitive.models + macro_namespace.models

    # Set up the search problem
    search_fn = {
        'astar': search.astar,
        'gbfs': search.gbfs,
        'weighted_astar': search.weighted_astar,
        'bfws_r0': bfws.bfws,
        'bfws_rg': bfws.bfws,
    }[args.search_alg]

    def get_successors(cube_):
        return [(copy.deepcopy(cube_).apply(swap_list=model), macro)
                for (macro, model) in zip(macro_list, model_list)]

    search_dict = {
        'start':
        start,
        'is_goal':
        lambda node: node.state == goal,
        'step_cost':
        lambda macro: len(macro) if args.cost_mode == 'per-action' else 1,
        'heuristic':
        lambda cube_: len(cube_.summarize_effects(baseline=goal)),
        'get_successors':
        get_successors,
        'max_transitions':
        args.max_transitions,
    }

    if args.search_alg == 'weighted_astar':
        assert (args.g_weight is not None and args.h_weight
                is not None), 'Must specify weights if using weighted A*.'
        gh_weights = (args.g_weight, args.h_weight)
        search_dict['gh_weights'] = gh_weights

    if 'bfws' in args.search_alg:
        search_dict['precision'] = args.bfws_precision
    if args.search_alg == 'bfws_rg':
        goal_fns = [(lambda x, i=i: x.state[i] == goal[i])
                    for i, _ in enumerate(goal)]
        relevant_atoms = iw.iw(1, start, get_successors, goal_fns)
        if not relevant_atoms:
            relevant_atoms = iw.iw(2, start, get_successors, goal_fns)
        if not relevant_atoms:
            relevant_atoms = start.all_atoms()
        search_dict['R'] = relevant_atoms

    #%% Run the search
    search_results = search_fn(**search_dict)

    #%% Save the results
    tag = args.macro_type
    if args.random_goal:
        tag = 'random_goal/' + tag
    else:
        tag = 'default_goal/' + tag
    if args.search_alg == 'weighted_astar':
        args.search_alg += '-g_{}-h_{}'.format(*gh_weights)
    problem_name = 'cube' if not args.buchner2018 else 'cube-buchner2018'
    results_dir = 'results/{}/{}/{}/'.format(problem_name, args.search_alg,
                                             tag)
    os.makedirs(results_dir, exist_ok=True)
    with open(results_dir + '/seed-{:03d}.pickle'.format(args.seed),
              'wb') as file:
        pickle.dump(search_results, file)
示例#7
0
def load_and_plot_macros():
    """Load and plot Rubik's cube macros"""

    plt.rcParams.update({'font.size': 12})
    _, ax = plt.subplots(figsize=(4,3))
    macro_names = [
        'Random',
        'Primitive',
        'Focused',
        'Expert',
    ]
    macros.generate_random_macro_set(14)
    macro_types = [
        macros.random,
        macros.primitive,
        macros.learned,
        macros.expert,
    ]
    marker_styles = [
        '^',
        'o',
        '+',
        'x',
    ]
    blue, orange, green, red, purple, brown, pink, gray, yellow, teal  = sns.color_palette('deep', n_colors=10)
    colors = [
        teal,   # random
        blue,   # primitive
        red,    # focused
        orange,   # expert
    ]
    for i, macro_type in enumerate(macro_types):
        if macro_names[i] == 'Random':
            for j in range(1,11):
                macros.generate_random_macro_set(j)
                lengths = [len(macro) for macro in macros.random.macros]
                effects = [len(cube.Cube().apply(swap_list=model).summarize_effects())
                           for model in macros.random.models]
                plt.scatter(lengths, effects, c=colors[i], marker='^',
                            facecolor='none', s=75, linewidths=1)
            macros.generate_random_macro_set(0)
        try:
            lengths = [len(macro) for macro in macro_type.macros]
        except AttributeError:
            lengths = [len(a) for a in macro_type.actions]
        effects = [len(cube.Cube().apply(swap_list=model).summarize_effects())
                   for model in macro_type.models]
        label = macro_names[i] + ' Macros' if macro_names[i] != 'Primitive' else 'Base Actions'
        # if macro_names[i] == 'primitive':
        #     jx, jy = None, None
        # else:
        #     jx, jy = 0.05, 0.25
        jx, jy = None, None
        plt.scatter(jitter(lengths,jx), jitter(effects,jy), c=colors[i], marker=marker_styles[i],
                    facecolor='none', s=75, label=label, linewidths=1)
    plt.hlines(48, 0, 26, linestyles='dashed', linewidths=1)
    handles, labels = ax.get_legend_handles_labels()
    # handles = [handles[0], handles[1], handles[2], handles[3]]
    # labels = [labels[0], labels[1], labels[2], labels[3]]
    leg = plt.legend(handles, labels)
    leg.set_draggable(True)
    plt.ylim([0,50])
    plt.xlim([0,26])
    plt.xticks(range(1,26,4))
    plt.xlabel('Length of Action Sequence')
    plt.ylabel('Stickers Modified')
    plt.tight_layout()
    plt.subplots_adjust(top = .96, bottom = .19, right = .95, left = 0.14,
        hspace = 0, wspace = 0)
    os.makedirs('results/plots/cube-buchner2018/', exist_ok=True)
    # plt.savefig('results/plots/cube-buchner2018/cube_entanglement.png')
    plt.show()
示例#8
0
class CPUTimer:
    def __enter__(self):
        self.start = time.time()
        self.end = self.start
        self.duration = 0.0
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is None:
            self.end = time.time()
            self.duration = self.end - self.start


n_steps = 1000
with CPUTimer() as timer:
    puzzle = cube.Cube()
    puzzle.scramble(length=n_steps)
print('Cube FPS:', n_steps / timer.duration)

with CPUTimer() as timer:
    puzzle = npuzzle.NPuzzle()
    puzzle.scramble(n_steps=n_steps)
print('15-puzzle FPS:', n_steps / timer.duration)

with CPUTimer() as timer:
    env_name = "hanoi_operator_actions"
    problem_index = 1
    render = False
    verbose = False
    seed = 0
    env = gym.make("PDDLEnv{}-v0".format(env_name.capitalize()))
def load_and_plot_macros():
    """Load and plot Rubik's cube macros"""

    plt.rcParams.update({'font.size': 20})
    _, ax = plt.subplots(figsize=(8,6))
    macro_names = [
        'random',
        'primitive',
        'focused',
        'expert',
    ]
    macros.generate_random_macro_set(14)
    macro_types = [
        macros.random,
        macros.primitive,
        macros.learned,
        macros.expert,
    ]
    marker_styles = [
        '^',
        'o',
        '+',
        'x',
    ]
    colors = [
        'C2',#r
        'C0',#p
        'C3',#l
        'C1',#e
    ]
    for i, macro_type in enumerate(macro_types):
        if macro_names[i] == 'random':
            for j in range(1,11):
                macros.generate_random_macro_set(j)
                lengths = [len(macro) for macro in macros.random.macros]
                effects = [len(cube.Cube().apply(swap_list=model).summarize_effects())
                           for model in macros.random.models]
                plt.scatter(lengths, effects, c=colors[i], marker='^',
                            facecolor='none', s=150, linewidths=1)
            macros.generate_random_macro_set(0)
        try:
            lengths = [len(macro) for macro in macro_type.macros]
        except AttributeError:
            lengths = [len(a) for a in macro_type.actions]
        effects = [len(cube.Cube().apply(swap_list=model).summarize_effects())
                   for model in macro_type.models]
        label = macro_names[i]
        # if macro_names[i] == 'primitive':
        #     jx, jy = None, None
        # else:
        #     jx, jy = 0.05, 0.25
        jx, jy = None, None
        plt.scatter(jitter(lengths,jx), jitter(effects,jy), c=colors[i], marker=marker_styles[i],
                    facecolor='none', s=150, label=label, linewidths=1)
    plt.hlines(48, 0, 26, linestyles='dashed', linewidths=2)
    handles, labels = ax.get_legend_handles_labels()
    # handles = [handles[0], handles[1], handles[2], handles[3]]
    # labels = [labels[0], labels[1], labels[2], labels[3]]
    plt.legend(handles, labels)
    plt.ylim([0,50])
    plt.xlim([0,26])
    plt.xticks(range(1,26,4))
    plt.xlabel('Macro-action length')
    plt.ylabel('Effect size')
    plt.tight_layout()
    plt.subplots_adjust(top = .96, bottom = .12, right = .95, left = 0.11,
        hspace = 0, wspace = 0)
    os.makedirs('results/plots/cube-buchner2018/', exist_ok=True)
    plt.savefig('results/plots/cube-buchner2018/cube_entanglement.png')
    plt.show()