コード例 #1
0
def create_phase2_edgemerge_table():
    """phase2_edgemerge retrieves the initial phase 2 ud_edges coordinate from the u_edges and d_edges coordinates."""
    table_name = "phase2_edgemerge"
    table_path = get_pruning_table_path(table_name)
    global u_edges_plus_d_edges_to_ud_edges
    c_u = cb.CubieCube()
    c_d = cb.CubieCube()
    c_ud = cb.CubieCube()
    edge_u = [Ed.UR, Ed.UF, Ed.UL, Ed.UB]
    edge_d = [Ed.DR, Ed.DF, Ed.DL, Ed.DB]
    edge_ud = [Ed.UR, Ed.UF, Ed.UL, Ed.UB, Ed.DR, Ed.DF, Ed.DL, Ed.DB]

    if not path.isfile(table_path):
        cnt = 0
        print("creating " + table_name + " table...")
        u_edges_plus_d_edges_to_ud_edges = ar.array(
            'H', [0 for i in range(N_U_EDGES_PHASE2 * N_PERM_4)])
        for i in range(N_U_EDGES_PHASE2):
            c_u.set_u_edges(i)
            for j in range(N_CHOOSE_8_4):
                c_d.set_d_edges(j * N_PERM_4)
                invalid = False
                for e in edge_ud:
                    c_ud.ep[e] = -1  # invalidate edges
                    if c_u.ep[e] in edge_u:
                        c_ud.ep[e] = c_u.ep[e]
                    if c_d.ep[e] in edge_d:
                        c_ud.ep[e] = c_d.ep[e]
                    if c_ud.ep[e] == -1:
                        invalid = True  # edge collision
                        break
                if not invalid:
                    for k in range(N_PERM_4):
                        c_d.set_d_edges(j * N_PERM_4 + k)
                        for e in edge_ud:
                            if c_u.ep[e] in edge_u:
                                c_ud.ep[e] = c_u.ep[e]
                            if c_d.ep[e] in edge_d:
                                c_ud.ep[e] = c_d.ep[e]
                        u_edges_plus_d_edges_to_ud_edges[
                            N_PERM_4 * i + k] = c_ud.get_ud_edges()
                        cnt += 1
                        if cnt % 2000 == 0:
                            print('.', end='', flush=True)
        print()
        fh = open(table_path, "wb")
        u_edges_plus_d_edges_to_ud_edges.tofile(fh)
        fh.close()
        print()
    else:
        fh = open(table_path, "rb")
        u_edges_plus_d_edges_to_ud_edges = ar.array('H')
        u_edges_plus_d_edges_to_ud_edges.fromfile(fh,
                                                  N_U_EDGES_PHASE2 * N_PERM_4)
コード例 #2
0
def create_phase2_cornsliceprun_table():
    """Creates/loads the cornslice_depth pruning table for phase 2. With this table we do a fast precheck
    at the beginning of phase 2."""
    table_name = "phase2_cornsliceprun"
    table_path = get_pruning_table_path(table_name)
    global cornslice_depth
    if not path.isfile(table_path):
        print("creating " + table_name + " table...")
        cornslice_depth = ar.array('b',
                                   [-1] * (defs.N_CORNERS * defs.N_PERM_4))
        corners = 0  # values for solved phase 2
        slice_ = 0
        cornslice_depth[defs.N_PERM_4 * corners + slice_] = 0
        done = 1
        depth = 0
        idx = 0
        while done != defs.N_CORNERS * defs.N_PERM_4:
            for corners in range(defs.N_CORNERS):
                for slice_ in range(defs.N_PERM_4):
                    if cornslice_depth[defs.N_PERM_4 * corners +
                                       slice_] == depth:
                        for m in (enums.Move.U1, enums.Move.U2, enums.Move.U3,
                                  enums.Move.R2, enums.Move.F2, enums.Move.D1,
                                  enums.Move.D2, enums.Move.D3, enums.Move.L2,
                                  enums.Move.B2):
                            corners1 = mv.corners_move[18 * corners + m]
                            slice_1 = mv.slice_sorted_move[18 * slice_ + m]
                            idx1 = defs.N_PERM_4 * corners1 + slice_1
                            if cornslice_depth[
                                    idx1] == -1:  # entry not yet filled
                                cornslice_depth[idx1] = depth + 1
                                done += 1
                                if done % 20000 == 0:
                                    print('.', end='', flush=True)

            depth += 1
        print()
        fh = open(table_path, "wb")
        cornslice_depth.tofile(fh)
    else:
        # print("loading " + table_name + " table...")
        fh = open(table_path, "rb")
        cornslice_depth = ar.array('b')
        cornslice_depth.fromfile(fh, defs.N_CORNERS * defs.N_PERM_4)
    fh.close()
