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
Beispiel #2
0
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
Beispiel #3
0
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)
Beispiel #4
0
    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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
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)
Beispiel #8
0
    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
Beispiel #9
0
    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)
Beispiel #10
0
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
Beispiel #11
0
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)
Beispiel #13
0
    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)
Beispiel #14
0
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
Beispiel #15
0
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)
Beispiel #16
0
    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
Beispiel #17
0
    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
Beispiel #18
0
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