def singleProjectorSample(args): (P, L, seed) = args # unpack arguments (easier for parallel code) (phases, xs, zs) = P t = len(xs[0]) # init seed np.random.seed(seed) # sample random theta theta = StabilizerState.randomStabilizerState(t) # project random state to P projfactor = 1 for g in range(len(phases)): res = theta.measurePauli(phases[g], zs[g], xs[g]) projfactor *= res if res == 0: return 0 # theta annihilated by P total = 0 if L is None: # exact decomposition size = int(np.ceil(t / 2)) for i in range(0, 2**size): phi = prepH(i, t) total += StabilizerState.innerProduct(theta, phi) else: # approximate decomposition size = len(L) for i in range(0, 2**size): phi = prepL(i, t, L) total += StabilizerState.innerProduct(theta, phi) return 2**t * np.abs(projfactor * total)**2
def prepL(i, t, L): # compute bitstring by adding rows of l Lbits = list(np.binary_repr(i, width=len(L))) bitstring = np.zeros(t) for idx in range(len(Lbits)): if Lbits[idx] == '1': bitstring += L[idx] bitstring = bitstring.astype(int) % 2 # Stabilizer state is product of |0> and |+> # 1's in bitstring indicate positions of |+> # initialize stabilizer state phi = StabilizerState(t, t) # construct state using shrink for xtildeidx in range(t): if bitstring[xtildeidx] == 0: vec = np.zeros(t) vec[xtildeidx] = 1 phi.shrink(vec, 0) # |0> at index, inner prod with 1 is 0 # |+> at index -> do nothing return phi
def exactThread(args): (P, L, i) = args (phases, xs, zs) = P t = len(xs[0]) if L is None: size = int(np.ceil(t/2)) else: size = len(L) total = 0 if L is None: theta = prepH(i, t) else: theta = prepL(i, t, L) projfactor = 1 for g in range(len(phases)): res = theta.measurePauli(phases[g], zs[g], xs[g]) projfactor *= res if res == 0: return 0 # theta annihilated by P for j in range(0, 2**size): if L is None: phi = prepH(j, t) else: phi = prepL(j, t, L) inner = StabilizerState.innerProduct(theta, phi) total += inner * projfactor return total
def load(psi): state = StabilizerState(psi["n"], psi["k"]) state.G = np.array(psi["G"]) state.Gbar = np.array(psi["Gbar"]) state.h = np.array(psi["h"]) if "D" in psi: state.D = np.array(psi["D"])[:state.k] state.J = np.array(psi["J"])[:state.k, :state.k] * 4 state.Q = psi["Q"] return state
def evalHcomponent(args): (i, _, theta, t) = args # unpack arguments (easier for parallel code) size = int(np.ceil(t/2)) odd = t % 2 == 1 bits = list(np.binary_repr(i, width=size)) # initialize stabilizer state phi = StabilizerState(t, t) for idx in range(size): bit = int(bits[idx]) if bit == 0 and not (odd and idx == size-1): # phi.J = np.array([[0, 4], [4, 0]]) phi.J[idx*2+1, idx*2] = 4 phi.J[idx*2, idx*2+1] = 4 for idx in range(size): bit = int(bits[idx]) vec = np.zeros(t) if odd and idx == size-1: vec[t-1] = 1 # last qubit: |H> = (1/2v)(|0> + |+>) if bit == 0: phi.measurePauli(0, vec, np.zeros(t)) # |0>, measure Z else: phi.measurePauli(0, np.zeros(t), vec) # |+>, measure X continue if bit == 0: continue vec[idx*2+1] = 1 vec[idx*2] = 1 phi.measurePauli(0, np.zeros(t), vec) # measure XX phi.measurePauli(0, vec, np.zeros(t)) # measure ZZ return StabilizerState.innerProduct(theta, phi)
def evalLcomponent(args): (i, L, theta, t) = args # unpack arguments (easier for parallel code) # compute bitstring by adding rows of l Lbits = list(np.binary_repr(i, width=len(L))) bitstring = np.zeros(t) for idx in range(len(Lbits)): if Lbits[idx] == '1': bitstring += L[idx] bitstring = bitstring.astype(int) % 2 # Stabilizer state is product of |0> and |+> # 1's in bitstring indicate positions of |+> # initialize stabilizer state phi = StabilizerState(t, t) # construct state by measuring paulis for xtildeidx in range(t): vec = np.zeros(t) vec[xtildeidx] = 1 if bitstring[xtildeidx] == 1: # |+> at index, so measure X phi.measurePauli(0, np.zeros(t), vec) else: # |0> at index, so measure Z phi.measurePauli(0, vec, np.zeros(t)) return StabilizerState.innerProduct(theta, phi)
def sampleProjector(args): (P, L, seed, parallel) = args # unpack arguments (easier for parallel code) (phases, xs, zs) = P # empty projector if len(phases) == 0: return 1 t = len(xs[0]) # clifford circuit if t == 0: lookup = {0: 1, 2: -1} generators = [1] # include identity for phase in phases: generators.append(lookup[phase]) # calculate sum of all permutations of generators return sum(generators)/len(generators) # set unique seed for this calculation # np.random.seed((seed) % 4294967296) # sample random theta theta = StabilizerState.randomStabilizerState(t) # project random state to P projfactor = 1 for g in range(len(phases)): res = theta.measurePauli(phases[g], zs[g], xs[g]) projfactor *= res # if res == 0: return 0 # theta annihilated by P if L is None: # use exact decomp into pairs of stabilizer states func = evalHcomponent size = int(np.ceil(t/2)) # need one bit for each pair, plus one more if t is odd else: func = evalLcomponent size = len(L) parallel = False if parallel: # parallelize for large enough L pool = Pool() total = sum(pool.map(func, [(i, L, theta, t) for i in range(0, 2**size)])) pool.close() pool.join() else: total = sum(map(func, [(i, L, theta, t) for i in range(0, 2**size)])) return 2**t * np.abs(projfactor*total)**2
def load(psi): state = StabilizerState(psi["n"], psi["k"]) state.G = np.array(psi["G"]) state.Gbar = np.array(psi["Gbar"]) state.h = np.array(psi["h"]) if "D" in psi: state.D = np.array(psi["D"])[:state.k] state.J = np.array(psi["J"])[:state.k, :state.k]*4 state.Q = psi["Q"] return state
def prepH(i, t): size = int(np.ceil(t / 2)) odd = t % 2 == 1 bits = list(np.binary_repr(i, width=size)) # initialize stabilizer state phi = StabilizerState(t, t) # set J matrix for idx in range(size): bit = int(bits[idx]) if bit == 0 and not (odd and idx == size - 1): # phi.J = np.array([[0, 4], [4, 0]]) phi.J[idx * 2 + 1, idx * 2] = 4 phi.J[idx * 2, idx * 2 + 1] = 4 # truncate affine space using shrink for idx in range(size): bit = int(bits[idx]) vec = np.zeros(t) if odd and idx == size - 1: # bit = 0 is |+> # bit = 1 is |0> if bit == 1: vec[t - 1] = 1 phi.shrink(vec, 0) continue # bit = 1 corresponds to |00> + |11> state # bit = 0 corresponds to |00> + |01> + |10> - |11> if bit == 1: vec[idx * 2] = 1 vec[idx * 2 + 1] = 1 phi.shrink(vec, 0) # only 00 and 11 have inner prod 0 with 11 return phi
def exactProjectorWork(args): (P, L, l) = args (phases, xs, zs) = P t = len(xs[0]) if L is None: size = int(np.ceil(t / 2)) else: size = len(L) chi = 2**size i = 0 while l >= chi - i: l -= chi - i i += 1 j = l + i if L is None: theta = prepH(i, t) else: theta = prepL(i, t, L) projfactor = 1 for g in range(len(phases)): res, status = theta.measurePauli(phases[g], zs[g], xs[g], give_status=True) projfactor *= res if res == 0: return 0 # theta annihilated by P if L is None: phi = prepH(j, t) else: phi = prepL(j, t, L) inner = StabilizerState.innerProduct(theta, phi) if i == j: return inner * projfactor else: return 2 * np.real(inner) * projfactor
f = open(directory + "ExponentialSum.txt") tests = json.loads(f.read()) # tests = [] indexcut = 0 failed = 0 index = 0 starttime = datetime.now() for test in tests: index += 1 if index < indexcut: continue # don't actually depend on n, but need for initialization k = len(test["D"]["D"]) # k = 4 state = StabilizerState(k, k) # state.D = np.array(test["D"]["D"])[:4] state.D = np.array(test["D"]["D"]) # state.J = np.array(test["J"]["J"])[:4, :4]*4 state.J = np.array(test["J"]["J"])*4 state.Q = test["Q"]["Q"] (eps, p, m) = state.exponentialSum(exact=True) if eps != test["eps_out"]\ or m != test["m_out"] % 8\ or p != test["p_out"]: if failed == 0: print("ExponentialSum errors:") print("ExponentialSum %d (k=%d) failed: (%d,%d,%d) should be (%d,%d,%d)" % (index, state.k, eps, p, m, test["eps_out"], test["p_out"], test["m_out"])) failed += 1 # break
f = open(directory + "ExponentialSum.txt") tests = json.loads(f.read()) tests = [] indexcut = 0 failed = 0 index = 0 starttime = datetime.now() for test in tests: index += 1 if index < indexcut: continue # don't actually depend on n, but need for initialization k = len(test["D"]["D"]) # k = 4 state = StabilizerState(k, k) # state.D = np.array(test["D"]["D"])[:4] state.D = np.array(test["D"]["D"]) # state.J = np.array(test["J"]["J"])[:4, :4]*4 state.J = np.array(test["J"]["J"]) * 4 state.Q = test["Q"]["Q"] (eps, p, m) = state.exponentialSum(exact=True) if eps != test["eps_out"]\ or m != test["m_out"] % 8\ or p != test["p_out"]: if failed == 0: print("ExponentialSum errors:") print( "ExponentialSum %d (k=%d) failed: (%d,%d,%d) should be (%d,%d,%d)" % (index, state.k, eps, p, m, test["eps_out"], test["p_out"], test["m_out"]))