def keep_n(psi, total, chosen_qubit): dm = np.kron(np.transpose(np.conjugate(psi)), psi) dm = np.reshape(dm, (2**total, 2**total)) LIST = list(range(total - 1)) del LIST[chosen_qubit] dm = partial_trace(dm, LIST) return dm
def init_quantum(nhood): v = nhood a = (v[0][0] + v[0][1] + v[0][2] + v[1][0] + v[1][2] + v[2][0] + v[2][1] + v[2][2]) / 8 a = a / np.linalg.norm(a) qr = QuantumRegister(3, 'qr') qc = QuantumCircuit(qr, name='conway') counter = 0 initial_state = (1 / np.sqrt(6)) * np.array([2, 1, 0, 1]) qc.initialize(initial_state, [qr[1], qr[2]]) qc.initialize(a, [qr[0]]) qc.cx(qr[0], qr[1]) qc.initialize(a, [qr[0]]) qc.cx(qr[0], qr[1]) qc.cx(qr[0], qr[2]) qc.cx(qr[1], qr[0]) qc.cx(qr[2], qr[0]) job = execute(qc, Aer.get_backend('statevector_simulator')) results = job.result().get_statevector() del qr del qc del job value = partial_trace(results, [1, 2])[0] value = np.real(value) return value
def test_pairwise_fitter(n, nshots): q = QuantumRegister(n) qc = QuantumCircuit(q) psi = np.random.rand(2**n) + 1j * np.random.rand(2**n) psi /= np.linalg.norm(psi) qc.initialize(psi, q) #rho = Statevector.from_instruction(qc).data rho = np.outer(psi.conj().T, psi) print("Density matrix evaluated") circ = pairwise_state_tomography_circuits(qc, range(n)) job = execute(circ, Aer.get_backend("qasm_simulator"), shots=nshots) print("Simulation done") fitter = PairwiseStateTomographyFitter(job.result(), circ, range(n)) np.set_printoptions(suppress=True) result = fitter.fit() print("Results fit") for (k, v) in result.items(): trace_qubits = list(range(n)) trace_qubits.remove(k[0]) trace_qubits.remove(k[1]) rhok = partial_trace(rho, trace_qubits) print(k, 1 - state_fidelity(v, rhok)) assert 1 - state_fidelity(v, rhok) < np.sqrt(nshots)
def tomography_random_circuit(self, n): q = QuantumRegister(n) qc = QuantumCircuit(q) psi = ((2 * np.random.rand(2**n) - 1) + 1j * (2 * np.random.rand(2**n) - 1)) psi /= np.linalg.norm(psi) qc.initialize(psi, q) rho = DensityMatrix.from_instruction(qc).data circ = pairwise_state_tomography_circuits(qc, q) job = execute(circ, Aer.get_backend("qasm_simulator"), shots=nshots) fitter = PairwiseStateTomographyFitter(job.result(), circ, q) result = fitter.fit() result_exp = fitter.fit(output='expectation') # Compare the tomography matrices with the partial trace of # the original state using fidelity for (k, v) in result.items(): trace_qubits = list(range(n)) trace_qubits.remove(k[0]) trace_qubits.remove(k[1]) rhok = partial_trace(rho, trace_qubits) try: self.check_density_matrix(v, rhok) except: print("Problem with density matrix:", k) raise try: self.check_pauli_expectaion(result_exp[k], rhok) except: print("Problem with expectation values:", k) raise
def evaluate_MPS_double2(params, training_data, ancilla,rounding): answers=np.zeros(training_data.shape[0]) L=training_data.shape[1]-1 for i in range(training_data.shape[0]): """FOR EACH DATA POINT""" """Lets Encode the data elements first""" #psi=initial_encode(training_data[i,:L],ancilla) norm1=(training_data[i,0]**2+training_data[i,1]**2)**0.5 norm2=(training_data[i,2]**2+training_data[i,3]**2)**0.5 psi=np.kron(np.array([training_data[i,0]/norm1, training_data[i,1]/norm1]),np.array([training_data[i,2]/norm2, training_data[i,3]/norm2])) """Stage 1: Unitaries on all of the qubits, ancilla or not""" for j in range(1): psi=np.matmul(ry(params[0],0,total),psi) """Stage 2: CNOT plus unitary for N-1 times (cascading)""" psi=np.matmul(cnot(0,1,total),psi) for j in range(1): psi=np.matmul(ry(params[1],1,total),psi) psi=np.matmul(cnot(1,0,total),psi) psi=np.matmul(ry(params[2],0,total),psi) dm=np.kron(np.transpose(psi),psi) dm=np.reshape(dm,(2**total,2**total)) dm=partial_trace(dm,[1]) """Stage 3: Trace and Measure""" zero_prob=prob_zero(dm) """Stage 4: Calculate Cost""" answers[i]=eval_cost(zero_prob,training_data[i,4],rounding) total_cost=np.sum(answers)/training_data.shape[0] return total_cost
def get_subsystem_fidelity(statevector, trace_systems, subsystem_state): """ Compute the fidelity of the quantum subsystem. Args: statevector (list|array): The state vector of the complete system trace_systems (list|range): The indices of the qubits to be traced. to trace qubits 0 and 4 trace_systems = [0,4] subsystem_state (list|array): The ground-truth state vector of the subsystem Returns: numpy.ndarray: The subsystem fidelity """ rho = np.outer(np.conj(statevector), statevector) rho_sub = partial_trace(rho, trace_systems) rho_sub_in = np.outer(np.conj(subsystem_state), subsystem_state) fidelity = np.trace( sqrtm( np.dot( np.dot(sqrtm(rho_sub), rho_sub_in), sqrtm(rho_sub) ) ) ) ** 2 return fidelity
def quantum_conditional_entropy(rho, theta, phi, qubit=0): """ The quantum conditional entropy for a two-qubit state, with a projective measurement in the specified direction Evaluates the formula .. math:: \\sum_k p_k S(\\rho_k^B) where p_k is the probability of outcome k in the measurement, `\\rho_k^B` is the reduced state of the non-measured qubit after the measurement, and S(\\rho) is the von-Neumann entropy (log in base 2). Args: rho (Array): a two-qubit density operator theta (float): "latitude" angle for the direction of the measurement phi (float): "longitude" angle for the direction of the measurement qubit (int): 0 or 1, the qubit on which the measurement is done (default 0) Returns: float: the quantum conditional entropy """ measurement = projective_measurement(theta, phi, qubit=qubit) prob = np.array([np.real(np.trace(p @ rho)) for p in measurement]) rho_cond = [partial_trace(p @ rho @ p, [qubit]) for p in measurement] rho_cond = [rho_cond[i] / prob[i] for i in range(len(prob))] s_ent = np.array(list(map(entropy, rho_cond))) return np.sum(prob * s_ent)
def tomography(self, full): if self.state == 'GHZ_teleport': self.qc.barrier() self.qc.cx(0, 1) self.qc.h(0) self.qc.h(2) c0 = ClassicalRegister(1) c1 = ClassicalRegister(1) c2 = ClassicalRegister(1) self.qc.add_register(c0, c1, c2) self.qc.measure(0, c0) self.qc.measure(1, c1) self.qc.measure(2, c2) self.qc.z(3).c_if(c0, 1) self.qc.x(3).c_if(c1, 1) self.qc.z(3).c_if(c2, 1) tomography_circuits = state_tomography_circuits( self.qc, self.q[self.a]) else: tomography_circuits = state_tomography_circuits(self.qc, self.q) job = execute(tomography_circuits, backend=self.backend, coupling_map=self.coupling_map, noise_model=self.noise_model, basis_gates=self.basis_gates, shots=self.shots, optimization_level=3) tomography_results = job.result() rho = StateTomographyFitter(tomography_results, tomography_circuits).fit() if self.state == 'GHZ_teleport': self.histogram_data.append( tomography_results.get_counts(tomography_circuits[2])) else: self.histogram_data.append( tomography_results.get_counts(tomography_circuits[3**self.n - 1])) if not full: rho = partial_trace( rho, np.delete(np.arange(self.n), [self.a, self.b])) if self.state == 'GHZ_teleport': for i in range(3): self.qc.data.pop(-1) self.qc.remove_final_measurements() for i in range(3): self.qc.data.pop(-1) return rho
def evolve_theoretical_rho(self, full): if full: evolving_rho = np.kron(np.array([[1, 0], [0, 0]]), self.theoretical_rho) evolved_rho = np.matmul(np.matmul(self.U, evolving_rho), self.U.conj().T) self.theoretical_rho = partial_trace(evolved_rho, self.n) else: evolving_rho = np.kron(np.array([[1, 0], [0, 0]]), self.theoretical_rho) evolved_rho = np.matmul(np.matmul(self.U, evolving_rho), self.U.conj().T) if self.state == 'GHZ_teleport': self.theoretical_rho = partial_trace(evolved_rho, 1) else: self.theoretical_rho = partial_trace(evolved_rho, 2)
def evaluate_circuit(inputs,operator_list, trace): for i in range(len(operator_list)): diff=int(math.log2(inputs.shape[0])-math.log2(operator_list[i].shape[0])) if diff>0: inputs=np.matmul(np.kron(operator_list[i],np.identity(2**diff)), inputs) inputs=np.matmul(inputs,np.matrix(np.kron(operator_list[i],np.identity(2**diff))).getH()) else: inputs=np.matmul(operator_list[i], inputs) inputs=np.matmul(inputs,np.matrix(operator_list[i]).getH()) if trace==1: inputs=partial_trace(inputs,[0]) return inputs
def conditional_entropy(state, qubit_a, qubit_b): """Conditional entropy S(A|B) = S(AB) - S(B) Args: state: a vector or density operator qubit_a: 0-based index of the qubit A qubit_b: 0-based index of the qubit B Returns: int: the conditional entropy """ return entropy(state) - entropy(partial_trace(state, [qubit_b]))
def test_partial_trace(self): # reference rho0 = [[0.5, 0.5], [0.5, 0.5]] rho1 = [[1, 0], [0, 0]] rho2 = [[0, 0], [0, 1]] rho10 = np.kron(rho1, rho0) rho20 = np.kron(rho2, rho0) rho21 = np.kron(rho2, rho1) rho210 = np.kron(rho21, rho0) rhos = [rho0, rho1, rho2, rho10, rho20, rho21] # test partial trace tau0 = partial_trace(rho210, sys=[1, 2]) tau1 = partial_trace(rho210, sys=[0, 2]) tau2 = partial_trace(rho210, sys=[0, 1]) # test different dimensions tau10 = partial_trace(rho210, dims=[4, 2], sys=[1]) tau20 = partial_trace(rho210, dims=[2, 2, 2], sys=[1]) tau21 = partial_trace(rho210, dims=[2, 4], sys=[0]) taus = [tau0, tau1, tau2, tau10, tau20, tau21] all_pass = True for i, j in zip(rhos, taus): all_pass &= (np.linalg.norm(i-j) == 0) self.assertTrue(all_pass)
def test_partial_trace(self): # reference rho0 = [[0.5, 0.5], [0.5, 0.5]] rho1 = [[1, 0], [0, 0]] rho2 = [[0, 0], [0, 1]] rho10 = np.kron(rho1, rho0) rho20 = np.kron(rho2, rho0) rho21 = np.kron(rho2, rho1) rho210 = np.kron(rho21, rho0) rhos = [rho0, rho1, rho2, rho10, rho20, rho21] # test partial trace tau0 = partial_trace(rho210, [1, 2]) tau1 = partial_trace(rho210, [0, 2]) tau2 = partial_trace(rho210, [0, 1]) # test different dimensions tau10 = partial_trace(rho210, [1], dimensions=[4, 2]) tau20 = partial_trace(rho210, [1], dimensions=[2, 2, 2]) tau21 = partial_trace(rho210, [0], dimensions=[2, 4]) taus = [tau0, tau1, tau2, tau10, tau20, tau21] all_pass = True for i, j in zip(rhos, taus): all_pass &= (np.linalg.norm(i - j) == 0) self.assertTrue(all_pass)
def get_subsystem_density_matrix(statevector, trace_systems): """ Compute the reduced density matrix of a quantum subsystem. Args: statevector (list|array): The state vector of the complete system trace_systems (list|range): The indices of the qubits to be traced out. Returns: numpy.ndarray: The reduced density matrix for the desired subsystem """ rho = np.outer(statevector, np.conj(statevector)) rho_sub = partial_trace(rho, trace_systems) return rho_sub
def classical_correlation(rho, qubit=0): """ Calculate the truly classical correlations between two qubits. The classical correlations are defined e.g. in Eq. (8) of Phys. Rev. A 83, 052108 (2011). We use base 2 for log. Args: rho (Array): a two-qubit density operator qubit (int): 0 or 1, the qubit on which the measurement is done (default 0) Returns: float: classical correlations """ assert rho.shape == (4, 4), "Not a two-qubit density matrix" cc = lambda x: quantum_conditional_entropy(rho, x[0], x[1], qubit=qubit) f = minimize(cc, [np.pi/2, np.pi]) return (entropy(partial_trace(rho, [qubit])) - f.fun)/np.log(2)
def test_meas_qubit_specification(self): n = 4 q = QuantumRegister(n) qc = QuantumCircuit(q) psi = ((2 * np.random.rand(2**n) - 1) + 1j * (2 * np.random.rand(2**n) - 1)) psi /= np.linalg.norm(psi) qc.initialize(psi, q) rho = DensityMatrix.from_instruction(qc).data measured_qubits = [q[0], q[2], q[3]] circ = pairwise_state_tomography_circuits(qc, measured_qubits) job = execute(circ, Aer.get_backend("qasm_simulator"), shots=nshots) fitter = PairwiseStateTomographyFitter(job.result(), circ, measured_qubits) result = fitter.fit() result_exp = fitter.fit(output='expectation') # Compare the tomography matrices with the partial trace of # the original state using fidelity for (k, v) in result.items(): #TODO: This method won't work if measured_qubits is not ordered in # wrt the DensityMatrix object. trace_qubits = list(range(n)) trace_qubits.remove(measured_qubits[k[0]].index) trace_qubits.remove(measured_qubits[k[1]].index) rhok = partial_trace(rho, trace_qubits) try: self.check_density_matrix(v, rhok) except: print("Problem with density matrix:", k) raise try: self.check_pauli_expectaion(result_exp[k], rhok) except: print("Problem with expectation values:", k) raise
def test_multiple_registers(self): n = 4 q = QuantumRegister(n / 2) p = QuantumRegister(n / 2) qc = QuantumCircuit(q, p) qc.h(q[0]) qc.rx(np.pi / 4, q[1]) qc.cx(q[0], p[0]) qc.cx(q[1], p[1]) rho = DensityMatrix.from_instruction(qc).data measured_qubits = q #[q[0], q[1], q[2]] circ = pairwise_state_tomography_circuits(qc, measured_qubits) job = execute(circ, Aer.get_backend("qasm_simulator"), shots=nshots) fitter = PairwiseStateTomographyFitter(job.result(), circ, measured_qubits) result = fitter.fit() result_exp = fitter.fit(output='expectation') # Compare the tomography matrices with the partial trace of # the original state using fidelity for (k, v) in result.items(): trace_qubits = list(range(n)) trace_qubits.remove(measured_qubits[k[0]].index) trace_qubits.remove(measured_qubits[k[1]].index) rhok = partial_trace(rho, trace_qubits) try: self.check_density_matrix(v, rhok) except: print("Problem with density matrix:", k) raise try: self.check_pauli_expectaion(result_exp[k], rhok) except: print("Problem with expectation values:", k) raise
def tracing_out(dm,tracing_out): l=[] for i in range(tracing_out): l.append(i) #l contains list of indexes to trace out new_dm=partial_trace(dm,l) return new_dm
def keep_last(psi, total): dm = np.kron(np.transpose(np.conjugate(psi)), psi) dm = np.reshape(dm, (2**total, 2**total)) dm = partial_trace(dm, list(range(total - 1))) return dm