def test_euler_basis_selection(self, euler_bases, kak_gates, seed): """Verify decomposition uses euler_basis for 1q gates.""" (euler_basis, oneq_gates) = euler_bases (kak_gate, kak_gate_name) = kak_gates with self.subTest(euler_basis=euler_basis, kak_gate=kak_gate): decomposer = TwoQubitBasisDecomposer(kak_gate, euler_basis=euler_basis) unitary = random_unitary(4, seed=seed) self.check_exact_decomposition(unitary.data, decomposer) decomposition_basis = set(decomposer(unitary).count_ops()) requested_basis = set(oneq_gates + [kak_gate_name]) self.assertTrue(decomposition_basis.issubset(requested_basis))
def test_global_phase_ucg(self): """Test global phase of uniformly controlled gates""" gates = [random_unitary(2).data for _ in range(2**2)] num_con = int(np.log2(len(gates))) q = QuantumRegister(num_con + 1) qc = QuantumCircuit(q) qc.uc(gates, q[1:], q[0], up_to_diagonal=False) simulator = BasicAer.get_backend("unitary_simulator") result = execute(qc, simulator).result() unitary = result.get_unitary(qc) unitary_desired = _get_ucg_matrix(gates) self.assertTrue(np.allclose(unitary_desired, unitary))
def unitary_random_gate_counts_nondeterministic(shots): """Unitary gate test circuits with nondeterministic counts.""" # random_unitary seed = nq targets = [] for n in range(1, 5): unitary1 = random_unitary(2**n, seed=n) state = Statevector.from_label(n * '0').evolve(unitary1) probs = state.probabilities_dict() hex_counts = { hex(int(key, 2)): val * shots for key, val in probs.items() } targets.append(hex_counts) return targets
def test_two_qubit_kak(self): """Verify KAK decomposition for random Haar 4x4 unitaries. """ for _ in range(100): unitary = random_unitary(4) with self.subTest(unitary=unitary): decomp_circuit = two_qubit_kak(unitary) result = execute(decomp_circuit, UnitarySimulatorPy()).result() decomp_unitary = Operator(result.get_unitary()) equal_up_to_phase = matrix_equal(unitary.data, decomp_unitary.data, ignore_phase=True, atol=1e-7) self.assertTrue(equal_up_to_phase)
def test_coupling_map_unequal_durations(self, opt): """Test direction with transpile/execute with backend durations.""" qr = QuantumRegister(2) circ = QuantumCircuit(qr) circ.append(random_unitary(4, seed=1), [1, 0]) backend = FakeVigo() tqc = transpile(circ, backend=backend, optimization_level=opt, translation_method="synthesis") tqc_index = {qubit: index for index, qubit in enumerate(tqc.qubits)} self.assertTrue( all(((0, 1) == (tqc_index[qlist[0]], tqc_index[qlist[1]]) for _, qlist, _ in tqc.get_instructions("cx"))))
def __init__(self, num_qubits: int, depth: Optional[int] = None, seed: Optional[int] = None, classical_permutation: bool = True) -> None: """Create quantum volume model circuit of size num_qubits x depth. Args: num_qubits: number of active qubits in model circuit. depth: layers of SU(4) operations in model circuit. seed: randomization seed. classical_permutation: use classical permutations at every layer, rather than quantum. """ depth = depth or num_qubits # how many layers of SU(4) width = int(np.floor(num_qubits/2)) # how many SU(4)s fit in each layer if seed is None: rng_set = np.random.RandomState() seed = rng_set.randint(low=1, high=1000) name = "quantum_volume_" + str([num_qubits, depth, seed]).replace(' ', '') super().__init__(num_qubits, name=name) rng = np.random.default_rng(seed) unitary_seeds = rng.integers(low=1, high=1000, size=[depth, width]) # For each layer, generate a permutation of qubits # Then generate and apply a Haar-random SU(4) to each pair inner = QuantumCircuit(num_qubits) perm_0 = list(range(num_qubits)) for d in range(depth): perm = rng.permutation(perm_0) if not classical_permutation: layer_perm = Permutation(num_qubits, perm) inner.compose(layer_perm, inplace=True) for w in range(width): seed_u = unitary_seeds[d][w] su4 = random_unitary(4, seed=seed_u).to_instruction() su4.label = 'su4_' + str(seed_u) if classical_permutation: physical_qubits = int(perm[2*w]), int(perm[2*w+1]) inner.compose(su4, [physical_qubits[0], physical_qubits[1]], inplace=True) else: inner.compose(su4, [2*w, 2*w+1], inplace=True) inner.label = name self.append(inner, self.qubits)
def test_approx_random_unitary_channel_2q(self): noise = Kraus(random_unitary(4, seed=123)) for opstr in ['pauli']: new_result = approximate_quantum_error(noise, operator_string=opstr) old_result = self.old_approximate_quantum_error( noise, operator_string=opstr) self.assertEqual(new_result, old_result) for opstr in ['reset']: new_result = approximate_quantum_error(noise, operator_string=opstr) old_result = self.old_approximate_quantum_error( noise, operator_string=opstr) self.assertGreaterEqual(process_fidelity(noise, new_result), process_fidelity(noise, old_result))
def test_mixed_registers(self): """Test circuit with mix of standalone and shared registers.""" qubits = [Qubit() for _ in range(5)] clbits = [Clbit() for _ in range(5)] qc = QuantumCircuit() qc.add_bits(qubits) qc.add_bits(clbits) qr = QuantumRegister(bits=qubits) cr = ClassicalRegister(bits=clbits) qc.add_register(qr) qc.add_register(cr) qr_standalone = QuantumRegister(2, "standalone") qc.add_register(qr_standalone) cr_standalone = ClassicalRegister(2, "classical_standalone") qc.add_register(cr_standalone) qc.unitary(random_unitary(32, seed=42), qr) qc.unitary(random_unitary(4, seed=100), qr_standalone) qc.measure(qr, cr) qc.measure(qr_standalone, cr_standalone) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ)
def test_two_qubit_synthesis_to_directional_cx_from_coupling_map_natural_false(self): """Verify natural cx direction is used when specified in coupling map when natural_direction is None.""" # TODO: should make check more explicit e.g. explicitly set gate # direction in test instead of using specific fake backend backend = FakeVigo() conf = backend.configuration() qr = QuantumRegister(2) coupling_map = CouplingMap([[0, 1], [1, 2], [1, 3], [3, 4]]) triv_layout_pass = TrivialLayout(coupling_map) qc = QuantumCircuit(qr) qc.unitary(random_unitary(4, seed=12), [0, 1]) unisynth_pass = UnitarySynthesis( basis_gates=conf.basis_gates, coupling_map=coupling_map, backend_props=backend.properties(), pulse_optimize=True, natural_direction=False, ) pm = PassManager([triv_layout_pass, unisynth_pass]) qc_out = pm.run(qc) unisynth_pass_nat = UnitarySynthesis( basis_gates=conf.basis_gates, coupling_map=coupling_map, backend_props=backend.properties(), pulse_optimize=True, natural_direction=False, ) pm_nat = PassManager([triv_layout_pass, unisynth_pass_nat]) qc_out_nat = pm_nat.run(qc) # the decomposer defaults to the [1, 0] direction but the coupling # map specifies a [0, 1] direction. Check that this is respected. self.assertTrue( all( # pylint: disable=no-member ([qr[1], qr[0]] == qlist for _, qlist, _ in qc_out.get_instructions("cx")) ) ) self.assertTrue( all( # pylint: disable=no-member ([qr[1], qr[0]] == qlist for _, qlist, _ in qc_out_nat.get_instructions("cx")) ) ) self.assertEqual(Operator(qc), Operator(qc_out)) self.assertEqual(Operator(qc), Operator(qc_out_nat))
def test_unitary_nottogether_across_4(self): """ Unitary that are 2 bits apart""" expected = '\n'.join([ " ┌──────────┐", "q_0: |0>┤0 ├", " │ │", "q_1: |0>┤ ├", " │ unitary │", "q_2: |0>┤ ├", " │ │", "q_3: |0>┤1 ├", " └──────────┘" ]) qr = QuantumRegister(4, 'q') qc = QuantumCircuit(qr) qc.append(random_unitary(4, seed=42), [qr[0], qr[3]]) self.assertEqual(str(_text_circuit_drawer(qc)), expected)
def test_non_overlapping_kak_gates_with_backendv2(self, opt_level): qr = QuantumRegister(2) circ = QuantumCircuit(qr) circ.append(random_unitary(4, seed=1), [1, 0]) backend = FakeBackendV2() tqc = transpile( circ, backend=backend, optimization_level=opt_level, translation_method="synthesis", layout_method="trivial", ) tqc_index = {qubit: index for index, qubit in enumerate(tqc.qubits)} self.assertGreaterEqual(len(tqc.get_instructions("ecr")), 1) for instr in tqc.get_instructions("ecr"): self.assertEqual((1, 0), (tqc_index[instr.qubits[0]], tqc_index[instr.qubits[1]]))
def qiskit_custom_unroll(): qr = QuantumRegister(5) cr = ClassicalRegister(5) qiskit_circuit = QuantumCircuit(qr, cr) """standard qiskit gates """ gate = qiskit_gates.CXGate() qiskit_circuit.append(gate, qargs=[3, 2]) gate = qiskit_gates.CZGate() qiskit_circuit.append(gate, qargs=[1, 2]) gate = qiskit_gates.HGate() qiskit_circuit.append(gate, qargs=[1]) gate = qiskit_gates.CCXGate() qiskit_circuit.append(gate, qargs=[0, 1, 2]) gate = qiskit_gates.RXGate(np.pi / 4) qiskit_circuit.append(gate, qargs=[0]) """custom gate""" # custom_matrix1 = np.array([ # [np.e**(1j*np.pi/2), 0, 0, 0], # [0, 1, 0, 0], # [0, 0, 1, 0], # [0, 0, 0, np.e**(1j*np.pi/2)] # ], dtype=complex) # custom_matrix1 = random_unitary(4, seed=42) # custom_gate1 = UnitaryGate(custom_matrix1, label="unitary_custom") # qiskit_circuit.append(custom_gate1, qargs=[0,1]) """custom gate #2""" custom_matrix1 = random_unitary(4, seed=42) custom_gate1 = UnitaryGate(custom_matrix1, label="unitary_2qubits") qiskit_circuit.append(custom_gate1, qargs=[0, 1]) """custom gate #3""" # custom_matrix1 = random_unitary(8, seed=42) # custom_gate1 = UnitaryGate(custom_matrix1, label="unitary_3qubits") # qiskit_circuit.append(custom_gate1, qargs=[0,1,2]) """custom gate #4""" # operator = Operator([[1, 0, 0, 0], # [0, 0, 0, 1], # [0, 0, 1, 0], # [0, 1, 0, 0]]) # custom_gate1 = UnitaryGate(custom_matrix1, label="operator") # qiskit_circuit.unitary(operator, [0,1], label="operator") """parameterized qiskit cirucit""" # theta = qiskit_circuit_library.Parameter("θ") # qiskit_circuit.rz(theta, 1) # show_figure(qiskit_circuit) return qiskit_circuit
def test_one_qubit_euler_angles(self): """Verify euler_angles_1q produces correct Euler angles for a single-qubit unitary. """ for _ in range(100): unitary = random_unitary(2) with self.subTest(unitary=unitary): angles = euler_angles_1q(unitary.data) decomp_circuit = QuantumCircuit(1) decomp_circuit.u3(*angles, 0) result = execute(decomp_circuit, UnitarySimulatorPy()).result() decomp_unitary = Operator(result.get_unitary()) equal_up_to_phase = matrix_equal(unitary.data, decomp_unitary.data, ignore_phase=True, atol=1e-7) self.assertTrue(equal_up_to_phase)
def test_scale(self): """Tests scale See: https://github.com/Qiskit/qiskit-terra/issues/4179""" filename1 = self._get_resource_path('test_latex_scale_default.tex') filename2 = self._get_resource_path('test_latex_scale_half.tex') filename3 = self._get_resource_path('test_latex_scale_double.tex') circuit = QuantumCircuit(5) circuit.unitary(random_unitary(2 ** 5), circuit.qubits) circuit_drawer(circuit, filename=filename1, output='latex_source') self.assertEqualToReference(filename1) circuit_drawer(circuit, filename=filename2, output='latex_source', scale=0.5) self.assertEqualToReference(filename2) circuit_drawer(circuit, filename=filename3, output='latex_source', scale=2.0) self.assertEqualToReference(filename3)
def build_model_circuit(width, depth, seed=None): """ The model circuits consist of layers of Haar random elements of SU(4) applied between corresponding pairs of qubits in a random bipartition. """ np.random.seed(seed) circuit = QuantumCircuit(width) # For each layer for _ in range(depth): # Generate uniformly random permutation Pj of [0...n-1] perm = np.random.permutation(width) # For each pair p in Pj, generate Haar random SU(4) for k in range(int(np.floor(width / 2))): U = random_unitary(4) pair = int(perm[2 * k]), int(perm[2 * k + 1]) circuit.append(U, [pair[0], pair[1]]) return circuit
def test_isometry(self): """Tests for the decomposition of isometries from m to n qubits""" for iso in [ np.eye(2, 2), random_unitary(2).data, np.eye(4, 4), random_unitary(4).data[:, 0], np.eye(4, 4)[:, 0:2], random_unitary(4).data, np.eye(4, 4)[:, np.random.permutation(np.eye(4, 4).shape[1])][:, 0:2], np.eye(8, 8)[:, np.random.permutation(np.eye(8, 8).shape[1])], random_unitary(8).data[:, 0:4], random_unitary(8).data, random_unitary(16).data, random_unitary(16).data[:, 0:8] ]: with self.subTest(iso=iso): if len(iso.shape) == 1: iso = iso.reshape((len(iso), 1)) num_q_input = int(np.log2(iso.shape[1])) num_q_ancilla_for_output = int(np.log2( iso.shape[0])) - num_q_input n = num_q_input + num_q_ancilla_for_output q = QuantumRegister(n) qc = QuantumCircuit(q) qc.isometry(iso, q[:num_q_input], q[num_q_input:]) # Verify the circuit can be decomposed self.assertIsInstance(qc.decompose(), QuantumCircuit) # Decompose the gate qc = transpile(qc, basis_gates=['u1', 'u3', 'u2', 'cx', 'id']) # Simulate the decomposed gate simulator = BasicAer.get_backend('unitary_simulator') result = execute(qc, simulator).result() unitary = result.get_unitary(qc) iso_from_circuit = unitary[::, 0:2**num_q_input] iso_desired = iso self.assertTrue( matrix_equal(iso_from_circuit, iso_desired, ignore_phase=True))
def unitary_random_gate_circuits_nondeterministic(final_measure=True): """Unitary gate test circuits with random unitary gate and nondeterministic count output.""" # random_unitary seed = nq circuits = [] for n in range(1, 5): qr = QuantumRegister(n, 'qr') if final_measure: cr = ClassicalRegister(n, 'cr') regs = (qr, cr) else: regs = (qr, ) circuit = QuantumCircuit(*regs) circuit.unitary(random_unitary(2**n, seed=n), list(range(n))) if final_measure: circuit.barrier(qr) circuit.measure(qr, cr) circuits.append(circuit) return circuits
def __init__(self, num_qubits: int, depth: Optional[int] = None, seed: Optional[int] = None) -> QuantumCircuit: """Create quantum volume model circuit of size num_qubits x depth. Args: num_qubits: number of active qubits in model circuit. depth: layers of SU(4) operations in model circuit. seed: randomization seed. Returns: QuantumCircuit: a randomly constructed quantum volume model circuit. Reference Circuit: .. jupyter-execute:: :hide-code: from qiskit.circuit.library import QuantumVolume import qiskit.tools.jupyter circuit = QuantumVolume(5, seed=42) %circuit_library_info circuit """ super().__init__(num_qubits, name="volume") depth = depth or num_qubits # how many layers of SU(4) width = int(np.floor(num_qubits / 2)) # how many SU(4)s fit in each layer rng = np.random.RandomState(seed) unitary_seeds = rng.randint(low=1, high=1000, size=[depth, width]) # For each layer, generate a permutation of qubits # Then generate and apply a Haar-random SU(4) to each pair perm_0 = list(range(num_qubits)) for d in range(depth): perm = rng.permutation(perm_0) for w in range(width): physical_qubits = int(perm[2 * w]), int(perm[2 * w + 1]) su4 = random_unitary(4, seed=unitary_seeds[d][w]) self.append(su4, [physical_qubits[0], physical_qubits[1]])
def test_reverse_direction(self, opt_level): target = Target(2) target.add_instruction(CXGate(), {(0, 1): InstructionProperties(error=1.2e-6)}) target.add_instruction(ECRGate(), {(0, 1): InstructionProperties(error=1.2e-7)}) target.add_instruction( UGate(Parameter("theta"), Parameter("phi"), Parameter("lam")), {(0,): None, (1,): None} ) qr = QuantumRegister(2) circ = QuantumCircuit(qr) circ.append(random_unitary(4, seed=1), [1, 0]) tqc = transpile( circ, target=target, optimization_level=opt_level, translation_method="synthesis", layout_method="trivial", ) tqc_index = {qubit: index for index, qubit in enumerate(tqc.qubits)} self.assertGreaterEqual(len(tqc.get_instructions("ecr")), 1) for instr in tqc.get_instructions("ecr"): self.assertEqual((0, 1), (tqc_index[instr.qubits[0]], tqc_index[instr.qubits[1]]))
def test_coupling_unequal_duration_with_backendv2(self, opt_level, bidirectional): qr = QuantumRegister(2) circ = QuantumCircuit(qr) circ.append(random_unitary(4, seed=1), [1, 0]) backend = FakeBackend5QV2(bidirectional) tqc = transpile( circ, backend=backend, optimization_level=opt_level, translation_method="synthesis", layout_method="trivial", ) tqc_index = {qubit: index for index, qubit in enumerate(tqc.qubits)} self.assertGreaterEqual(len(tqc.get_instructions("cx")), 1) if bidirectional: for instr in tqc.get_instructions("cx"): self.assertEqual((1, 0), (tqc_index[instr.qubits[0]], tqc_index[instr.qubits[1]])) else: for instr in tqc.get_instructions("cx"): self.assertEqual((0, 1), (tqc_index[instr.qubits[0]], tqc_index[instr.qubits[1]]))
def test_two_qubit_pulse_optimal_true_raises(self): """Verify raises if pulse optimal==True but cx is not in the backend basis.""" backend = FakeVigo() conf = backend.configuration() # this assumes iswawp pulse optimal decomposition doesn't exist conf.basis_gates = [gate if gate != "cx" else "iswap" for gate in conf.basis_gates] qr = QuantumRegister(2) coupling_map = CouplingMap([[0, 1], [1, 2], [1, 3], [3, 4]]) triv_layout_pass = TrivialLayout(coupling_map) qc = QuantumCircuit(qr) qc.unitary(random_unitary(4, seed=12), [0, 1]) unisynth_pass = UnitarySynthesis( basis_gates=conf.basis_gates, coupling_map=coupling_map, backend_props=backend.properties(), pulse_optimize=True, natural_direction=True, ) pm = PassManager([triv_layout_pass, unisynth_pass]) with self.assertRaises(QiskitError): pm.run(qc)
def build_model_circuit_kak(width, depth, seed=None): """Create quantum volume model circuit on quantum register qreg of given depth (default depth is equal to width) and random seed. The model circuits consist of layers of Haar random elements of U(4) applied between corresponding pairs of qubits in a random bipartition. """ qreg = QuantumRegister(width) depth = depth or width np.random.seed(seed) circuit = QuantumCircuit(qreg, name="Qvolume: %s by %s, seed: %s" % (width, depth, seed)) for _ in range(depth): # Generate uniformly random permutation Pj of [0...n-1] perm = np.random.permutation(width) # For each pair p in Pj, generate Haar random U(4) # Decompose each U(4) into CNOT + SU(2) for k in range(width // 2): U = random_unitary(4, seed).data for gate in two_qubit_cnot_decompose(U): qs = [qreg[int(perm[2 * k + i.index])] for i in gate[1]] pars = gate[0].params name = gate[0].name if name == "cx": circuit.cx(qs[0], qs[1]) elif name == "u1": circuit.u1(pars[0], qs[0]) elif name == "u2": circuit.u2(*pars[:2], qs[0]) elif name == "u3": circuit.u3(*pars[:3], qs[0]) elif name == "id": pass # do nothing else: raise Exception("Unexpected gate name: %s" % name) return circuit
def test_unitary(self): """Test unitary gate instruction""" num_trials = 10 max_qubits = 3 # Test 1 to max_qubits for random n-qubit unitary gate for i in range(max_qubits): num_qubits = i + 1 unitary_init = Operator(np.eye(2 ** num_qubits)) qr = QuantumRegister(num_qubits, "qr") for _ in range(num_trials): # Create random unitary unitary = random_unitary(2 ** num_qubits) # Compute expected output state unitary_target = unitary.dot(unitary_init) # Simulate output on circuit circuit = QuantumCircuit(qr) circuit.unitary(unitary, qr) job = execute(circuit, self.backend) result = job.result() unitary_out = Operator(result.get_unitary(0)) fidelity = process_fidelity(unitary_target, unitary_out) self.assertGreater(fidelity, 0.999)
def test_two_qubit_natural_direction_true_gate_length_raises(self): """Verify not attempting pulse optimal decomposition when pulse_optimize==False.""" # this assumes iswawp pulse optimal decomposition doesn't exist backend = FakeVigo() conf = backend.configuration() for _, nduv in backend.properties()._gates["cx"].items(): nduv["gate_length"] = (4e-7, nduv["gate_length"][1]) nduv["gate_error"] = (7e-3, nduv["gate_error"][1]) qr = QuantumRegister(2) coupling_map = CouplingMap([[0, 1], [1, 0], [1, 2], [1, 3], [3, 4]]) triv_layout_pass = TrivialLayout(coupling_map) qc = QuantumCircuit(qr) qc.unitary(random_unitary(4, seed=12), [0, 1]) unisynth_pass = UnitarySynthesis( basis_gates=conf.basis_gates, backend_props=backend.properties(), pulse_optimize=True, natural_direction=True, ) pm = PassManager([triv_layout_pass, unisynth_pass]) with self.assertRaises(TranspilerError): pm.run(qc)
def test_mps_options(self): """Test MPS options""" shots = 4000 method="matrix_product_state" backend_swap_left = self.backend(method=method, mps_swap_direction='mps_swap_left') backend_swap_right = self.backend(method=method, mps_swap_direction='mps_swap_right') backend_approx = self.backend(method=method, matrix_product_state_max_bond_dimension=8) # The test must be large enough and entangled enough so that # approximation actually truncates something n = 10 circuit = QuantumCircuit(n) for times in range(2): for i in range(0, n, 2): circuit.unitary(random_unitary(4), [i, i+1]) for i in range(1, n-1): circuit.cx(0, i) circuit.save_statevector('sv') result_swap_left = backend_swap_left.run(circuit, shots=shots).result() sv_left = result_swap_left.data(0)['sv'] result_swap_right = backend_swap_right.run(circuit, shots=shots).result() sv_right = result_swap_right.data(0)['sv'] result_approx = backend_approx.run(circuit, shots=shots).result() sv_approx = result_approx.data(0)['sv'] # swap_left and swap_right should give the same state vector self.assertAlmostEqual(state_fidelity(sv_left, sv_right), 1.0) # Check that the fidelity of approximation is reasonable self.assertGreaterEqual(state_fidelity(sv_left, sv_approx), 0.80) # Check that the approximated result is not identical to the exact # result, because that could mean there was actually no approximation self.assertLessEqual(state_fidelity(sv_left, sv_approx), 0.999)
def test_two_qubit_natural_direction_true_duration_fallback(self): """Verify not attempting pulse optimal decomposition when pulse_optimize==False.""" # this assumes iswawp pulse optimal decomposition doesn't exist backend = FakeVigo() conf = backend.configuration() # conf.basis_gates = [gate if gate != "cx" else "iswap" for gate in conf.basis_gates] qr = QuantumRegister(2) coupling_map = CouplingMap([[0, 1], [1, 0], [1, 2], [1, 3], [3, 4]]) triv_layout_pass = TrivialLayout(coupling_map) qc = QuantumCircuit(qr) qc.unitary(random_unitary(4, seed=12), [0, 1]) unisynth_pass = UnitarySynthesis( basis_gates=conf.basis_gates, coupling_map=coupling_map, backend_props=backend.properties(), pulse_optimize=True, natural_direction=True, ) pm = PassManager([triv_layout_pass, unisynth_pass]) qc_out = pm.run(qc) self.assertTrue( all(((qr[0], qr[1]) == instr.qubits for instr in qc_out.get_instructions("cx"))) )
def test_unitary(self): """Test unitary gate instruction""" num_trials = 10 max_qubits = 3 # Test 1 to max_qubits for random n-qubit unitary gate for i in range(max_qubits): num_qubits = i + 1 psi_init = np.zeros(2**num_qubits) psi_init[0] = 1.0 qr = QuantumRegister(num_qubits, 'qr') for _ in range(num_trials): # Create random unitary unitary = random_unitary(2**num_qubits) # Compute expected output state psi_target = unitary.data.dot(psi_init) # Simulate output on circuit circuit = QuantumCircuit(qr) circuit.unitary(unitary, qr) job = execute(circuit, self.backend) result = job.result() psi_out = result.get_statevector(0) fidelity = state_fidelity(psi_target, psi_out) self.assertGreater(fidelity, 0.999)
def test_random_unitary_gate_with_permutations(self, method, device, perm): """Test simulation with random unitary gate with permutations.""" backend = self.backend(method=method, device=device) all_permutations = list(itertools.permutations([0, 1, 2])) unitary_matrix = random_unitary(8, seed=5) n = 3 shots = 2000 circuit = QuantumCircuit(n, n) circuit.unitary(unitary_matrix, perm) circuit.barrier(range(n)) circuit.measure(range(n), range(n)) circuits = transpile(circuit, backend) result = backend.run(circuits, shots=shots).result() state = Statevector.from_label(n * '0').evolve(unitary_matrix, perm) state.seed(11111) probs = state.probabilities_dict() hex_counts = { hex(int(key, 2)): val * shots for key, val in probs.items() } self.assertSuccess(result) self.compare_counts(result, [circuit], [hex_counts], delta=0.05 * shots)
def test_two_qubit_synthesis_not_pulse_optimal(self): """Verify not attempting pulse optimal decomposition when pulse_optimize==False.""" backend = FakeVigo() conf = backend.configuration() qr = QuantumRegister(2) coupling_map = CouplingMap([[0, 1], [1, 2], [1, 3], [3, 4]]) triv_layout_pass = TrivialLayout(coupling_map) qc = QuantumCircuit(qr) qc.unitary(random_unitary(4, seed=12), [0, 1]) unisynth_pass = UnitarySynthesis( basis_gates=conf.basis_gates, coupling_map=coupling_map, backend_props=backend.properties(), pulse_optimize=False, natural_direction=True, ) pm = PassManager([triv_layout_pass, unisynth_pass]) qc_out = pm.run(qc) if isinstance(qc_out, QuantumCircuit): num_ops = qc_out.count_ops() else: num_ops = qc_out[0].count_ops() self.assertIn("sx", num_ops) self.assertGreaterEqual(num_ops["sx"], 16)
def test_random_unitary_gate_with_permutations(self): """Test simulation with random unitary gate with permutations.""" all_permutations = list(itertools.permutations([0, 1, 2])) unitary_matrix = random_unitary(8, seed=5) n = 3 shots = 2000 for perm in all_permutations: circuit = QuantumCircuit(n, n) circuit.unitary(unitary_matrix, perm) circuit.barrier(range(n)) circuit.measure(range(n), range(n)) result = execute(circuit, self.SIMULATOR, shots=shots, optimization_level=0, **self.BACKEND_OPTS).result() state = Statevector.from_label(n * '0').evolve( unitary_matrix, perm) counts = state.sample_counts(shots=shots) hex_counts = {hex(int(key, 2)): val for key, val in counts.items()} self.assertSuccess(result) self.compare_counts(result, [circuit], [hex_counts], delta=0.05 * shots)