def kronN(self, Us): n = len(Us) if n == 2: return npml.kron(Us[0], Us[1]) elif n > 2: return npml.kron(Us[0], self.kronN(Us[1:])) else: return Us[0]
def KrausToChoi(Kraus): # kraus input should be of the form kraus[k,:,:] NumberOfQubits = int(np.log2(Kraus[0,:,:].shape[1])) rhoout = np.zeros((2**(2*NumberOfQubits),2**(2*NumberOfQubits)),dtype=complex) NumOfOperators = Kraus.shape[0] id = np.diag(np.ones(2**NumberOfQubits)) choi = ChoiIn(NumberOfQubits) for k in xrange(NumOfOperators): rhoout += np.dot(npml.kron(id,Kraus[k,:,:]), np.dot(choi, npml.kron(id,Kraus[k,:,:]).transpose().conjugate())) return rhoout
def Hamiltonian_timedep_complete(self, targetion, omrabi, phase, detuning, wsec, eta, hspace, LDApprox = False): """ everything in the full interaction frame of the ions including the harmonic oscillation (opposing to the original version from hartmut that still had the phonon energy nonzero) in addition, this version won't omit the exp(+- i omega_z terms t) in attached to creation/annihilation operators this is eqn 3.6 in Christian Roo's thesis. """ # H = exp(i delta_c t+phase) omega(t) (sum_i address_error_i sigma_plus_i) (exp(i eta (a exp(-i omegaz t) + adag exp(i omegaz t)))) + h.c. # !!! note !!! # here eta is assumed to be the same for all qubits. this is # not necessarily the case. #a more correct version would allow for # individual etas for each qubit ... maybe later. not # really required here and would only slow down the code targetion = targetion[::-1] # prefactor including the timedepending omega and the detuning+phase prefac = lambda t: np.exp(1j * (detuning * t + phase)) * omrabi(t) * 1/2. # coupling to the sideband. argument of the exponent/ld approximation LDpart = lambda t: 1j * eta[-1] * (hspace.operator_dict['a'] * np.exp(-1j * wsec * t ) + hspace.operator_dict['a_dag'] * np.exp(1j * wsec * t ) ) # calculate the coupling based on the addressing errors sys = np.zeros((hspace.levels**hspace.nuions,hspace.levels**hspace.nuions)) for k in xrange(hspace.nuions): sys += targetion[k]*hspace.operator_dict['raising'][:,:,k] # Lamb-Dicke approximation yes/no? # kron with qubits to get the hamiltonian if LDApprox: sys_ho = lambda t: npml.kron( sys, np.diag(np.ones(hspace.maxphonons+1)) + LDpart(t) ) else: sys_ho = lambda t: npml.kron( sys, splg.expm2( LDpart(t)) ) # multiply with rabi-frequency part H = lambda t: prefac(t) * sys_ho(t) # add h.c. part HT = lambda t: H(t)+H(t).transpose().conjugate() return HT
def chirotinfidel(rot_vector, ideal_chi, my_chi,return_chi=False): "The infidelity function" NrOfQubits = int(len(rot_vector)/3) # rz = expm(-1j*pi/2 * rot_vector[0] * X) # ry = expm(-1j*pi/2 * rot_vector[1] * Y) # rx = expm(-1j*pi/2 * rot_vector[2] * X) R = lambda rot_vector: np.dot(expm(-1j*pi/2 * rot_vector[2] * X),np.dot(expm(-1j*pi/2 * rot_vector[1] * Y),expm(-1j*pi/2 * rot_vector[0] * X))) Rtot = 1 AllPaulis = [1] for k in xrange(NrOfQubits): Rtot = npml.kron(Rtot, R(rot_vector[3*k:3*k+3])) AllPaulis = proctom.baseappend(AllPaulis, Paulis) k = 0 l = 0 res1 = np.zeros((4**NrOfQubits,4**NrOfQubits),dtype=np.complex) for p_matrix in AllPaulis: RA = np.dot(Rtot, p_matrix) for p_matrix2 in AllPaulis: res0 = np.dot(p_matrix2.conj().T, RA) / 2**NrOfQubits res1[k,l] = np.trace(res0) l += 1 l = 0 k += 1 chirot = np.dot(res1.T,np.dot(my_chi, res1.conj())) # IF1 = np.real(1-np.trace(np.dot(ideal_chi,chirot))) # IF1 = np.real(1-np.sum(ideal_chi*chirot.transpose())) # IF = np.real(1-np.diag(np.dot(ideal_chi,chirot))) IF = np.real(1-np.sum(ideal_chi*chirot.transpose(),axis=1)) if return_chi: return chirot else: return IF
def Noise_spontdecay(self, params, dec): ''' randomly switch on projective matrix for spontaneous decay by setting HT to zero ''' ZeroMtx = params.hspace.operator_dict['zero'] cond = lambda t: bool(dec.spontdecayV[dec.decT == t][0]) if np.any(dec.decT==t) else False proj = params.hspace.operator_dict['proj'] projmtx = lambda t: npml.kron( self.R(proj, params.hspace.nuions, np.random.random_integers(0, params.hspace.nuions-1)), params.hspace.operator_dict['id_a'] ) randion = np.random.random_integers(0, params.hspace.nuions-1) jump = params.hspace.operator_dict['lowering'][:,:,randion] jumpop = npml.kron( jump, params.hspace.operator_dict['id_a'] ) jumpH = 0.5j * np.dot(jumpop.conj().transpose(), jumpop) noise = lambda t: projmtx(t) if cond(t) else ZeroMtx return noise
def baseappend(opin, opappend): len_opin = len(opin) len_opappend = len(opappend) opout = [] for k in xrange(len_opappend): for l in xrange(len_opin): opout.append(npml.kron(opappend[k],opin[l])) return opout
def baseappend(opin, opappend): len_opin = len(opin) len_opappend = len(opappend) opout = [] for k in range(len_opappend): for l in range(len_opin): opout.append(npml.kron(opappend[k],opin[l])) return opout
def Noise_spontdecayH(self, params, dec): ''' non-Hermitian Hamiltonian for spontaneous decay ''' jump = params.hspace.operator_dict['lowering'][:, :, -1] jumpop = npml.kron(jump, params.hspace.operator_dict['id_a']) jumpH = -0.5j * np.dot(jumpop.conj().transpose(), jumpop) noise = lambda t: jumpH return noise
def KrausToChoi(Kraus): # kraus input should be of the form kraus[k,:,:] NumberOfQubits = int(np.log2(Kraus[0, :, :].shape[1])) rhoout = np.zeros((2**(2 * NumberOfQubits), 2**(2 * NumberOfQubits)), dtype=complex) NumOfOperators = Kraus.shape[0] id = np.diag(np.ones(2**NumberOfQubits)) choi = ChoiIn(NumberOfQubits) for k in xrange(NumOfOperators): rhoout += np.dot( npml.kron(id, Kraus[k, :, :]), np.dot(choi, npml.kron(id, Kraus[k, :, :]).transpose().conjugate())) return rhoout
def Noise_spontdecayH(self, params, dec): ''' non-Hermitian Hamiltonian for spontaneous decay ''' jump = params.hspace.operator_dict['lowering'][:,:,-1] jumpop = npml.kron( jump, params.hspace.operator_dict['id_a'] ) jumpH = -0.5j * np.dot(jumpop.conj().transpose(), jumpop) noise = lambda t: jumpH return noise
def ACshift_corr(self, pulse, params): ''' extra term in HT to account for stark shift on S-P for ACstark pulse ''' hspace = params.hspace nuions = params.hspace.nuions sys = np.zeros((hspace.levels**hspace.nuions,hspace.levels**hspace.nuions)) for k in xrange(hspace.nuions): sys += hspace.operator_dict['sigz'][:,:,k] * pulse.targetion[nuions-k-1] hz = npml.kron( sys, hspace.operator_dict['id_a'] ) hz_diag = np.diag(hz) return params.ACcorr * pulse.omrabi**2 * hz_diag
def Noise_spontdecay(self, params, dec): ''' randomly switch on projective matrix for spontaneous decay by setting HT to zero ''' ZeroMtx = params.hspace.operator_dict['zero'] cond = lambda t: bool(dec.spontdecayV[dec.decT == t][0]) if np.any( dec.decT == t) else False proj = params.hspace.operator_dict['proj'] projmtx = lambda t: npml.kron( self.R(proj, params.hspace.nuions, np.random.random_integers(0, params.hspace.nuions - 1)), params.hspace.operator_dict['id_a']) randion = np.random.random_integers(0, params.hspace.nuions - 1) jump = params.hspace.operator_dict['lowering'][:, :, randion] jumpop = npml.kron(jump, params.hspace.operator_dict['id_a']) jumpH = 0.5j * np.dot(jumpop.conj().transpose(), jumpop) noise = lambda t: projmtx(t) if cond(t) else ZeroMtx return noise
def OSumToChoi(chi): """ map process representation in operator sum form into choi-jamilkowski density matrix representation """ NumberOfQubits = int(np.log2(chi.shape[0]) / 2) choi = ChoiIn(NumberOfQubits) id = np.diag(np.ones(2**NumberOfQubits)) # rewrote it to be faster using kron instead of generating a larger # chi matrix # generate the choi matrix of the doubled hilbert space # chi_choi = np.zeros((4**(2*NumberOfQubits),4**(2*NumberOfQubits))) # put the original chi matrix into the top corner so that it # acts onto the qubits 1->N but doesn't do anything to N+1->2N # chi_choi[0:4**(NumberOfQubits),0:4**(NumberOfQubits)] = chi # rho_choi = proctom.proc_channel_output(chi_choi, rho) rhoout = np.zeros((2**(2 * NumberOfQubits), 2**(2 * NumberOfQubits)), dtype=complex) A = proctom.proc_channel_operators(NumberOfQubits) for m in xrange(4**NumberOfQubits): for n in xrange(4**NumberOfQubits): rhoout += chi[m, n] * np.dot( npml.kron(id, A[:, :, m]), np.dot(choi, npml.kron(id, A[:, :, n]).transpose().conjugate())) rho_choi = rhoout return rho_choi
def Noise_heating(self, params, dec): ''' randomly switch on projective matrix for heating by setting HT to zero ''' ZeroMtx = params.hspace.operator_dict['zero'] cond = lambda t: bool(dec.heatingV[dec.decT == t][0]) if np.any(dec.decT==t) else False proj_a = params.hspace.operator_dict['a_dag'] proj_a[-1,-1] = 1 # make sure we don't exceed the phonon space projmtx = lambda t: npml.kron( np.eye(params.hspace.levels**params.hspace.nuions), proj_a ) noise = lambda t: projmtx(t) if cond(t) else ZeroMtx return noise
def Noise_heatingH(self, params, dec): ''' non-Hermitian Hamiltonian for heating ''' # TODO: fix. # this generates an operator with maxphonons/2*j on the diagonals # and causes an "overflow in exp" error in qctools jump = params.hspace.operator_dict['a_dag'] iden = np.eye(2**params.hspace.nuions) jumpop = npml.kron( iden, jump ) jumpH = -0.5j * np.dot(jumpop.conj().transpose(), jumpop) noise = lambda t: jumpH return noise
def Noise_heatingH(self, params, dec): ''' non-Hermitian Hamiltonian for heating ''' # TODO: fix. # this generates an operator with maxphonons/2*j on the diagonals # and causes an "overflow in exp" error in qctools jump = params.hspace.operator_dict['a_dag'] iden = np.eye(2**params.hspace.nuions) jumpop = npml.kron(iden, jump) jumpH = -0.5j * np.dot(jumpop.conj().transpose(), jumpop) noise = lambda t: jumpH return noise
def ACshift_corr(self, pulse, params): ''' extra term in HT to account for stark shift on S-P for ACstark pulse ''' hspace = params.hspace nuions = params.hspace.nuions sys = np.zeros( (hspace.levels**hspace.nuions, hspace.levels**hspace.nuions)) for k in xrange(hspace.nuions): sys += hspace.operator_dict['sigz'][:, :, k] * pulse.targetion[nuions - k - 1] hz = npml.kron(sys, hspace.operator_dict['id_a']) hz_diag = np.diag(hz) return params.ACcorr * pulse.omrabi**2 * hz_diag
def OSumToChoi(chi): """ map process representation in operator sum form into choi-jamilkowski density matrix representation """ NumberOfQubits = int(np.log2(chi.shape[0])/2) choi = ChoiIn(NumberOfQubits) id = np.diag(np.ones(2**NumberOfQubits)) # rewrote it to be faster using kron instead of generating a larger # chi matrix # generate the choi matrix of the doubled hilbert space # chi_choi = np.zeros((4**(2*NumberOfQubits),4**(2*NumberOfQubits))) # put the original chi matrix into the top corner so that it # acts onto the qubits 1->N but doesn't do anything to N+1->2N # chi_choi[0:4**(NumberOfQubits),0:4**(NumberOfQubits)] = chi # rho_choi = proctom.proc_channel_output(chi_choi, rho) rhoout = np.zeros((2**(2*NumberOfQubits),2**(2*NumberOfQubits)),dtype=complex) A = proctom.proc_channel_operators(NumberOfQubits) for m in xrange(4**NumberOfQubits): for n in xrange(4**NumberOfQubits): rhoout += chi[m,n] * np.dot(npml.kron(id,A[:,:,m]), np.dot(choi, npml.kron(id,A[:,:,n]).transpose().conjugate())) rho_choi = rhoout return rho_choi
def Noise_dephase(self, params, dec): ''' generate correlated dephasing error due to correlation, must pre-compute using dec.calcDephasing and search with searchsorted ''' hspace = params.hspace sys = np.zeros((hspace.levels**hspace.nuions,hspace.levels**hspace.nuions)) for k in xrange(hspace.nuions): sys += hspace.operator_dict['sigz'][:,:,k] noise_ho = npml.kron( sys, hspace.operator_dict['id_a'] ) noise = lambda t: dec.dephaseV[dec.decT.searchsorted(t)] * noise_ho \ if dec.decT.searchsorted(t) < len(dec.dephaseV) \ else dec.dephaseV[-1] * noise_ho return noise
def Noise_heating(self, params, dec): ''' randomly switch on projective matrix for heating by setting HT to zero ''' ZeroMtx = params.hspace.operator_dict['zero'] cond = lambda t: bool(dec.heatingV[dec.decT == t][0]) if np.any( dec.decT == t) else False proj_a = params.hspace.operator_dict['a_dag'] proj_a[-1, -1] = 1 # make sure we don't exceed the phonon space projmtx = lambda t: npml.kron( np.eye(params.hspace.levels**params.hspace.nuions), proj_a) noise = lambda t: projmtx(t) if cond(t) else ZeroMtx return noise
def Noise_dephase(self, params, dec): ''' generate correlated dephasing error due to correlation, must pre-compute using dec.calcDephasing and search with searchsorted ''' hspace = params.hspace sys = np.zeros( (hspace.levels**hspace.nuions, hspace.levels**hspace.nuions)) for k in xrange(hspace.nuions): sys += hspace.operator_dict['sigz'][:, :, k] noise_ho = npml.kron(sys, hspace.operator_dict['id_a']) noise = lambda t: dec.dephaseV[dec.decT.searchsorted(t)] * noise_ho \ if dec.decT.searchsorted(t) < len(dec.dephaseV) \ else dec.dephaseV[-1] * noise_ho return noise
def proc_channel_operators(NumberOfIons): """ return the operators A that we need for our quantum channels """ Paulis = getopbase() A = np.zeros((2**NumberOfIons, 2**NumberOfIons, 4**NumberOfIons),dtype=complex) # create operators for k in range(4**NumberOfIons): tmp = 1 for l in range(NumberOfIons): # print(np.mod(int(1.*k/4**l),4)) tmp = npml.kron(tmp,Paulis[np.mod(int(1.*k/4**l),4)]) A[:,:,k] = tmp return A
def proc_channel_operators(NumberOfIons): """ return the operators A that we need for our quantum channels """ Paulis = getopbase() A = np.zeros((2**NumberOfIons, 2**NumberOfIons, 4**NumberOfIons),dtype=complex) # create operators for k in xrange(4**NumberOfIons): tmp = 1 for l in xrange(NumberOfIons): # print np.mod(int(1.*k/4**l),4) tmp = npml.kron(tmp,Paulis[np.mod(int(1.*k/4**l),4)]) A[:,:,k] = tmp return A
def demo(): dat_2ions_id = np.loadtxt('2ion_proctomo_id.dat') dat_3ions_id = np.loadtxt('3ion_proctomo_id.dat') chi2exp = proctomo(dat_2ions_id, NumberOfIterations = 50) # chi3id = proctomo(dat_3ions_id, NumberOfIterations = 50) if chi2exp[0,0] > 0.95: print 'passed' #chi1id = np.zeros((4**1,4**1)) #chi1id[0,0] = 1 # chi1exp = np.array([ # [.5, 0, 0, -0.5j], # [0, 0, 0, 0], # [0, 0, 0, 0], # [0.5j, 0, 0, 0.5], # ]) chi1exp = np.array([ [0.25, 0, 0, 0.25], [0, 0.25, -0.25j, 0], [0, 0.25j, 0.25, 0], [0.25, 0, 0, 0.25], ]) # chi1exp = np.array([ # [0.5, 0, 0, -0.5j], # [0, 0., 0., 0], # [0, 0., 0., 0], # [0.5j, 0, 0, 0.5], # ]) # a = mean_process_fidelity(chi1exp, chi1id,type_rho_distribution = 'PureHaar',NumberOfSampleStates = 10) rho1 = np.array([[0.5, 0.5],[.5, .5]]) rhoo = proc_channel_output(chi1exp, rho1) print rhoo a = getopbase() A = baseappend(a,a) print np.all(npml.kron(a[0],a[1]) == A[1])
def demo(): dat_2ions_id = np.loadtxt('2ion_proctomo_id.dat') dat_3ions_id = np.loadtxt('3ion_proctomo_id.dat') chi2exp = proctomo(dat_2ions_id, NumberOfIterations = 50) # chi3id = proctomo(dat_3ions_id, NumberOfIterations = 50) if chi2exp[0,0] > 0.95: print('passed') #chi1id = np.zeros((4**1,4**1)) #chi1id[0,0] = 1 # chi1exp = np.array([ # [.5, 0, 0, -0.5j], # [0, 0, 0, 0], # [0, 0, 0, 0], # [0.5j, 0, 0, 0.5], # ]) chi1exp = np.array([ [0.25, 0, 0, 0.25], [0, 0.25, -0.25j, 0], [0, 0.25j, 0.25, 0], [0.25, 0, 0, 0.25], ]) # chi1exp = np.array([ # [0.5, 0, 0, -0.5j], # [0, 0., 0., 0], # [0, 0., 0., 0], # [0.5j, 0, 0, 0.5], # ]) # a = mean_process_fidelity(chi1exp, chi1id,type_rho_distribution = 'PureHaar',NumberOfSampleStates = 10) rho1 = np.array([[0.5, 0.5],[.5, .5]]) rhoo = proc_channel_output(chi1exp, rho1) print(rhoo) a = getopbase() A = baseappend(a,a) print(np.all(npml.kron(a[0],a[1]) == A[1]))
def Hamiltonian_timedep_complete(self, targetion, omrabi, phase, detuning, wsec, eta, hspace, LDApprox=False): """ everything in the full interaction frame of the ions including the harmonic oscillation (opposing to the original version from hartmut that still had the phonon energy nonzero) in addition, this version won't omit the exp(+- i omega_z terms t) in attached to creation/annihilation operators this is eqn 3.6 in Christian Roo's thesis. """ # H = exp(i delta_c t+phase) omega(t) (sum_i address_error_i sigma_plus_i) (exp(i eta (a exp(-i omegaz t) + adag exp(i omegaz t)))) + h.c. # !!! note !!! # here eta is assumed to be the same for all qubits. this is # not necessarily the case. #a more correct version would allow for # individual etas for each qubit ... maybe later. not # really required here and would only slow down the code targetion = targetion[::-1] # prefactor including the timedepending omega and the detuning+phase prefac = lambda t: np.exp(1j * (detuning * t + phase)) * omrabi(t) * 1 / 2. # coupling to the sideband. argument of the exponent/ld approximation LDpart = lambda t: 1j * eta[-1] * (hspace.operator_dict['a'] * np.exp( -1j * wsec * t) + hspace.operator_dict['a_dag'] * np.exp(1j * wsec * t)) # calculate the coupling based on the addressing errors sys = np.zeros( (hspace.levels**hspace.nuions, hspace.levels**hspace.nuions)) for k in xrange(hspace.nuions): sys += targetion[k] * hspace.operator_dict['raising'][:, :, k] # Lamb-Dicke approximation yes/no? # kron with qubits to get the hamiltonian if LDApprox: sys_ho = lambda t: npml.kron( sys, np.diag(np.ones(hspace.maxphonons + 1)) + LDpart(t)) else: sys_ho = lambda t: npml.kron(sys, splg.expm2(LDpart(t))) # multiply with rabi-frequency part H = lambda t: prefac(t) * sys_ho(t) # add h.c. part HT = lambda t: H(t) + H(t).transpose().conjugate() return HT
delta_t = 0.01 T0 = 0 Tmax = 1 T = np.arange(delta_t, Tmax, delta_t) Y = -1 * np.ones((len(T), 4), dtype='complex128') Pop = -1 * np.ones((len(T), 4)) # ------------------ # interaction/hamiltonian rabi = 2 * np.pi * 2 beatfreq = 2 * np.pi * 4 id = np.diag(np.array([1, 1])) sigmax = 1. / 2 * np.array([[0, 1], [1, 0]]) Hint = rabi * npml.kron(id, sigmax) H0 = np.diag(np.array([0, 0, 1, 1])) * 100 H = lambda t: (1 + np.cos(beatfreq * t)) / 2 * Hint + H0 # input state psiin = np.array([0, 1, 0, 0]) #psiin = 1./np.sqrt(2)* np.array([1,1]) tcur = T0 b = ODE_timeevo(H, T0, Tmax, delta_t, psiin) t2 = time.time() a = Chebyshev_timeevo(H, T0, Tmax, delta_t, psiin) print('chebyshev evo: ', time.time() - t2)
def proctomo(data, NumberOfIterations = 100, use_bell_basis=False): """Process tomography for an arbitrary number of ions Params data: either datafile string or a a cprb matrix NumberOfIterations: Number of iterations for the maximum likelihood algorithm """ Paulis = getopbase() NumberOfIons = np.int(np.log2(data.shape[1]-1)) RhoIn, Obs, ObsVal, NRho, NObs = LoadProctomData(data) # tic = time.time() RhoTObs = np.zeros((NRho*NObs,4**NumberOfIons,4**NumberOfIons),dtype=complex) TransposedRhoTObs = np.zeros((NRho*NObs,4**NumberOfIons,4**NumberOfIons),dtype=complex) for m in xrange(NRho): for n in xrange(NObs): tmp = npml.kron(RhoIn[m,:,:].transpose(),Obs[n,:,:]) RhoTObs[m*NObs+n,:,:] = tmp TransposedRhoTObs[m*NObs+n,:,:] = tmp.transpose() del RhoIn, Obs, tmp # TransposedRhoTObs[m*NObs+n,:,:] = transpose(RhoTObs[m*NObs+n,:,:]) # print time.time()-tic,'seconds' # reserving some more memory space QOps = np.zeros((2**NumberOfIons,2**NumberOfIons,(2**NumberOfIons)**2)) QOps2 = np.zeros((2**NumberOfIons,2**NumberOfIons,(2**NumberOfIons)**2), dtype = complex) AB = np.zeros((4**NumberOfIons,4**NumberOfIons), dtype = complex) AA = np.zeros((4**NumberOfIons,4**NumberOfIons), dtype = complex) v = np.eye(2**NumberOfIons); # Quantenoperatoren for m in xrange(2**NumberOfIons): for n in xrange(2**NumberOfIons): QOps[:,:,n+2**NumberOfIons*m] = np.outer(v[:,m],v[:,n]) for k in xrange(4**NumberOfIons): Op_tmp = 1 for l in xrange(NumberOfIons): Op_tmp = npml.kron(Paulis[np.mod(k/4**l,4)],Op_tmp) QOps2[:,:,k]=Op_tmp for m in xrange(4**NumberOfIons): for n in xrange(4**NumberOfIons): AB[m,n] = np.sum(QOps[:,:,m]*np.transpose(QOps2[:,:,n])) AA[m,n] = np.sum(QOps[:,:,m]*np.transpose(QOps[:,:,n])) C = np.dot(lnlg.inv(AB), AA) del AB, AA, QOps, QOps2 # -------------------------- dimH = 2**NumberOfIons dimK = dimH idH = np.eye(dimH) idK = np.eye(dimK) S0 = 1.*npml.kron(idH,idK)/dimK Kstart = np.zeros((4**NumberOfIons,4**NumberOfIons)) # -------------------------- #print RhoTObs.imag.max() ObsValCalc = np.zeros(NRho*NObs) #S = np.zeros(((2**NumberOfIons)**2,(2**NumberOfIons)**2)) # tic = time.time() for k in xrange(NumberOfIterations): ObsValCalc2 = np.real(np.sum(np.sum(npml.multiply(S0, TransposedRhoTObs), axis = 1), axis = 1)) # for mn in xrange(NRho*NObs): # ObsValCalc[mn] = np.sum(S0*np.transpose(RhoTObs[mn,:,:])) # alternative: this seems to be a factor of 2 faster for 2 ions, but becomes a factor of two slower for 3 ions ... # S0_long = tile(S0,(NRho*NObs,1,1)) # ObsValCalc = sum(sum(S0_long*TransposedRhoTObs,axis=2),axis=1) # tensordot(a,b,(0,0)) does something like sum_i a[i]*b[i,:,:] K = np.tensordot(ObsVal/ObsValCalc2,RhoTObs,(0,0)) # lagrange multiplication lamquad = __ptrace(np.dot(K,np.dot(S0,K)),dimH,dimK,2) # here is some complain about real/imag definitions ... laminv = lnlg.inv(lnlg.sqrtm(lamquad)) Laminv = npml.kron(laminv,idK) # new s-matrix S = np.dot(Laminv,np.dot(K,np.dot(S0,np.dot(K,Laminv)))) S0 = S # print time.time()-tic,'seconds' # calculate corresponding chi matrix # all the info is in the S matrix V = np.zeros(((2**NumberOfIons)**2,(2**NumberOfIons)**2)) for q in xrange(2**NumberOfIons): for m in xrange(2**NumberOfIons): V[:,q+2**NumberOfIons*m] = npml.kron(v[:,q],v[:,m]) Chi = np.zeros(((2**NumberOfIons)**2,(2**NumberOfIons)**2),dtype = complex) for p in xrange(4**NumberOfIons): for q in xrange(4**NumberOfIons): Chi[p,q] = np.dot(np.conjugate(np.transpose(V[:,p])),np.dot(S,V[:,q])) Chi_final = np.dot(C,np.dot(Chi,np.transpose(np.conjugate(C)))) return Chi_final
def Hamiltonian(self, pulse, params, LDApprox=True): ''' Hamiltonian definition using hspace.operator_dict ''' opdict = params.hspace.operator_dict targetion = pulse.targetion[::-1] omrabi = pulse.omrabi phase = pulse.phase detuning = pulse.detuning wsec = params.omz eta = params.eta hspace = params.hspace # prefactor including the timedepending omega and the detuning+phase prefac = np.exp(1j * phase) * omrabi * 1 / 2. # coupling to the sideband. argument of the exponent/ld approximation LDpart = 1j * eta[-1] * (opdict['a'] + opdict['a_dag']) # calculate the coupling based on the addressing errors # Lamb-Dicke approximation yes/no? # kron with qubits to get the hamiltonian # here we'll use the fact that eta may be different for each ion sys_ho = np.zeros(((hspace.maxphonons+1)*hspace.levels**hspace.nuions, \ (hspace.maxphonons+1)*hspace.levels**hspace.nuions ), \ np.complex128) if LDApprox: for k in xrange(hspace.nuions): #etak = eta[-1] if pulse.ion == -1 else eta[k] sys_ho += npml.kron( targetion[k]*opdict['raising'][:,:,k],\ np.diag(np.ones(hspace.maxphonons+1)) + \ 1j * eta[k] * (opdict['a']+opdict['a_dag']) ) else: for k in xrange(hspace.nuions): #etak = eta[-1] if pulse.ion == -1 else eta[k] sys_ho += npml.kron( targetion[k]*opdict['raising'][:,:,k],\ splg.expm2(1j * eta[k] * (opdict['a']+opdict['a_dag'])) ) # multiply with rabi-frequency part H = prefac * sys_ho # diagonal terms sysz = np.zeros( (hspace.levels**hspace.nuions, hspace.levels**hspace.nuions)) for k in xrange(hspace.nuions): sysz += opdict['sigz'][:, :, k] * 1 / 2. energies = -detuning * npml.kron(sysz, opdict['id_a']) + \ wsec * npml.kron(np.diag(np.ones(hspace.levels**hspace.nuions)), \ np.dot(opdict['a_dag'], opdict['a']) ) # subtract a zero offset energies -= np.diag(energies[0, 0] * np.ones_like(np.diag(energies))) # add h.c. part HT = H + H.transpose().conjugate() + energies # diagonal elements of matrix for basis transformation (lasertoqc) lqc = np.diag(HT) if pulse.type == 'Z': HT = HT + np.diag(self.ACshift_corr(pulse, params)) # to fix discrepancy between lab/Volkmar and here if pulse.theta < 0: HT = -HT lqc = -lqc return HT, lqc
def Hamiltonian(self, pulse, params, LDApprox=True): ''' Hamiltonian definition using hspace.operator_dict ''' opdict = params.hspace.operator_dict targetion = pulse.targetion[::-1] omrabi = pulse.omrabi phase = pulse.phase detuning = pulse.detuning wsec = params.omz eta = params.eta hspace = params.hspace # prefactor including the timedepending omega and the detuning+phase prefac = np.exp(1j * phase) * omrabi * 1/2. # coupling to the sideband. argument of the exponent/ld approximation LDpart = 1j * eta[-1] * (opdict['a']+opdict['a_dag']) # calculate the coupling based on the addressing errors # Lamb-Dicke approximation yes/no? # kron with qubits to get the hamiltonian # here we'll use the fact that eta may be different for each ion sys_ho = np.zeros(((hspace.maxphonons+1)*hspace.levels**hspace.nuions, \ (hspace.maxphonons+1)*hspace.levels**hspace.nuions ), \ np.complex128) if LDApprox: for k in xrange(hspace.nuions): #etak = eta[-1] if pulse.ion == -1 else eta[k] sys_ho += npml.kron( targetion[k]*opdict['raising'][:,:,k],\ np.diag(np.ones(hspace.maxphonons+1)) + \ 1j * eta[k] * (opdict['a']+opdict['a_dag']) ) else: for k in xrange(hspace.nuions): #etak = eta[-1] if pulse.ion == -1 else eta[k] sys_ho += npml.kron( targetion[k]*opdict['raising'][:,:,k],\ splg.expm2(1j * eta[k] * (opdict['a']+opdict['a_dag'])) ) # multiply with rabi-frequency part H = prefac * sys_ho # diagonal terms sysz = np.zeros((hspace.levels**hspace.nuions,hspace.levels**hspace.nuions)) for k in xrange(hspace.nuions): sysz += opdict['sigz'][:,:,k] * 1/2. energies = -detuning * npml.kron(sysz, opdict['id_a']) + \ wsec * npml.kron(np.diag(np.ones(hspace.levels**hspace.nuions)), \ np.dot(opdict['a_dag'], opdict['a']) ) # subtract a zero offset energies -= np.diag(energies[0,0]*np.ones_like(np.diag(energies))) # add h.c. part HT = H + H.transpose().conjugate() + energies # diagonal elements of matrix for basis transformation (lasertoqc) lqc = np.diag(HT) if pulse.type == 'Z': HT = HT+np.diag(self.ACshift_corr(pulse, params)) # to fix discrepancy between lab/Volkmar and here if pulse.theta < 0: HT = -HT lqc = -lqc return HT, lqc
def proctomo(data, NumberOfIterations = 100, use_bell_basis=False): """Process tomography for an arbitrary number of ions Params data: either datafile string or a a cprb matrix NumberOfIterations: Number of iterations for the maximum likelihood algorithm """ Paulis = getopbase() NumberOfIons = np.int(np.log2(data.shape[1]-1)) RhoIn, Obs, ObsVal, NRho, NObs = LoadProctomData(data) # tic = time.time() RhoTObs = np.zeros((NRho*NObs,4**NumberOfIons,4**NumberOfIons),dtype=complex) TransposedRhoTObs = np.zeros((NRho*NObs,4**NumberOfIons,4**NumberOfIons),dtype=complex) for m in range(NRho): for n in range(NObs): tmp = npml.kron(RhoIn[m,:,:].transpose(),Obs[n,:,:]) RhoTObs[m*NObs+n,:,:] = tmp TransposedRhoTObs[m*NObs+n,:,:] = tmp.transpose() del RhoIn, Obs, tmp # TransposedRhoTObs[m*NObs+n,:,:] = transpose(RhoTObs[m*NObs+n,:,:]) # print(time.time()-tic,'seconds') # reserving some more memory space QOps = np.zeros((2**NumberOfIons,2**NumberOfIons,(2**NumberOfIons)**2)) QOps2 = np.zeros((2**NumberOfIons,2**NumberOfIons,(2**NumberOfIons)**2), dtype = complex) AB = np.zeros((4**NumberOfIons,4**NumberOfIons), dtype = complex) AA = np.zeros((4**NumberOfIons,4**NumberOfIons), dtype = complex) v = np.eye(2**NumberOfIons); # Quantenoperatoren for m in range(2**NumberOfIons): for n in range(2**NumberOfIons): QOps[:,:,n+2**NumberOfIons*m] = np.outer(v[:,m],v[:,n]) for k in range(4**NumberOfIons): Op_tmp = 1 for l in range(NumberOfIons): Op_tmp = npml.kron(Paulis[np.mod(k//4**l,4)],Op_tmp) QOps2[:,:,k]=Op_tmp for m in range(4**NumberOfIons): for n in range(4**NumberOfIons): AB[m,n] = np.sum(QOps[:,:,m]*np.transpose(QOps2[:,:,n])) AA[m,n] = np.sum(QOps[:,:,m]*np.transpose(QOps[:,:,n])) C = np.dot(lnlg.inv(AB), AA) del AB, AA, QOps, QOps2 # -------------------------- dimH = 2**NumberOfIons dimK = dimH idH = np.eye(dimH) idK = np.eye(dimK) S0 = 1.*npml.kron(idH,idK)/dimK Kstart = np.zeros((4**NumberOfIons,4**NumberOfIons)) # -------------------------- #print(RhoTObs.imag.max()) ObsValCalc = np.zeros(NRho*NObs) #S = np.zeros(((2**NumberOfIons)**2,(2**NumberOfIons)**2)) # tic = time.time() for k in range(NumberOfIterations): ObsValCalc2 = np.real(np.sum(np.sum(npml.multiply(S0, TransposedRhoTObs), axis = 1), axis = 1)) # for mn in range(NRho*NObs): # ObsValCalc[mn] = np.sum(S0*np.transpose(RhoTObs[mn,:,:])) # alternative: this seems to be a factor of 2 faster for 2 ions, but becomes a factor of two slower for 3 ions ... # S0_long = tile(S0,(NRho*NObs,1,1)) # ObsValCalc = sum(sum(S0_long*TransposedRhoTObs,axis=2),axis=1) # tensordot(a,b,(0,0)) does something like sum_i a[i]*b[i,:,:] K = np.tensordot(ObsVal/ObsValCalc2,RhoTObs,(0,0)) # lagrange multiplication lamquad = __ptrace(np.dot(K,np.dot(S0,K)),dimH,dimK,2) # here is some complain about real/imag definitions ... laminv = lnlg.inv(lnlg.sqrtm(lamquad)) Laminv = npml.kron(laminv,idK) # new s-matrix S = np.dot(Laminv,np.dot(K,np.dot(S0,np.dot(K,Laminv)))) S0 = S # print(time.time()-tic,'seconds') # calculate corresponding chi matrix # all the info is in the S matrix V = np.zeros(((2**NumberOfIons)**2,(2**NumberOfIons)**2)) for q in range(2**NumberOfIons): for m in range(2**NumberOfIons): V[:,q+2**NumberOfIons*m] = npml.kron(v[:,q],v[:,m]) Chi = np.zeros(((2**NumberOfIons)**2,(2**NumberOfIons)**2),dtype = complex) for p in range(4**NumberOfIons): for q in range(4**NumberOfIons): Chi[p,q] = np.dot(np.conjugate(np.transpose(V[:,p])),np.dot(S,V[:,q])) Chi_final = np.dot(C,np.dot(Chi,np.transpose(np.conjugate(C)))) return Chi_final
def LoadProctomData(data): """ loads data and does some calculations on input/output states, etc mainly a helper-function """ NumberOfIons = np.int(np.log2(data.shape[1]-1)) dat = data[:,1:] Id = np.array([[1,0],[0,1]]) X = np.array([[0,1],[1,0]]) Y = np.array([[0,-1j],[1j,0]]) Z = np.array([[1,0],[0,-1]]) NRho = 4**NumberOfIons # 4 output dm's per ion (S,S+D,S+iD,D) NObs = 6**NumberOfIons # the 6 basis we measure: z, -z, x, -x, y, -y # reserve some memory RhoIn = np.zeros((NRho,2**NumberOfIons,2**NumberOfIons),dtype=complex) Obs = np.zeros((NObs,2**NumberOfIons,2**NumberOfIons),dtype=complex) ObsVal = np.zeros(NObs*NRho) # now we'll smartly figure out the thetas/rhos of the rotations theta_proc = np.array([0, 0.5, 0.5, 1])*np.pi phi_proc = np.array([0, 0, 0.5, 0])*np.pi # a bit tricky to get the right thetas for the ions now theta_list = [] for k in range(NumberOfIons): theta_tmp = 1 for l in range(NumberOfIons): if k==l: theta_tmp = npml.kron(theta_proc,theta_tmp) else: theta_tmp = npml.kron(np.ones(4),theta_tmp) theta_list.append(theta_tmp) phi_list = [] for k in range(NumberOfIons): phi_tmp = 1 for l in range(NumberOfIons): if k == l: phi_tmp = npml.kron(phi_proc,phi_tmp) else: phi_tmp = npml.kron(np.ones(4),phi_tmp) phi_list.append(phi_tmp) # states and matrixes psistart = np.zeros(2**NumberOfIons) psistart[2**NumberOfIons-1] = 1 # print((theta_list,phi_list)) # return (theta_list,phi_list) for k in range(NRho): Op_tmp = np.zeros((NumberOfIons,2,2),dtype=complex) for l in range(NumberOfIons): Op_tmp[l,:,:] = lnlg.expm(1j*theta_list[l][k]/2*(np.cos(phi_list[l][k])*X-np.sin(phi_list[l][k])*Y)) Op = Op_tmp[0,:,:] if NumberOfIons > 1: for l in range(NumberOfIons-1): Op = npml.kron(Op,Op_tmp[l+1,:,:]) psi_in = np.dot(Op,psistart) RhoIn[k,:,:] = np.outer(psi_in,np.conjugate(psi_in)) #print(RhoIn) # new lets start to work on teh projectors ez_list = [] for k in range(2**NumberOfIons): ez_list.append(np.eye(2**NumberOfIons)[:,k]) thetaIXY_state = np.array([0, 0.5, 0.5])*np.pi phiIXY_state = np.array([0, 1.5, 1.0])*np.pi theta_state_list = [] for k in range(NumberOfIons): theta_tmp = 1 for l in range(NumberOfIons): if k==l: theta_tmp = npml.kron(thetaIXY_state,theta_tmp) else: theta_tmp = npml.kron(np.ones(3),theta_tmp) theta_state_list.append(theta_tmp) # theta_state_list.insert(0,theta_tmp) phi_state_list = [] for k in range(NumberOfIons): phi_tmp = 1 for l in range(NumberOfIons): if k == l: phi_tmp = npml.kron(phiIXY_state, phi_tmp) else: phi_tmp = npml.kron(np.ones(3),phi_tmp) phi_state_list.append(phi_tmp) # phi_state_list.insert(0,phi_tmp) for k in range(np.int(NObs/2**NumberOfIons)): Op_tmp = np.zeros((NumberOfIons,2,2),dtype=complex) for l in range(NumberOfIons): Op_tmp[l,:,:]=lnlg.expm(-1j*theta_state_list[l][k]/2*(np.cos(phi_state_list[l][k])*X-np.sin(phi_state_list[l][k])*Y)); Op = Op_tmp[0,:,:] if NumberOfIons > 1: for l in range(NumberOfIons-1): # Op = npml.kron(Op_tmp[l+1,:,:],Op) Op = npml.kron(Op_tmp[l+1,:,:],Op) # print(Op) # sqrtm(Op) for m in range(2**NumberOfIons): psi = np.dot(Op,np.eye(2**NumberOfIons)[:,m]) Obs[k*(2**NumberOfIons)+m,:,:] = np.outer(psi,psi.conjugate()) # print(Obs) # calculate obsval for k in range(NRho): for l in range(np.int(NObs/(2**NumberOfIons))): obsind = NObs*k + (2**NumberOfIons)*l; datind = NObs//(2**NumberOfIons) * k + l; for m in range(2**NumberOfIons): ObsVal[obsind+m]=dat[datind,m] return (RhoIn, Obs, ObsVal, NRho, NObs)
def iterfun(data,NumberOfIterations, path=None): """iterative maximum likelihood state tomography data can be either a matrix,data_object or a time string """ if type(data)== str: data = rd.ReadData(data, path=path) try: data = data.data_dict['cprb'] except AttributeError: pass # tic=time.time() NumberRows=len(data[:,1]) NumberCols=len(data[1,:]) # check if number of rows and columns fit # numberofcols= 2^NumberOfIons+1 # numberrows=3^numberofions if not 3**np.log2(NumberCols-1)==NumberRows: print("dataset not complete") NumberOfIons=np.int(np.log2(NumberCols-1)) probs=data[:,1:] pulsecode=data[:,0] NoExp=len(pulsecode) # pulses = double(dec2base(pulsecode,3,NoI))-double('0'); pulses=np.zeros((3**NumberOfIons,NumberOfIons)) # pulses.shape= for i in xrange(3**NumberOfIons): pulses[i,:]=np.array(__dec2base(i,3,NumberOfIons)) #print(pulses) # pulsetable = reshape(kron(ones(1,2^NoI),pulses)',NoI,NoExp*2^NoI)'; # first part kron(ones(1,2^NoI),pulses)' = # = mtlb.transpose(mtlb.kron(ones(2**NumberOfIons),pulses)) # reshape = reshape(<whatever>,(NumberOfIons,3**NumberOfIons*2**NumberOfIons),'FORTRAN') a=npml.kron(np.ones(2**NumberOfIons),pulses).transpose() pulsetable = np.reshape(a,(NumberOfIons,3**NumberOfIons*2**NumberOfIons),'FORTRAN').transpose() #print(pulsetable) # Now the experimental data are stored in the same way: # probs = reshape(probs',1,NoExp*2^NoI)'; probs=np.reshape(probs.transpose(),(1,3**NumberOfIons*2**NumberOfIons),'FORTRAN').transpose() probs=probs[:,0] # For each experimental data point, a measurement of the D state has to be # labeled with +1, a measurement of the S-state with 0; # meas = (double(dec2bin(2^NoI-1:-1:0)')-double('0'))'; # meastable = kron(ones(NoExp,1),meas); meas=np.zeros((2**NumberOfIons,NumberOfIons)) k=0 for i in xrange(2**NumberOfIons-1,-1,-1): meas[k,:]=np.array(__dec2base(i,2,NumberOfIons),dtype=int) k+=1 a=np.ones((3**NumberOfIons,1)) meastable=npml.kron(a,meas) #meastable = meastable + 2 * pulsetable + 1; #Ntable=length(meastable); meastable+= 2*pulsetable Ntable=len(meastable) #Here are the corresponding projectors: #P(:,:,1) = [0;1]*[0;1]'; % - #P(:,:,2) = [1;0]*[1;0]'; % + #P(:,:,4) = [-1;1]*[-1;1]'/2; % - #P(:,:,3) = [1;1]*[1;1]'/2; % + #P(:,:,6) = [i;1]*[i;1]'/2; % - #P(:,:,5) = [-i;1]*[-i;1]'/2; % + P=np.zeros((6,2,2),dtype=complex) P[0,:,:]=np.outer(np.array([0,1]),np.array([0,1])) P[1,:,:]=np.outer(np.array([1,0]),np.array([1,0])) P[2,:,:]=np.outer(0.5*np.array([-1,1]),np.array([-1,1])) P[3,:,:]=np.outer(0.5*np.array([1,1]),np.array([1,1])) P[4,:,:]=np.outer(0.5*np.array([1j,1]),np.conjugate(np.array([1j,1]))) P[5,:,:]=np.outer(0.5*np.array([-1j,1]),np.conjugate(np.array([-1j,1]))) # about to start iterations ... rho = np.identity(2**NumberOfIons)/2**NumberOfIons # AllOp=zeros(2^NoI,2^NoI,Ntable); # AllOp=zeros((Ntable,2**NumberOfIons,2**NumberOfIons),dtype=complex) AllOp=[] # toc2=time.time() # print toc2-tic,'seconds for initialisation have elapsed' AllOp2 = np.zeros((Ntable,2**NumberOfIons,2**NumberOfIons),dtype=complex) AllOpTransposed = np.zeros((Ntable,2**NumberOfIons,2**NumberOfIons),dtype=complex) for k in xrange(Ntable): ind=meastable[k,:].copy() Op=P[ind[0],:,:] for m in xrange(1,NumberOfIons): Op=npml.kron(Op,P[ind[m],:,:]) AllOp.append(Op) AllOp2[k,:,:] = Op AllOpTransposed[k,:,:] = Op.transpose() # really starting with the iterations now # toc3=time.time() # print toc3-toc2,'seconds for operator initalisation' ROp_start=np.zeros((2**NumberOfIons,2**NumberOfIons),dtype=complex) list_probOp = np.zeros(Ntable) for i in xrange(NumberOfIterations): ROp=ROp_start.copy() list_probOp2 = np.sum(np.sum(npml.multiply(rho, AllOpTransposed), axis = 1), axis = 1) # for k in xrange(Ntable): # Op=AllOp[k] # # the following is tons faster because it relies on element wise multiplication only # probOp=(rho*Op.transpose()).sum() # list_probOp[k] = probOp # okay. if probOp would be zero, it would be a problem. but i # never got a zero here, so i'll just skip the if # if probOp > 0: # ROp += probs[k]/probOp * Op # tensordot results in a factor of 2 faster evaluation of # the w4 data compared to the old loop approach # print (list_probOp2[0] -list_probOp[0]) ROp2 = np.tensordot(probs/list_probOp2,AllOp2,(0,0)) rho=np.dot(np.dot(ROp2,rho),ROp2) # rho=np.dot(np.dot(ROp,rho),ROp) rho/=rho.trace() # toc=time.time() # print time.time()-toc3,' seconds for iterations' return rho
def LoadProctomData(data): """ loads data and does some calculations on input/output states, etc mainly a helper-function """ NumberOfIons = np.int(np.log2(data.shape[1]-1)) dat = data[:,1:] Id = np.array([[1,0],[0,1]]) X = np.array([[0,1],[1,0]]) Y = np.array([[0,-1j],[1j,0]]) Z = np.array([[1,0],[0,-1]]) NRho = 4**NumberOfIons # 4 output dm's per ion (S,S+D,S+iD,D) NObs = 6**NumberOfIons # the 6 basis we measure: z, -z, x, -x, y, -y # reserve some memory RhoIn = np.zeros((NRho,2**NumberOfIons,2**NumberOfIons),dtype=complex) Obs = np.zeros((NObs,2**NumberOfIons,2**NumberOfIons),dtype=complex) ObsVal = np.zeros(NObs*NRho) # now we'll smartly figure out the thetas/rhos of the rotations theta_proc = np.array([0, 0.5, 0.5, 1])*np.pi phi_proc = np.array([0, 0, 0.5, 0])*np.pi # a bit tricky to get the right thetas for the ions now theta_list = [] for k in xrange(NumberOfIons): theta_tmp = 1 for l in xrange(NumberOfIons): if k==l: theta_tmp = npml.kron(theta_proc,theta_tmp) else: theta_tmp = npml.kron(np.ones(4),theta_tmp) theta_list.append(theta_tmp) phi_list = [] for k in xrange(NumberOfIons): phi_tmp = 1 for l in xrange(NumberOfIons): if k == l: phi_tmp = npml.kron(phi_proc,phi_tmp) else: phi_tmp = npml.kron(np.ones(4),phi_tmp) phi_list.append(phi_tmp) # states and matrixes psistart = np.zeros(2**NumberOfIons) psistart[2**NumberOfIons-1] = 1 # print (theta_list,phi_list) # return (theta_list,phi_list) for k in xrange(NRho): Op_tmp = np.zeros((NumberOfIons,2,2),dtype=complex) for l in xrange(NumberOfIons): Op_tmp[l,:,:] = lnlg.expm(1j*theta_list[l][k]/2*(np.cos(phi_list[l][k])*X-np.sin(phi_list[l][k])*Y)) Op = Op_tmp[0,:,:] if NumberOfIons > 1: for l in xrange(NumberOfIons-1): Op = npml.kron(Op,Op_tmp[l+1,:,:]) psi_in = np.dot(Op,psistart) RhoIn[k,:,:] = np.outer(psi_in,np.conjugate(psi_in)) #print RhoIn # new lets start to work on teh projectors ez_list = [] for k in xrange(2**NumberOfIons): ez_list.append(np.eye(2**NumberOfIons)[:,k]) thetaIXY_state = np.array([0, 0.5, 0.5])*np.pi phiIXY_state = np.array([0, 1.5, 1.0])*np.pi theta_state_list = [] for k in xrange(NumberOfIons): theta_tmp = 1 for l in xrange(NumberOfIons): if k==l: theta_tmp = npml.kron(thetaIXY_state,theta_tmp) else: theta_tmp = npml.kron(np.ones(3),theta_tmp) theta_state_list.append(theta_tmp) # theta_state_list.insert(0,theta_tmp) phi_state_list = [] for k in xrange(NumberOfIons): phi_tmp = 1 for l in xrange(NumberOfIons): if k == l: phi_tmp = npml.kron(phiIXY_state, phi_tmp) else: phi_tmp = npml.kron(np.ones(3),phi_tmp) phi_state_list.append(phi_tmp) # phi_state_list.insert(0,phi_tmp) for k in xrange(np.int(NObs/2**NumberOfIons)): Op_tmp = np.zeros((NumberOfIons,2,2),dtype=complex) for l in xrange(NumberOfIons): Op_tmp[l,:,:]=lnlg.expm(-1j*theta_state_list[l][k]/2*(np.cos(phi_state_list[l][k])*X-np.sin(phi_state_list[l][k])*Y)); Op = Op_tmp[0,:,:] if NumberOfIons > 1: for l in xrange(NumberOfIons-1): # Op = npml.kron(Op_tmp[l+1,:,:],Op) Op = npml.kron(Op_tmp[l+1,:,:],Op) # print Op # sqrtm(Op) for m in xrange(2**NumberOfIons): psi = np.dot(Op,np.eye(2**NumberOfIons)[:,m]) Obs[k*(2**NumberOfIons)+m,:,:] = np.outer(psi,psi.conjugate()) # print Obs # calculate obsval for k in xrange(NRho): for l in xrange(np.int(NObs/(2**NumberOfIons))): obsind = NObs*k + (2**NumberOfIons)*l; datind = NObs/(2**NumberOfIons) * k + l; for m in xrange(2**NumberOfIons): ObsVal[obsind+m]=dat[datind,m] return (RhoIn, Obs, ObsVal, NRho, NObs)
def iterfun(data, NumberOfIterations, path=None): """iterative maximum likelihood state tomography data can be either a matrix,data_object or a time string """ if type(data) == str: data = rd.ReadData(data, path=path) try: data = data.data_dict['cprb'] except AttributeError: pass # tic=time.time() NumberRows = len(data[:, 1]) NumberCols = len(data[1, :]) # check if number of rows and columns fit # numberofcols= 2^NumberOfIons+1 # numberrows=3^numberofions if not 3**np.log2(NumberCols - 1) == NumberRows: print("dataset not complete") NumberOfIons = np.int(np.log2(NumberCols - 1)) probs = data[:, 1:] pulsecode = data[:, 0] NoExp = len(pulsecode) # pulses = double(dec2base(pulsecode,3,NoI))-double('0'); pulses = np.zeros((3**NumberOfIons, NumberOfIons), dtype=np.int) # pulses.shape= for i in range(3**NumberOfIons): pulses[i, :] = np.array(__dec2base(i, 3, NumberOfIons)) #print(pulses) # pulsetable = reshape(kron(ones(1,2^NoI),pulses)',NoI,NoExp*2^NoI)'; # first part kron(ones(1,2^NoI),pulses)' = # = mtlb.transpose(mtlb.kron(ones(2**NumberOfIons),pulses)) # reshape = reshape(<whatever>,(NumberOfIons,3**NumberOfIons*2**NumberOfIons),order='F') a = npml.kron(np.ones(2**NumberOfIons, dtype=np.int), pulses).transpose() pulsetable = np.reshape(a, (NumberOfIons, 3**NumberOfIons * 2**NumberOfIons), order='F').transpose() #print(pulsetable) # Now the experimental data are stored in the same way: # probs = reshape(probs',1,NoExp*2^NoI)'; probs = np.reshape(probs.transpose(), (1, 3**NumberOfIons * 2**NumberOfIons), order='F').transpose() probs = probs[:, 0] # For each experimental data point, a measurement of the D state has to be # labeled with +1, a measurement of the S-state with 0; # meas = (double(dec2bin(2^NoI-1:-1:0)')-double('0'))'; # meastable = kron(ones(NoExp,1),meas); meas = np.zeros((2**NumberOfIons, NumberOfIons), dtype=np.int) k = 0 for i in range(2**NumberOfIons - 1, -1, -1): meas[k, :] = np.array(__dec2base(i, 2, NumberOfIons)) k += 1 a = np.ones((3**NumberOfIons, 1), dtype=np.int) meastable = npml.kron(a, meas) #meastable = meastable + 2 * pulsetable + 1; #Ntable=length(meastable); meastable += 2 * pulsetable Ntable = len(meastable) #Here are the corresponding projectors: #P(:,:,1) = [0;1]*[0;1]'; % - #P(:,:,2) = [1;0]*[1;0]'; % + #P(:,:,4) = [-1;1]*[-1;1]'/2; % - #P(:,:,3) = [1;1]*[1;1]'/2; % + #P(:,:,6) = [i;1]*[i;1]'/2; % - #P(:,:,5) = [-i;1]*[-i;1]'/2; % + P = np.zeros((6, 2, 2), dtype=complex) P[0, :, :] = np.outer(np.array([0, 1]), np.array([0, 1])) P[1, :, :] = np.outer(np.array([1, 0]), np.array([1, 0])) P[2, :, :] = np.outer(0.5 * np.array([-1, 1]), np.array([-1, 1])) P[3, :, :] = np.outer(0.5 * np.array([1, 1]), np.array([1, 1])) P[4, :, :] = np.outer(0.5 * np.array([1j, 1]), np.conjugate(np.array([1j, 1]))) P[5, :, :] = np.outer(0.5 * np.array([-1j, 1]), np.conjugate(np.array([-1j, 1]))) # about to start iterations ... rho = np.identity(2**NumberOfIons) / 2**NumberOfIons # AllOp=zeros(2^NoI,2^NoI,Ntable); # AllOp=zeros((Ntable,2**NumberOfIons,2**NumberOfIons),dtype=complex) AllOp = [] # toc2=time.time() # print(toc2-tic,'seconds for initialisation have elapsed') AllOp2 = np.zeros((Ntable, 2**NumberOfIons, 2**NumberOfIons), dtype=complex) AllOpTransposed = np.zeros((Ntable, 2**NumberOfIons, 2**NumberOfIons), dtype=complex) for k in range(Ntable): ind = meastable[k, :].copy() Op = P[ind[0], :, :] for m in range(1, NumberOfIons): Op = npml.kron(Op, P[ind[m], :, :]) AllOp.append(Op) AllOp2[k, :, :] = Op AllOpTransposed[k, :, :] = Op.transpose() # really starting with the iterations now # toc3=time.time() # print(toc3-toc2,'seconds for operator initalisation') ROp_start = np.zeros((2**NumberOfIons, 2**NumberOfIons), dtype=complex) list_probOp = np.zeros(Ntable) for i in range(NumberOfIterations): ROp = ROp_start.copy() list_probOp2 = np.sum(np.sum(npml.multiply(rho, AllOpTransposed), axis=1), axis=1) # for k in range(Ntable): # Op=AllOp[k] # # the following is tons faster because it relies on element wise multiplication only # probOp=(rho*Op.transpose()).sum() # list_probOp[k] = probOp # okay. if probOp would be zero, it would be a problem. but i # never got a zero here, so i'll just skip the if # if probOp > 0: # ROp += probs[k]/probOp * Op # tensordot results in a factor of 2 faster evaluation of # the w4 data compared to the old loop approach # print((list_probOp2[0] -list_probOp[0])) ROp2 = np.tensordot(probs / list_probOp2, AllOp2, (0, 0)) rho = np.dot(np.dot(ROp2, rho), ROp2) # rho=np.dot(np.dot(ROp,rho),ROp) rho /= rho.trace() # toc=time.time() # print(time.time()-toc3,' seconds for iterations') return rho
def MMAPPH1FCFS(D, sigma, S, *argv): """ Returns various performane measures of a MMAP[K]/PH[K]/1 first-come-first-serve queue, see [1]_. Parameters ---------- D : list of matrices of shape (N,N), length (K+1) The D0...DK matrices of the arrival process. sigma : list of row vectors, length (K) The list containing the initial probability vectors of the service time distributions of the various customer types. The length of the vectors does not have to be the same. S : list of square matrices, length (K) The transient generators of the phase type distributions representing the service time of the jobs belonging to various types. further parameters : The rest of the function parameters specify the options and the performance measures to be computed. The supported performance measures and options in this function are: +----------------+--------------------+----------------------------------------+ | Parameter name | Input parameters | Output | +================+====================+========================================+ | "ncMoms" | Number of moments | The moments of the number of customers | +----------------+--------------------+----------------------------------------+ | "ncDistr" | Upper limit K | The distribution of the number of | | | | customers from level 0 to level K-1 | +----------------+--------------------+----------------------------------------+ | "stMoms" | Number of moments | The sojourn time moments | +----------------+--------------------+----------------------------------------+ | "stDistr" | A vector of points | The sojourn time distribution at the | | | | requested points (cummulative, cdf) | +----------------+--------------------+----------------------------------------+ | "stDistrME" | None | The vector-matrix parameters of the | | | | matrix-exponentially distributed | | | | sojourn time distribution | +----------------+--------------------+----------------------------------------+ | "stDistrPH" | None | The vector-matrix parameters of the | | | | matrix-exponentially distributed | | | | sojourn time distribution, converted | | | | to a continuous PH representation | +----------------+--------------------+----------------------------------------+ | "prec" | The precision | Numerical precision used as a stopping | | | | condition when solving the Riccati | | | | equation | +----------------+--------------------+----------------------------------------+ | "classes" | Vector of integers | Only the performance measures | | | | belonging to these classes are | | | | returned. If not given, all classes | | | | are analyzed. | +----------------+--------------------+----------------------------------------+ (The quantities related to the number of customers in the system include the customer in the server, and the sojourn time related quantities include the service times as well) Returns ------- Ret : list of the performance measures Each entry of the list corresponds to a performance measure requested. Each entry is a matrix, where the columns belong to the various job types. If there is just a single item, then it is not put into a list. References ---------- .. [1] Qiming He, "Analysis of a continuous time SM[K]/PH[K]/1/FCFS queue: Age process, sojourn times, and queue lengths", Journal of Systems Science and Complexity, 25(1), pp 133-155, 2012. """ K = len(D) - 1 # parse options eaten = [] precision = 1e-14 classes = np.arange(0, K) for i in range(len(argv)): if argv[i] == "prec": precision = argv[i + 1] eaten.append(i) eaten.append(i + 1) elif argv[i] == "classes": classes = np.array(argv[i + 1]) - 1 eaten.append(i) eaten.append(i + 1) if butools.checkInput and not CheckMMAPRepresentation(D): raise Exception( 'MMAPPH1FCFS: The arrival process is not a valid MMAP representation!' ) if butools.checkInput: for k in range(K): if not CheckPHRepresentation(sigma[k], S[k]): raise Exception( 'MMAPPH1FCFS: the vector and matrix describing the service times is not a valid PH representation!' ) # some preparation D0 = D[0] N = D0.shape[0] Ia = ml.eye(N) Da = ml.zeros((N, N)) for q in range(K): Da += D[q + 1] theta = CTMCSolve(D0 + Da) beta = [CTMCSolve(S[k] + ml.sum(-S[k], 1) * sigma[k]) for k in range(K)] lambd = [np.sum(theta * D[k + 1]) for k in range(K)] mu = [np.sum(beta[k] * (-S[k])) for k in range(K)] Nsk = [S[k].shape[0] for k in range(K)] ro = np.sum(np.array(lambd) / np.array(mu)) alpha = theta * Da / sum(lambd) D0i = (-D0).I Sa = S[0] sa = [ml.zeros(sigma[0].shape)] * K sa[0] = sigma[0] ba = [ml.zeros(beta[0].shape)] * K ba[0] = beta[0] sv = [ml.zeros((Nsk[0], 1))] * K sv[0] = ml.sum(-S[0], 1) Pk = [D0i * D[q + 1] for q in range(K)] for k in range(1, K): Sa = la.block_diag(Sa, S[k]) for q in range(K): if q == k: sa[q] = ml.hstack((sa[q], sigma[k])) ba[q] = ml.hstack((ba[q], beta[k])) sv[q] = ml.vstack((sv[q], -np.sum(S[k], 1))) else: sa[q] = ml.hstack((sa[q], ml.zeros(sigma[k].shape))) ba[q] = ml.hstack((ba[q], ml.zeros(beta[k].shape))) sv[q] = ml.vstack((sv[q], ml.zeros((Nsk[k], 1)))) Sa = ml.matrix(Sa) P = D0i * Da iVec = ml.kron(D[1], sa[0]) for k in range(1, K): iVec += ml.kron(D[k + 1], sa[k]) Ns = Sa.shape[0] Is = ml.eye(Ns) # step 1. solve the age process of the queue # ========================================== # solve Y0 and calculate T Y0 = FluidFundamentalMatrices(ml.kron(Ia, Sa), ml.kron(Ia, -ml.sum(Sa, 1)), iVec, D0, "P", precision) T = ml.kron(Ia, Sa) + Y0 * iVec # calculate pi0 and v0 pi0 = ml.zeros((1, T.shape[0])) for k in range(K): pi0 += ml.kron(theta * D[k + 1], ba[k] / mu[k]) pi0 = -pi0 * T iT = (-T).I oa = ml.ones((N, 1)) # step 2. calculate performance measures # ====================================== Ret = [] for k in classes: argIx = 0 clo = iT * ml.kron(oa, sv[k]) while argIx < len(argv): if argIx in eaten: argIx += 1 continue elif type(argv[argIx]) is str and argv[argIx] == "stMoms": numOfSTMoms = argv[argIx + 1] rtMoms = [] for m in range(1, numOfSTMoms + 1): rtMoms.append( math.factorial(m) * np.sum(pi0 * iT**m * clo / (pi0 * clo))) Ret.append(rtMoms) argIx += 1 elif type(argv[argIx]) is str and argv[argIx] == "stDistr": stCdfPoints = argv[argIx + 1] cdf = [] for t in stCdfPoints: pr = 1 - np.sum(pi0 * la.expm(T * t) * clo / (pi0 * clo)) cdf.append(pr) Ret.append(np.array(cdf)) argIx += 1 elif type(argv[argIx]) is str and argv[argIx] == "stDistrME": Bm = SimilarityMatrixForVectors(clo / (pi0 * clo), ml.ones((N * Ns, 1))) Bmi = Bm.I A = Bm * T * Bmi alpha = pi0 * Bmi Ret.append(alpha) Ret.append(A) elif type(argv[argIx]) is str and argv[argIx] == "stDistrPH": vv = pi0 * iT ix = np.arange(N * Ns) nz = ix[vv.flat > precision] delta = Diag(vv[:, nz]) cl = -T * clo / (pi0 * clo) alpha = cl[nz, :].T * delta A = delta.I * T[nz, :][:, nz].T * delta Ret.append(alpha) Ret.append(A) elif type(argv[argIx]) is str and argv[argIx] == "ncDistr": numOfQLProbs = argv[argIx + 1] argIx += 1 values = np.empty(numOfQLProbs) jm = ml.zeros((Ns, 1)) jm[np.sum(Nsk[0:k]):np.sum(Nsk[0:k + 1]), :] = 1 jmc = ml.ones((Ns, 1)) jmc[np.sum(Nsk[0:k]):np.sum(Nsk[0:k + 1]), :] = 0 LmCurr = la.solve_sylvester(T, ml.kron(D0 + Da - D[k + 1], Is), -ml.eye(N * Ns)) values[0] = 1 - ro + np.sum(pi0 * LmCurr * ml.kron(oa, jmc)) for i in range(1, numOfQLProbs): LmPrev = LmCurr LmCurr = la.solve_sylvester( T, ml.kron(D0 + Da - D[k + 1], Is), -LmPrev * ml.kron(D[k + 1], Is)) values[i] = np.sum(pi0 * LmCurr * ml.kron(oa, jmc) + pi0 * LmPrev * ml.kron(oa, jm)) Ret.append(values) elif type(argv[argIx]) is str and argv[argIx] == "ncMoms": numOfQLMoms = argv[argIx + 1] argIx += 1 jm = ml.zeros((Ns, 1)) jm[np.sum(Nsk[0:k]):np.sum(Nsk[0:k + 1]), :] = 1 ELn = [ la.solve_sylvester(T, ml.kron(D0 + Da, Is), -ml.eye(N * Ns)) ] qlMoms = [] for n in range(1, numOfQLMoms + 1): bino = 1 Btag = ml.zeros((N * Ns, N * Ns)) for i in range(n): Btag += bino * ELn[i] bino *= (n - i) / (i + 1) ELn.append( la.solve_sylvester(T, ml.kron(D0 + Da, Is), -Btag * ml.kron(D[k + 1], Is))) qlMoms.append( np.sum(pi0 * ELn[n]) + np.sum(pi0 * Btag * ml.kron(oa, jm))) Ret.append(qlMoms) else: raise Exception("MMAPPH1FCFS: Unknown parameter " + str(argv[argIx])) argIx += 1 if len(Ret) == 1: return Ret[0] else: return Ret
def haar_matrix(dim): ''' Generate haar transformation matrix. ''' Q = M.matrix('1 1;-1 1') return 1 / M.sqrt(2) * M.kron(M.eye(dim / 2), Q)
print('>>> print(beta)') print(beta) print('>>> print(B)') print(B) print('>>> stdFromPH = CdfFromPH(betap, Bp, np.arange(0.,1.1,0.1))') stdFromPH = CdfFromPH(betap, Bp, np.arange(0., 1.1, 0.1)) print('>>> print(stdFromPH)') print(stdFromPH) print('>>> stmFromME = MomentsFromME(beta, B, 5)') stmFromME = MomentsFromME(beta, B, 5) print('>>> print(stmFromME)') print(stmFromME) IA = ml.eye(D0.shape[0]) IS = ml.eye(S0.shape[0]) butools.verbose = False gamma, G = QBDQueue(ml.kron(IA, S1), ml.kron(D0, IS) + ml.kron(IA, S0), ml.kron(D1, IS), ml.kron(D0, IS), "stDistrME") butools.verbose = True msmall = MomentsFromME(beta, B, 5) mlarge = MomentsFromME(gamma, G, 5) print('>>> delta = ml.matrix([[0.5,0.1,0.4]])') delta = ml.matrix([[0.5, 0.1, 0.4]]) print('>>> Dm = ml.matrix([[-8., 1., 2.],[0., -6., 4.],[3., 0., -3.]])') Dm = ml.matrix([[-8., 1., 2.], [0., -6., 4.], [3., 0., -3.]]) print('>>> sigma = ml.matrix([[0.2,0.7,0.1]])') sigma = ml.matrix([[0.2, 0.7, 0.1]]) print('>>> S = ml.matrix([[-10., 4., 0.],[5., -7., 2.],[1., 2., -8.]])') S = ml.matrix([[-10., 4., 0.], [5., -7., 2.], [1., 2., -8.]]) print('>>> D0 = Dm') D0 = Dm
delta_t = 0.01 T0 = 0 Tmax = 1 T = np.arange(delta_t,Tmax,delta_t) Y = -1* np.ones((len(T),4), dtype='complex128') Pop = -1* np.ones((len(T),4)) # ------------------ # interaction/hamiltonian rabi = 2*np.pi*2 beatfreq = 2*np.pi*4 id = np.diag(np.array([1,1])) sigmax = 1./2*np.array([[0,1],[1,0]]) Hint = rabi*npml.kron(id,sigmax) H0 = np.diag(np.array([0,0,1,1])) * 100 H = lambda t: (1+np.cos(beatfreq * t))/2 * Hint + H0 # input state psiin = np.array([0,1,0,0]) #psiin = 1./np.sqrt(2)* np.array([1,1]) tcur = T0 b = ODE_timeevo(H, T0, Tmax, delta_t, psiin) t2 = time.time() a = Chebyshev_timeevo(H, T0, Tmax, delta_t, psiin) print 'chebyshev evo: ',time.time()-t2
def MMAPPH1FCFS(D, sigma, S, *argv): """ Returns various performane measures of a MMAP[K]/PH[K]/1 first-come-first-serve queue, see [1]_. Parameters ---------- D : list of matrices of shape (N,N), length (K+1) The D0...DK matrices of the arrival process. sigma : list of row vectors, length (K) The list containing the initial probability vectors of the service time distributions of the various customer types. The length of the vectors does not have to be the same. S : list of square matrices, length (K) The transient generators of the phase type distributions representing the service time of the jobs belonging to various types. further parameters : The rest of the function parameters specify the options and the performance measures to be computed. The supported performance measures and options in this function are: +----------------+--------------------+----------------------------------------+ | Parameter name | Input parameters | Output | +================+====================+========================================+ | "ncMoms" | Number of moments | The moments of the number of customers | +----------------+--------------------+----------------------------------------+ | "ncDistr" | Upper limit K | The distribution of the number of | | | | customers from level 0 to level K-1 | +----------------+--------------------+----------------------------------------+ | "stMoms" | Number of moments | The sojourn time moments | +----------------+--------------------+----------------------------------------+ | "stDistr" | A vector of points | The sojourn time distribution at the | | | | requested points (cummulative, cdf) | +----------------+--------------------+----------------------------------------+ | "stDistrME" | None | The vector-matrix parameters of the | | | | matrix-exponentially distributed | | | | sojourn time distribution | +----------------+--------------------+----------------------------------------+ | "stDistrPH" | None | The vector-matrix parameters of the | | | | matrix-exponentially distributed | | | | sojourn time distribution, converted | | | | to a continuous PH representation | +----------------+--------------------+----------------------------------------+ | "prec" | The precision | Numerical precision used as a stopping | | | | condition when solving the Riccati | | | | equation | +----------------+--------------------+----------------------------------------+ | "classes" | Vector of integers | Only the performance measures | | | | belonging to these classes are | | | | returned. If not given, all classes | | | | are analyzed. | +----------------+--------------------+----------------------------------------+ (The quantities related to the number of customers in the system include the customer in the server, and the sojourn time related quantities include the service times as well) Returns ------- Ret : list of the performance measures Each entry of the list corresponds to a performance measure requested. Each entry is a matrix, where the columns belong to the various job types. If there is just a single item, then it is not put into a list. References ---------- .. [1] Qiming He, "Analysis of a continuous time SM[K]/PH[K]/1/FCFS queue: Age process, sojourn times, and queue lengths", Journal of Systems Science and Complexity, 25(1), pp 133-155, 2012. """ K = len(D)-1 # parse options eaten = [] precision = 1e-14; classes = np.arange(0,K) for i in range(len(argv)): if argv[i]=="prec": precision = argv[i+1] eaten.append(i) eaten.append(i+1) elif argv[i]=="classes": classes = np.array(argv[i+1])-1 eaten.append(i) eaten.append(i+1) if butools.checkInput and not CheckMMAPRepresentation(D): raise Exception('MMAPPH1FCFS: The arrival process is not a valid MMAP representation!') if butools.checkInput: for k in range(K): if not CheckPHRepresentation(sigma[k],S[k]): raise Exception('MMAPPH1FCFS: the vector and matrix describing the service times is not a valid PH representation!') # some preparation D0 = D[0] N = D0.shape[0] Ia = ml.eye(N); Da = ml.zeros((N,N)) for q in range(K): Da += D[q+1] theta = CTMCSolve(D0+Da) beta = [CTMCSolve(S[k]+ml.sum(-S[k],1)*sigma[k]) for k in range(K)] lambd = [np.sum(theta*D[k+1]) for k in range(K)] mu = [np.sum(beta[k]*(-S[k])) for k in range(K)] Nsk = [S[k].shape[0] for k in range(K)] ro = np.sum(np.array(lambd)/np.array(mu)) alpha = theta*Da/sum(lambd) D0i = (-D0).I Sa = S[0]; sa = [ml.zeros(sigma[0].shape)]*K sa[0] = sigma[0] ba = [ml.zeros(beta[0].shape)]*K ba[0] = beta[0] sv = [ml.zeros((Nsk[0],1))]*K sv[0] = ml.sum(-S[0],1) Pk = [D0i*D[q+1] for q in range(K)] for k in range(1,K): Sa = la.block_diag(Sa, S[k]) for q in range(K): if q==k: sa[q] = ml.hstack((sa[q], sigma[k])) ba[q] = ml.hstack((ba[q], beta[k])) sv[q] = ml.vstack((sv[q], -np.sum(S[k],1))) else: sa[q] = ml.hstack((sa[q], ml.zeros(sigma[k].shape))) ba[q] = ml.hstack((ba[q], ml.zeros(beta[k].shape))) sv[q] = ml.vstack((sv[q], ml.zeros((Nsk[k],1)))) Sa = ml.matrix(Sa) P = D0i*Da iVec = ml.kron(D[1],sa[0]) for k in range(1,K): iVec += ml.kron(D[k+1],sa[k]) Ns = Sa.shape[0] Is = ml.eye(Ns) # step 1. solve the age process of the queue # ========================================== # solve Y0 and calculate T Y0 = FluidFundamentalMatrices (ml.kron(Ia,Sa), ml.kron(Ia,-ml.sum(Sa,1)), iVec, D0, "P", precision) T = ml.kron(Ia,Sa) + Y0 * iVec # calculate pi0 and v0 pi0 = ml.zeros((1,T.shape[0])) for k in range(K): pi0 += ml.kron(theta*D[k+1],ba[k]/mu[k]) pi0 = - pi0 * T iT = (-T).I oa = ml.ones((N,1)) # step 2. calculate performance measures # ====================================== Ret = [] for k in classes: argIx = 0 clo = iT*ml.kron(oa,sv[k]) while argIx<len(argv): if argIx in eaten: argIx += 1 continue elif type(argv[argIx]) is str and argv[argIx]=="stMoms": numOfSTMoms = argv[argIx+1] rtMoms = [] for m in range(1,numOfSTMoms+1): rtMoms.append(math.factorial(m) * np.sum(pi0 * iT**m * clo / (pi0*clo))) Ret.append(rtMoms) argIx += 1 elif type(argv[argIx]) is str and argv[argIx]=="stDistr": stCdfPoints = argv[argIx+1] cdf = []; for t in stCdfPoints: pr = 1 - np.sum(pi0 * la.expm(T*t) * clo / (pi0*clo)) cdf.append(pr) Ret.append(np.array(cdf)) argIx += 1 elif type(argv[argIx]) is str and argv[argIx]=="stDistrME": Bm = SimilarityMatrixForVectors(clo/(pi0*clo),ml.ones((N*Ns,1))) Bmi = Bm.I A = Bm * T * Bmi alpha = pi0 * Bmi Ret.append(alpha) Ret.append(A) elif type(argv[argIx]) is str and argv[argIx]=="stDistrPH": vv = pi0*iT ix = np.arange(N*Ns) nz = ix[vv.flat>precision] delta = Diag(vv[:,nz]) cl = -T*clo/(pi0*clo) alpha = cl[nz,:].T*delta A = delta.I*T[nz,:][:,nz].T*delta Ret.append(alpha) Ret.append(A) elif type(argv[argIx]) is str and argv[argIx]=="ncDistr": numOfQLProbs = argv[argIx+1] argIx += 1 values = np.empty(numOfQLProbs) jm = ml.zeros((Ns,1)) jm[np.sum(Nsk[0:k]):np.sum(Nsk[0:k+1]),:] = 1 jmc = ml.ones((Ns,1)) jmc[np.sum(Nsk[0:k]):np.sum(Nsk[0:k+1]),:] = 0 LmCurr = la.solve_sylvester(T, ml.kron(D0+Da-D[k+1],Is), -ml.eye(N*Ns)) values[0] = 1-ro+np.sum(pi0*LmCurr*ml.kron(oa,jmc)) for i in range(1,numOfQLProbs): LmPrev = LmCurr LmCurr = la.solve_sylvester(T, ml.kron(D0+Da-D[k+1],Is), -LmPrev*ml.kron(D[k+1],Is)) values[i] = np.sum(pi0*LmCurr*ml.kron(oa,jmc) + pi0*LmPrev*ml.kron(oa,jm)); Ret.append(values) elif type(argv[argIx]) is str and argv[argIx]=="ncMoms": numOfQLMoms = argv[argIx+1] argIx += 1 jm = ml.zeros((Ns,1)) jm[np.sum(Nsk[0:k]):np.sum(Nsk[0:k+1]),:] = 1 ELn = [la.solve_sylvester(T, ml.kron(D0+Da,Is), -ml.eye(N*Ns))] qlMoms = [] for n in range(1,numOfQLMoms+1): bino = 1 Btag = ml.zeros((N*Ns,N*Ns)) for i in range(n): Btag += bino * ELn[i] bino *= (n-i) / (i+1) ELn.append(la.solve_sylvester(T, ml.kron(D0+Da,Is), -Btag*ml.kron(D[k+1],Is))) qlMoms.append(np.sum(pi0*ELn[n]) + np.sum(pi0*Btag*ml.kron(oa,jm))) Ret.append(qlMoms) else: raise Exception("MMAPPH1FCFS: Unknown parameter "+str(argv[argIx])) argIx += 1 if len(Ret)==1: return Ret[0] else: return Ret