def selectRegion2(string, width, args):
    """
    select a region within width from the given x-string
    (for x-PBC use only)

    Parameters
    -----------------
    string : list of bonds
        bonds on the string operator
    width : int
        width of the spreading from string operator
    size : (int, int)
        linear size of the lattice system
    """
    region = []
    size = [args['nx'], args['ny']]
    xperiodic = args['xperiodic']
    if xperiodic == False:
        sys.exit("selectRegion2 recognizes x-PBC only")
    for bond in string:
        x, y, dir = bond[0], bond[1], bond[2]
        # add the plaquette above/below this bond
        above = [(x, y, 'r')]
        below = [(x, y, 'r')]
        for d in range(width):
            above.append((x, y - d - 1, 'r'))
            above.append((x, y - d - 1, 'd'))
            above.append((x + 1, y - d - 1, 'd'))
            below.append((x, y + d + 1, 'r'))
            below.append((x, y + d, 'd'))
            below.append((x + 1, y + d, 'd'))
        if y == 0:  # upper boundary; add plq. below only
            above = []
        if y == size[1] - 1:  # lower boundary; add plq. above only
            below = []
        for newbond in above:
            region.append(lat.lat(newbond[0:2], newbond[2], size, xperiodic))
        for newbond in below:
            region.append(lat.lat(newbond[0:2], newbond[2], size, xperiodic))
    region = np.asarray(region, dtype=int)
    region = np.unique(region)
    return region
Esempio n. 2
0
    # use default p.args['nx']
    sep = 10
    # use default p.args['hz']
    width = 2
    os.makedirs(result_dir, exist_ok=True)
    benckmark = False
    # save parameters
    with open(result_dir + '/parameters.txt', 'w+') as file:
        pass

# create string operator pair (x-PBC) MPO enclosing different area
closed_str_list = crt.str_create3(args, sep)
string = closed_str_list[0]
bond_on_str, area, circum = crt.convertToStrOp(string, args)
bond_list = [
    lat.lat(bond_on_str[i][0:2], bond_on_str[i][2], (args['nx'], args['ny']),
            args['xperiodic']) for i in range(len(bond_on_str))
]
region = crt.selectRegion2(bond_on_str, width, args)

# save parameters
with open(result_dir + '/parameters.txt', 'a+') as file:
    file.write(json.dumps(args) + '\n')  # use json.loads to do the reverse
    # Output information
    file.write("area: {}\ncircumference: {}\n".format(area, circum))
    file.write("bond on str: \n{}\n".format(bond_on_str))
    file.write("bond number: \n{}\n".format(bond_list))
    if benchmark == False:
        file.write("bond within distance {}: \n{}\n\n".format(width, region))

# create Toric Code ground state |psi>
psi = gnd_state.gnd_state_builder(args)
        n += args['ny'] - 1
        args['n'] = n
        # n in case of periodic X
        if args['xperiodic'] == True:
            args['real_n'] = n - (args['ny'] - 1)
        else:
            args['real_n'] = n
        # create Toric Code ground state
        psi = np.load(
            psi_dir +
            "mps_{}by{}_hz-{:.2f}.npy".format(nx, args['ny'], args['hz']))

        # restore information of the string
        closed_str_list = crt.str_create3(args, sep)
        string = closed_str_list[0]
        bond_on_str, area, circum = crt.convertToStrOp(string, args)
        bond_list = [
            lat.lat(bond_on_str[i][0:2], bond_on_str[i][2],
                    (args['nx'], args['ny']), args['xperiodic'])
            for i in range(len(bond_on_str))
        ]

        op = np.load(result_dir +
                     'quasi_op_{}by{}_sep-{}_hz-{:.2f}.npy'.format(
                         args['nx'], args['ny'], sep, args['hz']),
                     allow_pickle=True)
        op = list(op)
        exp_value = mps.matElem(psi, op, psi, verbose=True)
        with open(resultfile, 'a+') as file:
            file.write("{}\t{}\t{}\n".format(area, circum, exp_value))
