def __initrealoperatorbasis(self): self.operatorbasis = [] for i in arange(self.__dimH): tmp = zeros(self.__dim, dtype=numpy.complex128) tmp[i,i] = 1. self.operatorbasis += [hoperator(tmp,self.__dimsubs)] for x in arange(self.__dimH): for y in arange(x+1,self.__dimH): tmp = zeros(self.__dim, dtype=numpy.complex128) tmp[x,y] = tmp[y,x] = 1. self.operatorbasis += [hoperator(tmp,self.__dimsubs)]
def setoperatorbasis(self,opbasis=[]): """ Set an custom operator basis If this basis does not span the full operator space the resulting witnesses lie within the subspace only opbasis : list of array_like A list of array_like objects representing a basis in the space of operators/observables. Try to find the optimal witness within the operator subspace spanned by pauli operators X,Y,Z and qubit identity matrices (1): 111, XXZ, XZX, ZXX, ZZZ >>> from gmntools import gmn, pauli >>> qb_3 = pauli([2,2,2]) >>> basis = [qb_3.operator(i) for i in ['eee','xxz','xzx','zxx','zzz']] >>> ghz = [[.5,0,0,0,0,0,0,.5],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[.5,0,0,0,0,0,0,.5]] >>> gmntool = gmn([2,2,2],ghz) By default a complete basis is used >>> gmntool.gmn() 0.499999998369068 There is no witness within the subspace detecting the GHZ state >>> gmntool.setoperatorbasis(basis) >>> gmntool.gmn() -3.646152630556347e-08 To reset to the full standard basis call the function without argument >>> gmntool.setoperatorbasis() >>> gmntool.gmn() 0.499999998369068 """ self.operatorbasis = [hoperator(o,self.__dimsubs) for o in opbasis]
def __W(self,sol): nop = len(self.operatorbasis) self.W = {} W = numpy.sum([sol['x'][index]*op.matrix for index,op in enumerate(self.operatorbasis)],axis=0) self.W['W'] = W for i in range(1,2**(self.__nsys -1)): temp = map(int,numpy.binary_repr(i,self.__nsys)) subsys = [] for index,j in enumerate(temp): if j ==1: subsys.append(index) m = (str(subsys)+'|'+str([l for l in range(1,self.__nsys+1) if l not in subsys])).replace('[','').replace(']','').replace(' ','') Pm = numpy.sum([sol['x'][i*nop+k]*op.matrix for k,op in enumerate(self.operatorbasis)],axis=0) self.W['P_'+m] = Pm self.W['Q_'+m] = hoperator(W-Pm,self.__dimsubs).ptranspose(subsys) return 0
def gmn_partial_info_ppt(self,meas,real=False,altsolver=None): """ Lower bound the genuine multiparticle negativity as given in Ref. [*] based on incomplete tomographic data without the need of state reconstruction. Here, however, fully PPT witnesses are used compared to fully decomposable witnesses in the gmn_partial_info memberfunction. Hence, fewer states are detected and in general more measurements are needed. [*] M. Hofmann, T. Moroder, and O. Guhne, J. Phys. A: Math. Theor. 47 155301 (2014). meas : list of tuples A list of tuples. The first entry of the tuple is an array_like object representing the measurement operator. The second entry represents the measured value. real : Boolean Set to true if the densitymatrix has real eigenvalues only to speed up computation. Use the memberfuction setrealbasis() or manually set a real operator basis to optimize the gain. altsolver : None or 'dsdp' If you have the solver DSDP5.8 installed on your system use it for optimal performance As example consider the W state >>> w = [[0,0,0,0,0,0,0,0],[0,1./3.,1./3.,0,1./3.,0,0,0],[0,1./3.,1./3.,0,1./3.,0,0,0],[0,0,0,0,0,0,0,0],[0,1./3.,1./3.,0,1./3.,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0]] As in the memberfunction gmn_partial_info measure the W state in just four directions given by tensor products of Pauli operators XXZ, XZX, ZXX, ZZZ >>> from gmntools import gmn, pauli >>> from numpy import trace, dot >>> pauliop = pauli(3) >>> measurements = [pauliop.operator(i) for i in ['xxz','xzx','zxx','zzz'] ] >>> meas_w = [(o,trace(dot(w,o)).real) for o in measurements] Initialize gmn class >>> gmntool = gmn([2,2,2]) No fully PPT witness can be constructed from the given measurements, which can detect the W state >>> gmntool.setrealbasis() >>> gmntool.gmn_partial_info(meas_w) -4.6050924423687366e-10 """ measurements = list(meas) if type(measurements) is not list: if [m for m in measurements if (type(m) is not tuple and type(m) is not list) or len(m)!=2 or type(m[1]) not in [int,complex,float,long]]: raise TypeError("'mesurements' must be a list of tuples containing the measured operator and its expectation value '(operator,expectation_value)'") measurements += [(eye(self.__dimH,dtype=numpy.complex128),1.)] #setting up SDP ##setting up problem vector nmes= len(measurements) mesop = [hoperator(m[0],self.__dimsubs) for m in measurements] c = zeros(nmes, dtype=numpy.float64) for index,o in enumerate(measurements): c[index] = o[1] ##setting up semidefinite constraints F0 = [] F = [] ##setting up constraint W^(T_m) >= 0 for i in range(1,2**(self.__nsys -1)): temp = map(int,numpy.binary_repr(i,self.__nsys)) subsys = [] for index,j in enumerate(temp): if j ==1: subsys.append(index) F0 += [zeros(self.__dim)] F += [[o.ptranspose(subsys) for o in mesop]] ##setting up constraint W^(T_m) <= 1 for i in range(1,2**(self.__nsys -1)): temp = map(int,numpy.binary_repr(i,self.__nsys)) subsys = [] for index,j in enumerate(temp): if j ==1: subsys.append(index) F0 += [eye(self.__dimH)] F += [[-o.ptranspose(subsys) for o in mesop]] sol = self.__solve(c,F0,F,real,altsolver) self.status = sol['status'] return -sol['primal objective']