Пример #1
0
def rule_op(V, R, r, d, totalistic=False, hamiltonian=False):
    """
    Operator for rule R, activation V, and neighborhood radius r, and dimension d.
    hamiltonian flag for simultaion type (hamiltonian=analog, unitary=digital)
    """
    N = 2 * r * d
    OP = np.zeros((2 ** (N + 1), 2 ** (N + 1)), dtype=complex)
    if totalistic:
        R2 = mx.dec_to_bin(R, N + 1)[::-1]
    else:
        R2 = mx.dec_to_bin(R, 2 ** N)[::-1]
    for elnum, Rel in enumerate(R2):
        if totalistic:
            K = elnum * [1] + (N - elnum) * [0]
            hoods = list(set([perm for perm in permutations(K, N)]))
            hoods = map(list, hoods)
        else:
            hoods = [mx.dec_to_bin(elnum, N)]
        for hood in hoods:
            OP += rule_element(V, Rel, hood, hamiltonian=hamiltonian)
    if hamiltonian:
        assert mx.isherm(OP)
    else:  # unitaty
        assert mx.isU(OP)
    return OP
Пример #2
0
def boundary_rule_ops(V, R, r, d, BC_conf, totalistic=False, hamiltonian=False):
    """
    Special operators for boundaries (of which there are 2r).
    BC_conf is a string "b0b1...br...b2r" where each bj is
    either 0 or 1. Visiually, BC_conf represents the fixed boundaries
    from left to right: |b0>|b1>...|br> |psi>|b2r-r>|b2r-r+1>...|b2r>.
    """
    BC_conf = np.array([int(s) for s in BC_conf])
    OPs = []
    N = 2 * r * d
    if totalistic:
        R2 = mx.dec_to_bin(R, N + 1)[::-1]
    else:
        R2 = mx.dec_to_bin(R, 2 ** N)[::-1]

    indsj = [np.arange(r), np.array([r]), np.arange(r+1, 2*r+1)]
    dj = 2*r + 1
    if d == 2:
        indsk = indsj
        dk = 2*r + 1
    elif d ==1:
        indsk = [[0]]
        dk =1
    OPs = []
    for J, js in enumerate(indsj):
        for K, ks in enumerate(indsk):
            OPs_region = []
            for j in js:
                OPs_row = []
                for k in ks:
                    mask = make_mask(j, k, dj, dk, r, d, BC_type="1")
                    clip = np.logical_not(mask)
                    if np.sum(clip) > 0:
                        dim = np.sum(mask)+1
                        OP = np.zeros((2 ** dim, 2 ** dim), dtype=complex)
                        for elnum, Rel in enumerate(R2):
                            if totalistic:
                                tot = elnum * [1] + (N - elnum) * [0]
                                hoods = list(set([perm for perm in permutations(tot, N)]))
                                hoods = map(np.array, hoods)
                            else:
                                hoods = np.array([mx.dec_to_bin(elnum, N)])
                            for hood in hoods:
                                if np.all(BC_conf[clip] == hood[clip]):
                                    OP += rule_element(
                                        V,
                                        Rel,
                                        hood[mask],
                                        hamiltonian=hamiltonian,
                                    )
                        if hamiltonian:
                            assert mx.isherm(OP)
                        else:  # unitaty
                            assert mx.isU(OP)
                        OPs_row.append(OP)
                OPs_region.append(OPs_row)
            if len(OPs_region[0]) > 0:
                OPs.append(OPs_region)
    return OPs
