def test_phase_damping_error_ideal(self): """Test phase damping error with param=0 (ideal)""" error = phase_damping_error(0) circ, p = error.error_term(0) self.assertEqual(p, 1, msg="ideal probability") self.assertEqual(circ[0], {"name": "id", "qubits": [0]}, msg="ideal circuit")
def test_phase_damping_error_full_noncanonical(self): """Test phase damping error with param=1 and non-canonical kraus""" error = phase_damping_error(1, canonical_kraus=False) circ, p = error.error_term(0) targets = [np.diag([1, 0]), np.diag([0, 1])] self.assertEqual(p, 1, msg="Kraus probability") self.assertEqual(circ[0][1], [circ.qubits[0]]) self.assertTrue(np.allclose(circ[0][0].params, targets), msg="Incorrect kraus matrices")
def test_phase_damping_error_full_noncanonical(self): """Test phase damping error with param=1 and non-canonical kraus""" error = phase_damping_error(1, canonical_kraus=False) circ, p = error.error_term(0) targets = [np.diag([1, 0]), np.diag([0, 1])] self.assertEqual(p, 1, msg="Kraus probability") self.assertEqual(circ[0]["qubits"], [0]) for op in circ[0]['params']: self.remove_if_found(op, targets) self.assertEqual(targets, [], msg="Incorrect kraus matrices")
def test_phase_damping_error_noncanonical(self): """Test phase damping error with non-canonical kraus""" p_phase = 0.3 error = phase_damping_error(0.3, canonical_kraus=False) circ, p = error.error_term(0) targets = [np.array([[1, 0], [0, np.sqrt(1 - p_phase)]]), np.array([[0, 0], [0, np.sqrt(p_phase)]])] self.assertEqual(p, 1, msg="Kraus probability") self.assertEqual(circ[0][1], [circ.qubits[0]]) self.assertTrue(np.allclose(circ[0][0].params, targets), msg="Incorrect kraus matrices")
def test_phase_damping_error_noncanonical(self): """Test phase damping error with non-canonical kraus""" p_phase = 0.3 error = phase_damping_error(0.3, canonical_kraus=False) circ, p = error.error_term(0) targets = [np.array([[1, 0], [0, np.sqrt(1 - p_phase)]]), np.array([[0, 0], [0, np.sqrt(p_phase)]])] self.assertEqual(p, 1, msg="Kraus probability") self.assertEqual(circ[0]["qubits"], [0]) for op in circ[0]['params']: self.remove_if_found(op, targets) self.assertEqual(targets, [], msg="Incorrect kraus matrices")
def test_phase_damping_error_canonical(self): """Test phase damping error with canonical kraus""" p_phase = 0.3 error = phase_damping_error(p_phase, canonical_kraus=True) # The canonical form of this channel should be a mixed # unitary dephasing channel targets = [[{'name': 'z', 'qubits': [0]}], [{'name': 'id', 'qubits': [0]}]] for j in range(2): circ, p = error.error_term(j) self.assertEqual(circ[0]["qubits"], [0]) self.remove_if_found(circ, targets) self.assertEqual(targets, [], msg="Incorrect canonical circuits")
def test_t2(self): """ Run the simulator with dephasing noise. Then verify that the calculated T2 matches the dephasing parameter. """ # 25 numbers ranging from 1 to 200, linearly spaced num_of_gates = (np.linspace(1, 300, 35)).astype(int) gate_time = 0.11 num_of_qubits = 2 qubit = 0 circs, xdata = t2_circuits(num_of_gates, gate_time, num_of_qubits, qubit) expected_t2 = 20 gamma = 1 - np.exp(-2 * gate_time / expected_t2) error = phase_damping_error(gamma) noise_model = NoiseModel() noise_model.add_all_qubit_quantum_error(error, 'id') # TODO: Include SPAM errors backend = qiskit.Aer.get_backend('qasm_simulator') shots = 300 backend_result = qiskit.execute(circs, backend, shots=shots, backend_options={ 'max_parallel_experiments': 0 }, noise_model=noise_model).result() initial_t2 = expected_t2 initial_a = 1 initial_c = 0.5 * (-1) fit = T2Fitter(backend_result, shots, xdata, num_of_qubits, qubit, fit_p0=[initial_a, initial_t2, initial_c], fit_bounds=([0, 0, -1], [2, expected_t2 * 1.2, 1])) self.assertAlmostEqual(fit.time, expected_t2, delta=4, msg='Calculated T2 is inaccurate') self.assertTrue( fit.time_err < 5, 'Confidence in T2 calculation is too low: ' + str(fit.time_err))
def test_phase_damping_error_canonical(self): """Test phase damping error with canonical kraus""" p_phase = 0.3 error = phase_damping_error(p_phase, canonical_kraus=True) # The canonical form of this channel should be a mixed # unitary dephasing channel targets = [qi.Pauli("I").to_matrix(), qi.Pauli("Z").to_matrix()] self.assertEqual(error.size, 1) circ, p = error.error_term(0) self.assertEqual(p, 1, msg="Kraus probability") self.assertEqual(circ[0][1], [circ.qubits[0]]) for actual, expected in zip(circ[0][0].params, targets): self.assertTrue(np.allclose(actual/actual[0][0], expected), msg="Incorrect kraus matrix")
def test_t2star(self): """ Run the simulator with phase damping noise. Then verify that the calculated T2star matches the phase damping parameter. """ # Setting parameters # 25 numbers ranging from 100 to 1000, linearly spaced num_of_gates = num_of_gates = np.append((np.linspace(10, 150, 30)).astype(int), (np.linspace(160,450,20)).astype(int)) gate_time = 0.1 num_of_qubits = 1 qubit = 0 expected_t2 = 10 p = 1 - np.exp(-2*gate_time/expected_t2) error = phase_damping_error(p) noise_model = NoiseModel() noise_model.add_all_qubit_quantum_error(error, 'id') backend = qiskit.Aer.get_backend('qasm_simulator') shots = 300 # Estimating T2* via an exponential function circs, xdata, _ = circuits.t2star(num_of_gates, gate_time, num_of_qubits, qubit) backend_result = qiskit.execute(circs, backend, shots=shots, backend_options={'max_parallel_experiments': 0}, noise_model=noise_model).result() initial_t2 = expected_t2 initial_a = 0.5 initial_c = 0.5 fit = T2StarExpFitter(backend_result, shots, xdata, num_of_qubits, qubit, fit_p0=[initial_a, initial_t2, initial_c], fit_bounds=([-0.5, 0, -0.5], [1.5, expected_t2*1.2, 1.5])) print(fit.time) print(fit.time_err) self.assertAlmostEqual(fit.time, expected_t2, delta=2, msg='Calculated T2 is inaccurate') self.assertTrue(fit.time_err < 2, 'Confidence in T2 calculation is too low: ' + str(fit.time_err)) # Estimate T2* via an oscilliator function circs_osc, xdata, omega = circuits.t2star(num_of_gates, gate_time, num_of_qubits, qubit, 5) backend_result = qiskit.execute(circs_osc, backend, shots=shots, backend_options={'max_parallel_experiments': 0}, noise_model=noise_model).result() initial_a = 0.5 initial_c = 0.5 initial_f = omega initial_phi = 0 fit = T2StarOscFitter(backend_result, shots, xdata, num_of_qubits, qubit, fit_p0=[initial_a, initial_t2, initial_f, initial_phi, initial_c], fit_bounds=([-0.5, 0, omega-0.02, -np.pi, -0.5], [1.5, expected_t2*1.2, omega+0.02, np.pi, 1.5])) print(fit.time) print(fit.time_err) self.assertAlmostEqual(fit.time, expected_t2, delta=2, msg='Calculated T2 is inaccurate') self.assertTrue(fit.time_err < 2, 'Confidence in T2 calculation is too low: ' + str(fit.time_err))
def test_phase_damping_error_ideal(self): """Test phase damping error with param=0 (ideal)""" error = phase_damping_error(0) circ, p = error.error_term(0) self.assertEqual(p, 1, msg="ideal probability") self.assertTrue(error.ideal(), msg="ideal circuit")
def quantum_cadets(n_qubits, noise_circuit, damping_error=0.02): """ n_qubits [int]: total number of qubits - 2^(n_qubits-1) is the number of qft points, plus one sensing qubit noise_circuit [function]: function that takes one input (a time index between 0-1) and returns a quantum circuit with 1 qubit damping_error [float]: T2 damping error """ register_size = n_qubits - 1 # Create a Quantum Circuit acting on the q register qr = QuantumRegister(n_qubits, 'q') cr = ClassicalRegister(register_size) qc = QuantumCircuit(qr, cr) # Add a H gate on qubit 1,2,3...N-1 for i in range(register_size): qc.h(i+1) # multi-qubit controlled-not (mcmt) gate mcmt_gate = MCMT(XGate(), register_size, 1) qr_range=[*range(1, n_qubits), 0] for bit in range(2**register_size): qc.append(mcmt_gate, [qr[i] for i in qr_range]) # external noise gates qc.append(noise_circuit(bit / 2**register_size), [qr[0]]) qc.append(mcmt_gate, [qr[i] for i in qr_range]) if bit == 0: for i in range(register_size): qc.x(i + (n_qubits - register_size)) elif bit == 2**register_size - 1: pass else: conv_register, XRange = build_encode_circuit(bit, n_qubits, register_size) qc.append(conv_register, qr[XRange]) # run the QFT qft = circuit.library.QFT(register_size) qc.append(qft, qr[1:n_qubits]) # map the quantum measurement to classical bits qc.measure(range(1, n_qubits), range(0, register_size)) # display the quantum circuit in text form print(qc.draw('text')) #qc.draw('mpl') plt.show() # noise model t2_noise_model = NoiseModel() t2_noise_model.add_quantum_error(phase_damping_error(damping_error), 'id', [0]) # run the quantum circuit on the statevector simulator backend #backend = Aer.get_backend('statevector_simulator') # run the quantum circuit on the qasm simulator backend backend = Aer.get_backend('qasm_simulator') # number of histogram samples shots = 10000 # execute the quantum program job = execute(qc, backend, noise_model=t2_noise_model, shots=shots) # outputstate = result.get_statevector(qc, decimals=3) # visualization.plot_state_city(outputstate) result = job.result() # collect the state histogram counts counts = result.get_counts(qc) #plot_histogram(counts) qft_result = np.zeros(2**register_size) for f in range(len(qft_result)): # invert qubit order and convert to string f_bin_str = ('{0:0' + str(register_size) + 'b}').format(f)[::-1] if f_bin_str in counts: if f: # flip frequency axis and assign histogram counts qft_result[2**register_size - f] = counts[f_bin_str] / shots else: # assign histogram counts, no flipping because of qft representation (due to nyquist sampling?) qft_result[0] = counts[f_bin_str] / shots freq = np.arange(2**register_size) plt.plot(freq, qft_result, label='QFT') plt.xlabel('Frequency (Hz)') # print the final measurement results print('QFT spectrum:') print(qft_result) # show the plots plt.show()