def WalkWithExperimentalNoise(U,eps,pairs,refs=(0,0),losses=None,seed=None): '''Return a unitary with noise applied as Poissonian noise in both amplitude and phase reconstructions. Function assumes U is a quantum walk unitary, therefore all elements in real-bordered form are real and only signs must be deduced from dips. These signs are determined by taking single point measurements for classical and quantum coincidences, rather than fitting a full dip. U : (ideal) unitary to apply noise to eps : error in power meter readings for amplitudes pairs : rate of coincidence counts for Poissonian noise refs : reference row and column (respectively) for phases losses : input and output losses seed : (optional) seed for rng return : (numpy array) unitary with noise applied''' # Get the amplitudes V=numpy.abs(PowerMeterNoise(U,eps,losses,seed)) # Get the phases nrows,ncols=U.shape refrow,refcol=refs rows=range(nrows) rows.remove(refrow) cols=range(ncols) cols.remove(refcol) for i in rows: for j in cols: # Get the phase (sign) cmean=float(pairs)*(hamiltomo.abs2(U[refrow,refcol]*U[i,j])+\ hamiltomo.abs2(U[refrow,j]*U[i,refcol])) qmean=float(pairs)*hamiltomo.abs2(U[refrow,refcol]*U[i,j]+\ U[refrow,j]*U[i,refcol]) if cmean<1000: # Poissonian classical=numpy.random.poisson(cmean) else: # Gaussian approximation classical=numpy.random.normal(cmean,numpy.sqrt(cmean)) if qmean<1000: # Poissonian quantum=numpy.random.poisson(qmean) else: # Gaussian approximation quantum=numpy.random.normal(qmean,numpy.sqrt(qmean)) #if cmean > qmean: if classical > quantum: # Dip => negative sign V[i,j]*=float(-1) return V
def UnitaryFidelity(U,V): '''Distance measure between two unitary matrices. Uses a trace distance (1/N) Tr(U^V) U : reference matrix (always unitary) V : test matrix (not necessarily unitary) return : (float) trace distance between U and V''' dim=U.shape[0] uv=numpy.dot(U, hamiltomo.dagger(V)) return hamiltomo.abs2((1./dim)*sum(uv.flatten()[0::dim+1]))
def PowerMeterNoise(U,eps,losses=None,seed=None): '''Return a unitary with noise applied as +-eps on power meter readings but ideal phases. The total power in each column (i.e. input) is 1. U : unitary to apply noise to eps : error on power meter readings losses : input and output losses seed : (optional) seed for rng return : (numpy array) unitary with noise applied''' dim=U.shape[0] # assume square amps=hamiltomo.abs2(U) rng=Random(seed) if losses is None: losses=numpy.ones((2,dim)) V=numpy.zeros_like(U) for i in range(dim): for j in range(dim): amp=numpy.sqrt(max(amps[i,j]*losses[0,j]*losses[1,i]+rng.gauss(0,eps),0)) phase=U[i,j]/abs(U[i,j]) V[i,j]=amp*phase pre,V,post=hamiltomo.Normalise(V,eps=1e-10,maxiter=200) return V