def applyCH(self, state: chstate.CHState) -> chstate.CHState: t = state.s ^ (state.G[self.target] * state.v) u = (state.s ^ (state.F[self.target] * np.uint8(1 - state.v)) ^ (state.M[self.target] * state.v)) alpha = (state.B[self.target] * np.uint8(1 - state.v) * state.s).sum() beta = (state.C[self.target] * np.uint8(1 - state.v) * state.s + state.A[self.target] * state.v * (state.C[self.target] + state.s)).sum() if all(t == u): state.s = t state.phase = state.phase * ( (-1)**alpha + (complex(0, 1)**state.g[self.target]) * (-1)**beta) / np.sqrt(2) return state else: phase, VCList, v, s = util.desuperpositionise( t, u, np.uint8((state.g[self.target] + 2 * (alpha + beta))) % constants.UNSIGNED_4, state.v) state.phase *= phase state.phase *= (-1)**alpha / np.sqrt( 2) # sqrt(2) since H = (X + Z)/sqrt(2) state.v = v state.s = s for gate in VCList: gate.rightMultiplyC(state) return state
def rightMultiplyC(self, state: chstate.CHState) -> chstate.CHState: state.C[:, self.target] = state.C[:, self.target] ^ state.A[:, self.target] state.g = np.uint8(state.g - state.A[:, self.target]) % constants.UNSIGNED_4 return state
def applyCH(self, state: chstate.CHState) -> chstate.CHState: alpha = np.uint8((state.G[self.target] * (1 - state.v) * state.s).sum() % np.uint8(2)) state.s = np.uint8( (state.s + state.G[self.target] * state.v) % np.uint8(2)) state.phase *= (-1)**alpha return state
def applyCH(self, state: chstate.CHState) -> chstate.CHState: #apply commutation rules to get (1/2) (1+ (-1)^a Z_p) UC UH |s> = (1/2) UC UH (1 + (-1)^a (prod_j Z_j^{G_{pj} (1-v_j)} X_j^{G_{pj}^{v_j}} )) |s> #then we apply the unitaries to |s> to get # UC UH (|s> + (-1)^(k+a) |t>) k = self.a + (state.B[self.target] * np.uint8(1 + state.v) * state.s).sum(dtype=np.uint8) % np.uint8(2) t = np.uint8((state.B[self.target] * state.v) ^ state.s) if all(t == state.s): state.phase *= (1 + (-1)**k) / 2 else: phase, VCList, v, s = util.desuperpositionise( state.s, t, np.uint8(2 * k % constants.UNSIGNED_4), state.v) for gate in VCList: gate.rightMultiplyC(state) state.phase *= phase / 2 # 2 since P = (I +- Z)/2 state.v = v state.s = s return state
def rightMultiplyC(self, state: chstate.CHState) -> chstate.CHState: state.C[:, self.control] = state.C[:, self.control] ^ state.A[:, self.target] state.C[:, self.target] = state.C[:, self.target] ^ state.A[:, self.control] state.g = (state.g + 2 * state.A[:, self.control] * state.A[:, self.target]) % constants.UNSIGNED_4 return state
def leftMultiplyC(self, state: chstate.CHState) -> chstate.CHState: permutation = list(range(state.N)) permutation[self.a] = self.b permutation[self.b] = self.a state.A = state.A[permutation][:, permutation] state.B = state.B[permutation][:, permutation] state.C = state.C[permutation][:, permutation] state.g = state.g[permutation] state.v = state.v[permutation] state.s = state.s[permutation] return state
from measurement import MeasurementOutcome from chstate import CHState import constants from gates.cliffords import SGate, CXGate, HGate, PauliZProjector import itertools import util import random import qk from numpy import linalg if __name__ == "__main__": np.set_printoptions(linewidth=128) #makes printing long matrices a bit better sometimes #produce the 3 qubit |000> state1 = CHState.basis(N=3) #produce the 2 qubit |01> state2 = CHState.basis(s=[0,1]) #produce the 3 qubit |111> state3 = CHState.basis(s=[1,1,1]) #print state1 in the form N F G M gamma v s w #where N is number of qubits, F, G, M and NxN matrices, gamma, v and s are column vectors and w is a complex number #looks like """ 3 100 100 000 0 0 0 (1+0j) 010 010 000 0 0 0 001 001 000 0 0 0 """
def rightMultiplyC(self, state: chstate.CHState) -> chstate.CHState: state.v = state.v[permutation] state.s = state.s[permutation] return state