コード例 #3
0
# #### generate the table for the conjugation of a move m by a symmetry s. conj_move[m, s] = s*m*s^-1###################
conj_move = np.empty([N_MOVE, N_SYM], dtype=np.uint8)
for s in range(N_SYM):
    for m in Mv:
        ss = cb.CubieCube(symCube[s].cp, symCube[s].co, symCube[s].ep, symCube[s].eo)  # copy cube
        ss.multiply(cb.moveCube[m])  # s*m
        ss.multiply(symCube[inv_idx[s]])  # s*m*s^-1
        for m2 in Mv:
            if ss == cb.moveCube[m2]:
                conj_move[m][s] = m2
########################################################################################################################

# ####### generate the phase 1 table for the conjugation of the twist t by a symmetry s. conj_twist[t, s] = s*t*s^-1####
table_name = "conj_twist"
table_path = get_pruning_table_path(table_name)
if not path.isfile(table_path):
    print('On the first run, several tables will be created. This takes from 1/2 hour (e.g. PC) to 6 hours '
          '(e.g. RaspberryPi3), depending on the hardware.')
    print("creating " + table_name + " table...")
    twist_conj = ar.array('H', [0] * (N_TWIST * N_SYM_D4h))
    for t in range(N_TWIST):
        cc = cb.CubieCube()
        cc.set_twist(t)
        for s in range(N_SYM_D4h):
            ss = cb.CubieCube(symCube[s].cp, symCube[s].co, symCube[s].ep, symCube[s].eo)  # copy cube
            ss.corner_multiply(cc)  # s*t
            ss.corner_multiply(symCube[inv_idx[s]])  # s*t*s^-1
            twist_conj[N_SYM_D4h * t + s] = ss.get_twist()
    fh = open(table_path, "wb")
    twist_conj.tofile(fh)