Esempio n. 4
0
def makeGateList(siteNum, args, region=range(10000)):
    """
    Create time-evolution/swap gate list

    Parameters
    ---------------
    siteNum : int
        number of sites
    args : dictionary
        parameter dictionary
    region : iterable of integers (default range(p.args['n']))
        the region from which gates are constructed
    """
    gateList = []
    xperiodic = args['xperiodic']
    putsite = [False] * siteNum
    swapGates = []
    # open boundary condition along x
    # make plaquette gates (together with field)
    if (args['g'] != 0):
        # i -> row; j -> column
        for j, i in product(range(args['ny'] - 1), range(args['nx'] - 1)):
            out_of_region = False
            u = lat.lat((i, j),
                        'r', (args['nx'], args['ny']),
                        xperiodic=xperiodic)
            l = lat.lat((i, j),
                        'd', (args['nx'], args['ny']),
                        xperiodic=xperiodic)
            r = lat.lat((i + 1, j),
                        'd', (args['nx'], args['ny']),
                        xperiodic=xperiodic)
            d = lat.lat((i, j + 1),
                        'r', (args['nx'], args['ny']),
                        xperiodic=xperiodic)
            sites = [u, l, r, d]
            # check if this gate is in the region
            for i in range(len(sites)):
                if sites[i] not in region:
                    out_of_region = True
                    break
            if out_of_region == True:
                continue
            # print(sites)
            # create swap gates
            # reaching boundary
            if (r % (args['nx'] - 1) == 0 and xperiodic == True):
                # in this case r = u + 1, l = u + nx - 1, d = u + 2 (nx - 1)
                sites.sort()
                # now sites = [u, u + 1, u + nx - 1, u + 2 (nx - 1)]
                # move sites[2]
                for site in np.arange(sites[2], sites[1] + 1, -1, dtype=int):
                    swapGates.append(
                        gate([site - 1, site], putsite, 'Swap', args))
                # move sites[3]
                for site in np.arange(sites[3], sites[1] + 2, -1, dtype=int):
                    swapGates.append(
                        gate([site - 1, site], putsite, 'Swap', args))
                gateSites = [
                    sites[0], sites[0] + 1, sites[0] + 2, sites[0] + 3
                ]
            else:
                # OBC case / PBC case off boundary
                # move sites[0]
                for site in np.arange(sites[0], sites[1] - 1, 1, dtype=int):
                    swapGates.append(
                        gate([site, site + 1], putsite, 'Swap', args))
                # move sites[3]
                for site in np.arange(sites[3], sites[2] + 1, -1, dtype=int):
                    swapGates.append(
                        gate([site - 1, site], putsite, 'Swap', args))
                gateSites = [
                    sites[1] - 1, sites[1], sites[1] + 1, sites[1] + 2
                ]

            for k in range(len(swapGates)):
                gateList.append(swapGates[k])
            # evolution gate (plaquette with field)
            gateList.append(gate(gateSites, putsite, 'tEvolP', args))
            """
            VERY IMPORTANT:
            how to add magnetic field to the sites

            Example
            -----------
            Suppose a 4-site operator acts on [11,15,16,20]
            It will become [14,15,16,17] after applying the swap gates 
            We NOW add field to site 14,15,16,17 instead of 11,15,16,20
            But we will set putsite[11,15,16,20] (not [14,15,16,17]) to True
            """
            for site in sites:
                putsite[site] = True
            # put sites back to the original place
            for k in reversed(range(len(swapGates))):
                gateList.append(swapGates[k])
            swapGates.clear()
    # vertex gates (ZZZZ) are not necessary since it commutes with
    # plaquette (XXXX), closed string (X...X) and field (Z)
    # make vertex gates
    if (args['U'] != 0):
        # i -> row; j -> column
        if xperiodic == True:
            irange = range(args['nx'] - 1)
        else:
            irange = range(args['nx'])
        for j, i in product(range(args['ny'] - 1), irange):
            out_of_region = False
            sites = lat.vertex((i, j), args)
            sites.sort()
            # create swap gates
            for site in np.arange(sites[0], sites[1] - 1, 1, dtype=int):
                swapGates.append(gate([site, site + 1], putsite, 'Swap', args))
            for site in np.arange(sites[3] - 1, sites[2], -1, dtype=int):
                swapGates.append(gate([site, site + 1], putsite, 'Swap', args))
            gateSites = [sites[1] - 1, sites[1], sites[1] + 1, sites[1] + 2]
            for k in range(len(swapGates)):
                gateList.append(swapGates[k])
            # evolution gate (vertex)
            gateList.append(gate(gateSites, putsite, 'tEvolV', args))
            # put sites back to the original place
            for k in reversed(range(len(swapGates))):
                gateList.append(swapGates[k])
            swapGates.clear()

    # second order Trotter decomposition
    # b1.b2.b3....b3.b2.b1
    # append "reversed gateList" to "gateList"
    gateNum = len(gateList)
    for i in reversed(range(gateNum)):
        gateList.append(gateList[i])
    cleanGates(gateList)
    return gateList
def selectRegion(string, width, args):
    """
    select a region within width from the given string

    Parameters
    -----------------
    string : list of bonds
        bonds on the string operator
    width : int
        width of the spreading from string operator
    size : (int, int)
        linear size of the lattice system
    """
    region = []
    size = [args['nx'], args['ny']]
    xperiodic = args['xperiodic']
    for bond in string:
        x, y, dir = bond[0], bond[1], bond[2]
        if dir == 'd':
            # add the plaquette to the left/right of this bond
            left = [(x - 1, y, 'r'), (x - 1, y, 'd'), (x, y, 'd'),
                    (x - 1, y + 1, 'r')]
            right = [(x, y, 'd'), (x, y, 'r'), (x + 1, y, 'd'),
                     (x, y + 1, 'r')]
            # check whether this is a boundary bond
            if xperiodic == False:
                if x == 0:  # left boundary: add right plq. only
                    left = []
                elif x == size[0] - 1:  # right boundary: add left plq. only
                    right = []
            elif xperiodic == True:
                if x == 0:  # left boundary: add rightmost plq.
                    left = [(x - 1, y, 'r'), (x - 1, y, 'd'), (x, y, 'd'),
                            (x - 1, y + 1, 'r')]
                elif x == size[0] - 1:  # right boundary: add leftmost plq.
                    right = [(x, y, 'd'), (x, y, 'r'), (x + 1, y, 'd'),
                             (x, y + 1, 'r')]
            for newbond in left:
                region.append(
                    lat.lat(newbond[0:2], newbond[2], size, xperiodic))
            for newbond in right:
                region.append(
                    lat.lat(newbond[0:2], newbond[2], size, xperiodic))
        if dir == 'r':
            # add the plaquette above/below this bond
            above = [(x, y - 1, 'r'), (x, y - 1, 'd'), (x + 1, y - 1, 'd'),
                     (x, y, 'r')]
            below = [(x, y, 'r'), (x, y, 'd'), (x + 1, y, 'd'),
                     (x, y + 1, 'r')]
            if y == 0:  # upper boundary; add plq. below only
                above = []
            if y == size[1] - 1:  # lower boundary; add plq. above only
                below = []
            for newbond in above:
                region.append(
                    lat.lat(newbond[0:2], newbond[2], size, xperiodic))
            for newbond in below:
                region.append(
                    lat.lat(newbond[0:2], newbond[2], size, xperiodic))
    region = np.asarray(region, dtype=int)
    region = np.unique(region)
    return region