Пример #3
0
def boundary_rule_ops(V, R, r, BC_conf, totalistic=False, hamiltonian=False):
    """
    Special operators for boundaries (of which there are 2r).
    BC_conf is a string "b0b1...br...b2r" where each bj is
    either 0 or 1. Visiually, BC_conf represents the fixed boundaries
    from left to right: |b0>|b1>...|br> |psi>|b2r-r>|b2r-r+1>...|b2r>.
    """
    # split BC configuration into left and reverse-right boundaries
    BC_conf = [BC_conf[:r], BC_conf[r::][::-1]]
    N = 2 * r
    OPs = []
    for j, BC in enumerate(BC_conf):
        for e in range(r):
            dim = r + 1 + e
            if j == 0:  # left boundary
                lslice = slice(r - e, r)
                rslice = slice(r, N)
                cslice = slice(0, r - e)
            elif j == 1:  # right boundary
                lslice = slice(0, r)
                rslice = slice(r, r + e)
                cslice = slice(r + e, N)
            OP = np.zeros((2**dim, 2**dim), dtype=complex)
            if totalistic:
                R2 = mx.dec_to_bin(R, N + 1)[::-1]
                for elnum, Rel in enumerate(R2):
                    K = elnum * [1] + (N - elnum) * [0]
                    hoods = list(set([perm for perm in permutations(K, N)]))
                    hoods = map(list, hoods)
                    for hood in hoods:
                        if BC[e:r] == hood[cslice]:
                            OP += rule_element(
                                V,
                                Rel,
                                hood,
                                lslice=lslice,
                                rslice=rslice,
                                hamiltonian=hamiltonian,
                            )

            else:  # non-totalistic
                R2 = mx.dec_to_bin(R, 2**N)[::-1]
                for elnum, Rel in enumerate(R2):
                    hood = mx.dec_to_bin(elnum, N)
                    if BC[e:r] == hood[cslice]:
                        OP += rule_element(
                            V,
                            Rel,
                            hood,
                            lslice=lslice,
                            rslice=rslice,
                            hamiltonian=hamiltonian,
                        )
            if hamiltonian:
                assert mx.isherm(OP)
            else:  # unitaty
                assert mx.isU(OP)
            OPs.append(OP)
    return OPs[:r], OPs[r:][::-1]
Пример #4
0
def rule_unitaries(V,
                   R,
                   r,
                   BC,
                   L,
                   dt,
                   totalistic=False,
                   hamiltonian=False,
                   trotter=True):
    """
    Calculate qca unitiary activation V, rule R, radius r, bounary condition BC,
    size L, and time step dt.
    """
    BC_type, *BC_conf = BC.split("-")
    BC_conf = "".join(BC_conf)
    if BC_type == "1":
        BC_conf = [int(bc) for bc in BC_conf]
    if L is None:
        L = 2 * r + 1
    bulk = rule_op(V, R, r, totalistic=totalistic, hamiltonian=hamiltonian)
    lUs, rUs = boundary_rule_ops(V,
                                 R,
                                 r,
                                 BC_conf,
                                 totalistic=totalistic,
                                 hamiltonian=hamiltonian)
    if hamiltonian:
        if trotter:
            bulk = expm(-1j * bulk * dt)
            rUs = [expm(-1j * H * dt) for H in rUs]
            lUs = [expm(-1j * H * dt) for H in lUs]
        else:  # not trotter:
            H = np.zeros((2**L, 2**L), dtype=complex)
            for j in range(r, L - r):
                ln = j - r
                rn = L - 2 * r - 1 - ln
                left = np.eye(2**ln)
                right = np.eye(2**rn)
                H += mx.listkron([left, bulk, right])
            # boundaries
            for j, (lU, rU) in enumerate(zip(lUs, rUs[::-1])):
                end = np.eye(2**(L - r - 1 - j))
                H += mx.listkron([end, rU])
                H += mx.listkron([lU, end])
            U = expm(-1j * H * dt)
            assert mx.isU(U)
            return U

    if BC_type == "0":
        return bulk
    else:  # BC_type == "1"
        return lUs, bulk, rUs
Пример #5
0
def make_U(V, r, S):
    N = 2 * r
    Sb = mx.dec_to_bin(S, 2**N)[::-1]
    U = np.zeros((2**(N + 1), 2**(N + 1)), dtype=complex)
    for sig, s in enumerate(Sb):
        sigb = mx.dec_to_bin(sig, N)
        Vmat = get_V(V, s)
        ops = ([mx.ops[str(op)] for op in sigb[0:r]] + [Vmat] +
               [mx.ops[str(op)] for op in sigb[r:2 * r + 1]])
        U += mx.listkron(ops)

    if not mx.isU(U):
        raise AssertionError
    return U