コード例 #4
0
def create_phase1_prun_table():
    """Creates/loads the flipslice_twist_depth3 pruning table for phase 1."""
    global flipslice_twist_depth3
    total = defs.N_FLIPSLICE_CLASS * defs.N_TWIST
    table_name = "phase1_prun"
    table_path = get_pruning_table_path(table_name)
    if not path.isfile(table_path):
        print("creating " + table_name + " table...")
        print(
            'This may take half an hour or even longer, depending on the hardware.'
        )

        flipslice_twist_depth3 = ar.array('L',
                                          [0xffffffff] * (total // 16 + 1))
        # #################### create table with the symmetries of the flipslice classes ###############################
        cc = cb.CubieCube()
        fs_sym = ar.array('H', [0] * defs.N_FLIPSLICE_CLASS)
        for i in range(defs.N_FLIPSLICE_CLASS):
            if (i + 1) % 1000 == 0:
                print('.', end='', flush=True)
            rep = sy.flipslice_rep[i]
            cc.set_slice(rep // defs.N_FLIP)
            cc.set_flip(rep % defs.N_FLIP)

            for s in range(defs.N_SYM_D4h):
                ss = cb.CubieCube(sy.symCube[s].cp, sy.symCube[s].co,
                                  sy.symCube[s].ep,
                                  sy.symCube[s].eo)  # copy cube
                ss.edge_multiply(cc)  # s*cc
                ss.edge_multiply(sy.symCube[sy.inv_idx[s]])  # s*cc*s^-1
                if ss.get_slice() == rep // defs.N_FLIP and ss.get_flip(
                ) == rep % defs.N_FLIP:
                    fs_sym[i] |= 1 << s
        print()
        # ##################################################################################################################

        fs_classidx = 0  # value for solved phase 1
        twist = 0
        set_flipslice_twist_depth3(defs.N_TWIST * fs_classidx + twist, 0)
        done = 1
        depth = 0
        backsearch = False
        print('depth:', depth, 'done: ' + str(done) + '/' + str(total))
        while done != total:
            depth3 = depth % 3
            if depth == 9:
                # backwards search is faster for depth >= 9
                print('flipping to backwards search...')
                backsearch = True
            if depth < 8:
                mult = 5
            else:
                mult = 1
            idx = 0
            for fs_classidx in range(defs.N_FLIPSLICE_CLASS):
                if (fs_classidx + 1) % (200 * mult) == 0:
                    print('.', end='', flush=True)
                if (fs_classidx + 1) % (16000 * mult) == 0:
                    print('')

                twist = 0
                while twist < defs.N_TWIST:

                    # ########## if table entries are not populated, this is very fast: ################################
                    if not backsearch and idx % 16 == 0 and flipslice_twist_depth3[idx // 16] == 0xffffffff \
                            and twist < defs.N_TWIST - 16:
                        twist += 16
                        idx += 16
                        continue
                    ####################################################################################################

                    if backsearch:
                        match = (get_flipslice_twist_depth3(idx) == 3)
                    else:
                        match = (get_flipslice_twist_depth3(idx) == depth3)

                    if match:
                        flipslice = sy.flipslice_rep[fs_classidx]
                        flip = flipslice % 2048  # defs.N_FLIP = 2048
                        slice_ = flipslice >> 11  # // defs.N_FLIP
                        for m in enums.Move:
                            twist1 = mv.twist_move[18 * twist +
                                                   m]  # defs.N_MOVE = 18
                            flip1 = mv.flip_move[18 * flip + m]
                            slice1 = mv.slice_sorted_move[
                                432 * slice_ +
                                m] // 24  # defs.N_PERM_4 = 24, 18*24 = 432
                            flipslice1 = (slice1 << 11) + flip1
                            fs1_classidx = sy.flipslice_classidx[flipslice1]
                            fs1_sym = sy.flipslice_sym[flipslice1]
                            twist1 = sy.twist_conj[(twist1 << 4) + fs1_sym]
                            idx1 = 2187 * fs1_classidx + twist1  # defs.N_TWIST = 2187
                            if not backsearch:
                                if get_flipslice_twist_depth3(
                                        idx1) == 3:  # entry not yet filled
                                    set_flipslice_twist_depth3(
                                        idx1, (depth + 1) % 3)
                                    done += 1
                                    # ####symmetric position has eventually more than one representation ###############
                                    sym = fs_sym[fs1_classidx]
                                    if sym != 1:
                                        for j in range(1, 16):
                                            sym >>= 1
                                            if sym % 2 == 1:
                                                twist2 = sy.twist_conj[
                                                    (twist1 << 4) + j]
                                                # fs2_classidx = fs1_classidx due to symmetry
                                                idx2 = 2187 * fs1_classidx + twist2
                                                if get_flipslice_twist_depth3(
                                                        idx2) == 3:
                                                    set_flipslice_twist_depth3(
                                                        idx2, (depth + 1) % 3)
                                                    done += 1
                                    ####################################################################################

                            else:  # backwards search
                                if get_flipslice_twist_depth3(idx1) == depth3:
                                    set_flipslice_twist_depth3(
                                        idx, (depth + 1) % 3)
                                    done += 1
                                    break
                    twist += 1
                    idx += 1  # idx = defs.N_TWIST * fs_class + twist

            depth += 1
            print()
            print('depth:', depth, 'done: ' + str(done) + '/' + str(total))

        fh = open(table_path, "wb")
        flipslice_twist_depth3.tofile(fh)
    else:
        # print("loading " + table_name + " table...")
        fh = open(table_path, "rb")
        flipslice_twist_depth3 = ar.array('L')
        flipslice_twist_depth3.fromfile(fh, total // 16 + 1)
    fh.close()
コード例 #5
0
def create_phase2_prun_table():
    """Creates/loads the corners_ud_edges_depth3 pruning table for phase 2."""
    total = defs.N_CORNERS_CLASS * defs.N_UD_EDGES
    table_name = "phase2_prun"
    table_path = get_pruning_table_path(table_name)
    global corners_ud_edges_depth3
    if not path.isfile(table_path):
        print("creating " + table_name + " table...")

        corners_ud_edges_depth3 = ar.array('L', [0xffffffff] * (total // 16))
        # ##################### create table with the symmetries of the corners classes ################################
        cc = cb.CubieCube()
        c_sym = ar.array('H', [0] * defs.N_CORNERS_CLASS)
        for i in range(defs.N_CORNERS_CLASS):
            if (i + 1) % 1000 == 0:
                print('.', end='', flush=True)
            rep = sy.corner_rep[i]
            cc.set_corners(rep)
            for s in range(defs.N_SYM_D4h):
                ss = cb.CubieCube(sy.symCube[s].cp, sy.symCube[s].co,
                                  sy.symCube[s].ep,
                                  sy.symCube[s].eo)  # copy cube
                ss.corner_multiply(cc)  # s*cc
                ss.corner_multiply(sy.symCube[sy.inv_idx[s]])  # s*cc*s^-1
                if ss.get_corners() == rep:
                    c_sym[i] |= 1 << s
        print()
        ################################################################################################################

        c_classidx = 0  # value for solved phase 2
        ud_edge = 0
        set_corners_ud_edges_depth3(defs.N_UD_EDGES * c_classidx + ud_edge, 0)
        done = 1
        depth = 0
        print('depth:', depth, 'done: ' + str(done) + '/' + str(total))
        while depth < 10:  # we fill the table only do depth 9 + 1
            depth3 = depth % 3
            idx = 0
            mult = 2
            if depth > 9:
                mult = 1
            for c_classidx in range(defs.N_CORNERS_CLASS):
                if (c_classidx + 1) % (20 * mult) == 0:
                    print('.', end='', flush=True)
                if (c_classidx + 1) % (1600 * mult) == 0:
                    print('')

                ud_edge = 0
                while ud_edge < defs.N_UD_EDGES:

                    # ################ if table entries are not populated, this is very fast: ##########################
                    if idx % 16 == 0 and corners_ud_edges_depth3[idx // 16] == 0xffffffff \
                            and ud_edge < defs.N_UD_EDGES - 16:
                        ud_edge += 16
                        idx += 16
                        continue
                    ####################################################################################################

                    if get_corners_ud_edges_depth3(idx) == depth3:
                        corner = sy.corner_rep[c_classidx]
                        # only iterate phase 2 moves
                        for m in (enums.Move.U1, enums.Move.U2, enums.Move.U3,
                                  enums.Move.R2, enums.Move.F2, enums.Move.D1,
                                  enums.Move.D2, enums.Move.D3, enums.Move.L2,
                                  enums.Move.B2):
                            ud_edge1 = mv.ud_edges_move[18 * ud_edge + m]
                            corner1 = mv.corners_move[18 * corner + m]
                            c1_classidx = sy.corner_classidx[corner1]
                            c1_sym = sy.corner_sym[corner1]
                            ud_edge1 = sy.ud_edges_conj[(ud_edge1 << 4) +
                                                        c1_sym]
                            idx1 = 40320 * c1_classidx + ud_edge1  # N_UD_EDGES = 40320
                            if get_corners_ud_edges_depth3(
                                    idx1) == 3:  # entry not yet filled
                                set_corners_ud_edges_depth3(
                                    idx1, (depth + 1) % 3)  # depth + 1 <= 10
                                done += 1
                                # ######symmetric position has eventually more than one representation #############
                                sym = c_sym[c1_classidx]
                                if sym != 1:
                                    for j in range(1, 16):
                                        sym >>= 1
                                        if sym % 2 == 1:
                                            ud_edge2 = sy.ud_edges_conj[
                                                (ud_edge1 << 4) + j]
                                            # c1_classidx does not change
                                            idx2 = 40320 * c1_classidx + ud_edge2
                                            if get_corners_ud_edges_depth3(
                                                    idx2) == 3:
                                                set_corners_ud_edges_depth3(
                                                    idx2, (depth + 1) % 3)
                                                done += 1
                                ####################################################################################

                    ud_edge += 1
                    idx += 1  # idx = defs.N_UD_EDGEPERM * corner_classidx + ud_edge

            depth += 1
            print()
            print('depth:', depth, 'done: ' + str(done) + '/' + str(total))

        print('remaining unfilled entries have depth >=11')
        fh = open(table_path, "wb")
        corners_ud_edges_depth3.tofile(fh)
    else:
        # print("loading " + table_name + " table...")
        fh = open(table_path, "rb")
        corners_ud_edges_depth3 = ar.array('L')
        corners_ud_edges_depth3.fromfile(fh, total // 16)

    fh.close()
コード例 #6
0
# ################### Movetables describe the transformation of the coordinates by cube moves. #########################

from os import path
import array as ar
import cubie as cb
import enums
from defs import N_TWIST, N_FLIP, N_SLICE_SORTED, N_CORNERS, N_UD_EDGES, N_MOVE
from misc import get_pruning_table_path

a = cb.CubieCube()
# ########### Move table for the twists of the corners. twist < 2187 in phase 1, twist = 0 in phase 2. #################

# The twist coordinate describes the 3^7 = 2187 possible orientations of the 8 corners
table_name = "move_twist"
table_path = get_pruning_table_path(table_name)
if not path.isfile(table_path):
    print("creating " + table_name + " table...")
    twist_move = ar.array('H', [0 for i in range(N_TWIST * N_MOVE)])
    for i in range(N_TWIST):
        a.set_twist(i)
        for j in enums.Color:  # six faces U, R, F, D, L, B
            for k in range(
                    3
            ):  # three moves for each face, for example U, U2, U3 = U'
                a.corner_multiply(cb.basicMoveCube[j])
                twist_move[N_MOVE * i + 3 * j + k] = a.get_twist()
            a.corner_multiply(cb.basicMoveCube[j])  # 4. move restores face
    fh = open(table_path, "wb")
    twist_move.tofile(fh)
else:
    # print("loading " + table_name + " table...")