def test_qubits_with_instruction_gate(self): """Test `qubits_with_instruction`.""" sched = Schedule() inst_map = InstructionScheduleMap() inst_map.add(U1Gate(0), (0, ), sched) inst_map.add(U1Gate(0), (1, ), sched) inst_map.add(CXGate(), [0, 1], sched) self.assertEqual(inst_map.qubits_with_instruction(U1Gate(0)), [0, 1]) self.assertEqual(inst_map.qubits_with_instruction(CXGate()), [(0, 1)]) self.assertEqual(inst_map.qubits_with_instruction('none'), [])
def test_has_from_mock_gate(self): """Test `has` and `assert_has` from mock data.""" inst_map = FakeOpenPulse2Q().defaults().instruction_schedule_map self.assertTrue(inst_map.has(U1Gate(0), [0])) self.assertTrue(inst_map.has(CXGate(), (0, 1))) self.assertTrue(inst_map.has(U3Gate(0, 0, 0), 0)) self.assertTrue(inst_map.has('measure', [0, 1])) self.assertFalse(inst_map.has(U1Gate(0), [0, 1])) with self.assertRaises(PulseError): inst_map.assert_has('dne', [0]) with self.assertRaises(PulseError): inst_map.assert_has(CXGate(), 100)
def test_has_gate(self): """Test `has` and `assert_has`.""" sched = Schedule() inst_map = InstructionScheduleMap() inst_map.add(U1Gate(0), (0, ), sched) inst_map.add(CXGate(), [0, 1], sched) self.assertTrue(inst_map.has(U1Gate(0), [0])) self.assertTrue(inst_map.has(CXGate(), (0, 1))) with self.assertRaises(PulseError): inst_map.assert_has('dne', [0]) with self.assertRaises(PulseError): inst_map.assert_has(CXGate(), 100)
def run(self, dag): """Run the CXDirection pass on `dag`. Flips the cx nodes to match the directed coupling map. Modifies the input dag. Args: dag (DAGCircuit): DAG to map. Returns: DAGCircuit: The rearranged dag for the coupling map Raises: TranspilerError: If the circuit cannot be mapped just by flipping the cx nodes. """ cmap_edges = set(self.coupling_map.get_edges()) if len(dag.qregs) > 1: raise TranspilerError( 'CXDirection expects a single qreg input DAG,' 'but input DAG had qregs: {}.'.format(dag.qregs)) trivial_layout = Layout.generate_trivial_layout(*dag.qregs.values()) for cnot_node in dag.named_nodes('cx', 'CX'): control = cnot_node.qargs[0] target = cnot_node.qargs[1] physical_q0 = trivial_layout[control] physical_q1 = trivial_layout[target] if self.coupling_map.distance(physical_q0, physical_q1) != 1: raise TranspilerError( 'The circuit requires a connection between physical ' 'qubits %s and %s' % (physical_q0, physical_q1)) if (physical_q0, physical_q1) not in cmap_edges: # A flip needs to be done # Create the replacement dag and associated register. sub_dag = DAGCircuit() sub_qr = QuantumRegister(2) sub_dag.add_qreg(sub_qr) # Add H gates before sub_dag.apply_operation_back(U2Gate(0, pi), [sub_qr[0]], []) sub_dag.apply_operation_back(U2Gate(0, pi), [sub_qr[1]], []) # Flips the cx sub_dag.apply_operation_back(CXGate(), [sub_qr[1], sub_qr[0]], []) # Add H gates after sub_dag.apply_operation_back(U2Gate(0, pi), [sub_qr[0]], []) sub_dag.apply_operation_back(U2Gate(0, pi), [sub_qr[1]], []) dag.substitute_node_with_dag(cnot_node, sub_dag) return dag
def __init__(self, coupling_map, target=None): """GateDirection pass. Args: coupling_map (CouplingMap): Directed graph represented a coupling map. target (Target): The backend target to use for this pass. If this is specified it will be used instead of the coupling map """ super().__init__() self.coupling_map = coupling_map self.target = target # Create the replacement dag and associated register. self._cx_dag = DAGCircuit() qr = QuantumRegister(2) self._cx_dag.add_qreg(qr) self._cx_dag.apply_operation_back(HGate(), [qr[0]], []) self._cx_dag.apply_operation_back(HGate(), [qr[1]], []) self._cx_dag.apply_operation_back(CXGate(), [qr[1], qr[0]], []) self._cx_dag.apply_operation_back(HGate(), [qr[0]], []) self._cx_dag.apply_operation_back(HGate(), [qr[1]], []) self._ecr_dag = DAGCircuit() qr = QuantumRegister(2) self._ecr_dag.add_qreg(qr) self._ecr_dag.apply_operation_back(RYGate(-pi / 2), [qr[0]], []) self._ecr_dag.apply_operation_back(RYGate(pi / 2), [qr[1]], []) self._ecr_dag.apply_operation_back(ECRGate(), [qr[1], qr[0]], []) self._ecr_dag.apply_operation_back(HGate(), [qr[0]], []) self._ecr_dag.apply_operation_back(HGate(), [qr[1]], [])
def __init__(self, kak_basis_gate=None, force_consolidate=False, basis_gates=None): """ConsolidateBlocks initializer. Args: kak_basis_gate (Gate): Basis gate for KAK decomposition. force_consolidate (bool): Force block consolidation basis_gates (List(str)): Basis gates from which to choose a KAK gate. """ super().__init__() self.basis_gates = basis_gates self.force_consolidate = force_consolidate if kak_basis_gate is not None: self.decomposer = TwoQubitBasisDecomposer(kak_basis_gate) elif basis_gates is not None: kak_basis_gate = unitary_synthesis._choose_kak_gate(basis_gates) if kak_basis_gate is not None: self.decomposer = TwoQubitBasisDecomposer(kak_basis_gate) else: self.decomposer = None else: self.decomposer = TwoQubitBasisDecomposer(CXGate())
def __init__(self, coupling_map): """GateDirection pass. Args: coupling_map (CouplingMap): Directed graph represented a coupling map. """ super().__init__() self.coupling_map = coupling_map # Create the replacement dag and associated register. self._cx_dag = DAGCircuit() qr = QuantumRegister(2) self._cx_dag.add_qreg(qr) self._cx_dag.apply_operation_back(HGate(), [qr[0]], []) self._cx_dag.apply_operation_back(HGate(), [qr[1]], []) self._cx_dag.apply_operation_back(CXGate(), [qr[1], qr[0]], []) self._cx_dag.apply_operation_back(HGate(), [qr[0]], []) self._cx_dag.apply_operation_back(HGate(), [qr[1]], []) self._ecr_dag = DAGCircuit() qr = QuantumRegister(2) self._ecr_dag.add_qreg(qr) self._ecr_dag.apply_operation_back(RYGate(-pi / 2), [qr[0]], []) self._ecr_dag.apply_operation_back(RYGate(pi / 2), [qr[1]], []) self._ecr_dag.apply_operation_back(ECRGate(), [qr[1], qr[0]], []) self._ecr_dag.apply_operation_back(HGate(), [qr[0]], []) self._ecr_dag.apply_operation_back(HGate(), [qr[1]], [])
def __init__(self, kak_basis_gate=None, force_consolidate=False, basis_gates=None, target=None): """ConsolidateBlocks initializer. Args: kak_basis_gate (Gate): Basis gate for KAK decomposition. force_consolidate (bool): Force block consolidation basis_gates (List(str)): Basis gates from which to choose a KAK gate. target (Target): The target object for the compilation target backend """ super().__init__() self.basis_gates = None self.target = target if basis_gates is not None: self.basis_gates = set(basis_gates) self.force_consolidate = force_consolidate if kak_basis_gate is not None: self.decomposer = TwoQubitBasisDecomposer(kak_basis_gate) elif basis_gates is not None: self.decomposer = unitary_synthesis._basis_gates_to_decomposer_2q( basis_gates) else: self.decomposer = TwoQubitBasisDecomposer(CXGate())
def __init__(self, kak_basis_gate=CXGate(), force_consolidate=False): """ConsolidateBlocks initializer. Args: kak_basis_gate (Gate): Basis gate for KAK decomposition. force_consolidate (bool): Force block consolidation """ super().__init__() self.force_consolidate = force_consolidate self.decomposer = TwoQubitBasisDecomposer(kak_basis_gate)
def __init__(self): super().__init__( None, name="FakeV2", description="A fake BackendV2 example", online_date=datetime.datetime.utcnow(), backend_version="0.0.1", ) self._target = Target() self._theta = Parameter("theta") self._phi = Parameter("phi") self._lam = Parameter("lambda") rx_props = { (0, ): InstructionProperties(duration=5.23e-8, error=0.00038115), (1, ): InstructionProperties(duration=4.52e-8, error=0.00032115), } self._target.add_instruction(RXGate(self._theta), rx_props) rx_30_props = { (0, ): InstructionProperties(duration=1.23e-8, error=0.00018115), (1, ): InstructionProperties(duration=1.52e-8, error=0.00012115), } self._target.add_instruction(RXGate(np.pi / 6), rx_30_props, name="rx_30") u_props = { (0, ): InstructionProperties(duration=5.23e-8, error=0.00038115), (1, ): InstructionProperties(duration=4.52e-8, error=0.00032115), } self._target.add_instruction(UGate(self._theta, self._phi, self._lam), u_props) cx_props = { (0, 1): InstructionProperties(duration=5.23e-7, error=0.00098115), } self._target.add_instruction(CXGate(), cx_props) measure_props = { (0, ): InstructionProperties(duration=6e-6, error=5e-6), (1, ): InstructionProperties(duration=1e-6, error=9e-6), } self._target.add_instruction(Measure(), measure_props) ecr_props = { (1, 0): InstructionProperties(duration=4.52e-9, error=0.0000132115), } self._target.add_instruction(ECRGate(), ecr_props) self.options.set_validator("shots", (1, 4096)) self._qubit_properties = { 0: QubitProperties(t1=63.48783e-6, t2=112.23246e-6, frequency=5.17538e9), 1: QubitProperties(t1=73.09352e-6, t2=126.83382e-6, frequency=5.26722e9), }
def __init__(self, bidirectional=True): super().__init__( None, name="Fake5QV2", description="A fake BackendV2 example", online_date=datetime.datetime.utcnow(), backend_version="0.0.1", ) self._target = Target() self._theta = Parameter("theta") self._phi = Parameter("phi") self._lam = Parameter("lambda") u_props = { (0,): InstructionProperties(duration=5.23e-8, error=0.00038115), (1,): InstructionProperties(duration=4.52e-8, error=0.00032115), (2,): InstructionProperties(duration=5.23e-8, error=0.00038115), (3,): InstructionProperties(duration=4.52e-8, error=0.00032115), (4,): InstructionProperties(duration=4.52e-8, error=0.00032115), } self._target.add_instruction(UGate(self._theta, self._phi, self._lam), u_props) cx_props = { (0, 1): InstructionProperties(duration=5.23e-7, error=0.00098115), (3, 4): InstructionProperties(duration=5.23e-7, error=0.00098115), } if bidirectional: cx_props[(1, 0)] = InstructionProperties(duration=6.23e-7, error=0.00099115) cx_props[(4, 3)] = InstructionProperties(duration=7.23e-7, error=0.00099115) self._target.add_instruction(CXGate(), cx_props) measure_props = { (0,): InstructionProperties(duration=6e-6, error=5e-6), (1,): InstructionProperties(duration=1e-6, error=9e-6), (2,): InstructionProperties(duration=6e-6, error=5e-6), (3,): InstructionProperties(duration=1e-6, error=9e-6), (4,): InstructionProperties(duration=1e-6, error=9e-6), } self._target.add_instruction(Measure(), measure_props) ecr_props = { (1, 2): InstructionProperties(duration=4.52e-9, error=0.0000132115), (2, 3): InstructionProperties(duration=4.52e-9, error=0.0000132115), } if bidirectional: ecr_props[(2, 1)] = InstructionProperties(duration=5.52e-9, error=0.0000232115) ecr_props[(3, 2)] = InstructionProperties(duration=5.52e-9, error=0.0000232115) self._target.add_instruction(ECRGate(), ecr_props) self.options.set_validator("shots", (1, 4096)) self._qubit_properties = { 0: QubitProperties(t1=63.48783e-6, t2=112.23246e-6, frequency=5.17538e9), 1: QubitProperties(t1=73.09352e-6, t2=126.83382e-6, frequency=5.26722e9), 2: QubitProperties(t1=73.09352e-6, t2=126.83382e-6, frequency=5.26722e9), 3: QubitProperties(t1=73.09352e-6, t2=126.83382e-6, frequency=5.26722e9), 4: QubitProperties(t1=73.09352e-6, t2=126.83382e-6, frequency=5.26722e9), }
def test_qubit_instructions_gate(self): """Test `qubit_instructions`.""" sched = Schedule() inst_map = InstructionScheduleMap() inst_map.add(U1Gate(0), (0, ), sched) inst_map.add(U1Gate(0), (1, ), sched) inst_map.add(CXGate(), [0, 1], sched) self.assertEqual(inst_map.qubit_instructions(0), ['u1']) self.assertEqual(inst_map.qubit_instructions(1), ['u1']) self.assertEqual(inst_map.qubit_instructions((0, 1)), ['cx']) self.assertEqual(inst_map.qubit_instructions(10), [])
def _basis_gates_to_decomposer_2q(basis_gates, pulse_optimize=None): kak_gate = _choose_kak_gate(basis_gates) euler_basis = _choose_euler_basis(basis_gates) if isinstance(kak_gate, RZXGate): backup_optimizer = TwoQubitBasisDecomposer( CXGate(), euler_basis=euler_basis, pulse_optimize=pulse_optimize) return XXDecomposer(euler_basis=euler_basis, backup_optimizer=backup_optimizer) elif kak_gate is not None: return TwoQubitBasisDecomposer(kak_gate, euler_basis=euler_basis, pulse_optimize=pulse_optimize) else: return None
def _choose_kak_gate(basis_gates): """Choose the first available 2q gate to use in the KAK decomposition.""" kak_gate_names = { 'cx': CXGate(), 'cz': CZGate(), 'iswap': iSwapGate(), 'rxx': RXXGate(pi / 2), } kak_gate = None kak_gates = set(basis_gates or []).intersection(kak_gate_names.keys()) if kak_gates: kak_gate = kak_gate_names[kak_gates.pop()] return kak_gate
def __init__(self): super().__init__( None, name="FakeSimpleV2", description="A fake simple BackendV2 example", online_date=datetime.datetime.utcnow(), backend_version="0.0.1", ) self._lam = Parameter("lambda") self._target = Target(num_qubits=20) self._target.add_instruction(SXGate()) self._target.add_instruction(XGate()) self._target.add_instruction(RZGate(self._lam)) self._target.add_instruction(CXGate()) self._target.add_instruction(Measure()) self._runner = QasmSimulatorPy()
def _choose_kak_gate(basis_gates): """Choose the first available 2q gate to use in the KAK decomposition.""" kak_gate_names = { "cx": CXGate(), "cz": CZGate(), "iswap": iSwapGate(), "rxx": RXXGate(pi / 2), "ecr": ECRGate(), } kak_gate = None kak_gates = set(basis_gates or []).intersection(kak_gate_names.keys()) if kak_gates: kak_gate = kak_gate_names[kak_gates.pop()] return kak_gate
def random_linear_circuit(num_qubits, num_gates, seed=None): """Generate a pseudo random linear circuit.""" instructions = { "cx": (CXGate(), 2), "swap": (SwapGate(), 2), } if isinstance(seed, np.random.Generator): rng = seed else: rng = np.random.default_rng(seed) name_samples = rng.choice(tuple(instructions), num_gates) circ = QuantumCircuit(num_qubits) for name in name_samples: gate, nqargs = instructions[name] qargs = rng.choice(range(num_qubits), nqargs, replace=False).tolist() circ.append(gate, qargs) return circ
def _standard_gate_instruction(instruction, ignore_phase=True): """Temporary function to create Instruction objects from a json string, which is necessary for creating a new QuantumError object from deprecated json-based input. Note that the type of returned object is different from the deprecated standard_gate_instruction. TODO: to be removed after deprecation period. Args: instruction (dict): A qobj instruction. ignore_phase (bool): Ignore global phase on unitary matrix in comparison to canonical unitary. Returns: list: a list of (instructions, qubits) equivalent to in input instruction. """ gate = { "id": IGate(), "x": XGate(), "y": YGate(), "z": ZGate(), "h": HGate(), "s": SGate(), "sdg": SdgGate(), "t": TGate(), "tdg": TdgGate(), "cx": CXGate(), "cz": CZGate(), "swap": SwapGate() } name = instruction.get("name", None) qubits = instruction["qubits"] if name in gate: return [(gate[name], qubits)] if name not in ["mat", "unitary", "kraus"]: return [instruction] params = instruction["params"] with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit.providers.aer.noise.errors.errorutils") # Check for single-qubit reset Kraus if name == "kraus": if len(qubits) == 1: superop = SuperOp(Kraus(params)) # Check if reset to |0> reset0 = reset_superop(1) if superop == reset0: return [(Reset(), [0])] # Check if reset to |1> reset1 = reset0.compose(Operator(standard_gate_unitary('x'))) if superop == reset1: return [(Reset(), [0]), (XGate(), [0])] return [instruction] # Check single qubit gates mat = params[0] if len(qubits) == 1: # Check clifford gates for j in range(24): if matrix_equal( mat, single_qubit_clifford_matrix(j), ignore_phase=ignore_phase): return [(gate, [0]) for gate in _CLIFFORD_GATES[j]] # Check t gates for name in ["t", "tdg"]: if matrix_equal( mat, standard_gate_unitary(name), ignore_phase=ignore_phase): return [(gate[name], qubits)] # TODO: u1,u2,u3 decomposition # Check two qubit gates if len(qubits) == 2: for name in ["cx", "cz", "swap"]: if matrix_equal( mat, standard_gate_unitary(name), ignore_phase=ignore_phase): return [(gate[name], qubits)] # Check reversed CX if matrix_equal( mat, standard_gate_unitary("cx_10"), ignore_phase=ignore_phase): return [(CXGate(), [qubits[1], qubits[0]])] # Check 2-qubit Pauli's paulis = ["id", "x", "y", "z"] for pauli0 in paulis: for pauli1 in paulis: pmat = np.kron( standard_gate_unitary(pauli1), standard_gate_unitary(pauli0)) if matrix_equal(mat, pmat, ignore_phase=ignore_phase): if pauli0 == "id": return [(gate[pauli1], [qubits[1]])] elif pauli1 == "id": return [(gate[pauli0], [qubits[0]])] else: return [(gate[pauli0], [qubits[0]]), (gate[pauli1], [qubits[1]])] # Check three qubit toffoli if len(qubits) == 3: if matrix_equal( mat, standard_gate_unitary("ccx_012"), ignore_phase=ignore_phase): return [(CCXGate(), qubits)] if matrix_equal( mat, standard_gate_unitary("ccx_021"), ignore_phase=ignore_phase): return [(CCXGate(), [qubits[0], qubits[2], qubits[1]])] if matrix_equal( mat, standard_gate_unitary("ccx_120"), ignore_phase=ignore_phase): return [(CCXGate(), [qubits[1], qubits[2], qubits[0]])] # Else return input in return [instruction]
from qiskit.quantum_info.synthesis.xx_decompose import XXDecomposer from qiskit.quantum_info.synthesis.two_qubit_decompose import TwoQubitBasisDecomposer from qiskit.circuit.parameter import Parameter from qiskit.circuit.library.standard_gates import ( iSwapGate, CXGate, CZGate, RXXGate, RZXGate, ECRGate, ) from qiskit.transpiler.passes.synthesis import plugin from qiskit.providers.models import BackendProperties KAK_GATE_NAMES = { "cx": CXGate(), "cz": CZGate(), "iswap": iSwapGate(), "rxx": RXXGate(pi / 2), "ecr": ECRGate(), "rzx": RZXGate(pi / 4), # typically pi/6 is also available } def _choose_kak_gate(basis_gates): """Choose the first available 2q gate to use in the KAK decomposition.""" kak_gate = None kak_gates = set(basis_gates or []).intersection(KAK_GATE_NAMES.keys()) if kak_gates: kak_gate = KAK_GATE_NAMES[kak_gates.pop()]
def convert_to_target(conf_dict: dict, props_dict: dict = None, defs_dict: dict = None) -> Target: """Uses configuration, properties and pulse defaults dicts to construct and return Target class. """ name_mapping = { "id": IGate(), "sx": SXGate(), "x": XGate(), "cx": CXGate(), "rz": RZGate(Parameter("λ")), "reset": Reset(), } custom_gates = {} qubit_props = None if props_dict: qubit_props = qubit_props_from_props(props_dict) target = Target(qubit_properties=qubit_props) # Parse from properties if it exsits if props_dict is not None: # Parse instructions gates = {} for gate in props_dict["gates"]: name = gate["gate"] if name in name_mapping: if name not in gates: gates[name] = {} elif name not in custom_gates: custom_gate = Gate(name, len(gate["qubits"]), []) custom_gates[name] = custom_gate gates[name] = {} qubits = tuple(gate["qubits"]) gate_props = {} for param in gate["parameters"]: if param["name"] == "gate_error": gate_props["error"] = param["value"] if param["name"] == "gate_length": gate_props["duration"] = apply_prefix( param["value"], param["unit"]) gates[name][qubits] = InstructionProperties(**gate_props) for gate, props in gates.items(): if gate in name_mapping: inst = name_mapping.get(gate) else: inst = custom_gates[gate] target.add_instruction(inst, props) # Create measurement instructions: measure_props = {} count = 0 for qubit in props_dict["qubits"]: qubit_prop = {} for prop in qubit: if prop["name"] == "readout_length": qubit_prop["duration"] = apply_prefix( prop["value"], prop["unit"]) if prop["name"] == "readout_error": qubit_prop["error"] = prop["value"] measure_props[(count, )] = InstructionProperties(**qubit_prop) count += 1 target.add_instruction(Measure(), measure_props) # Parse from configuration because properties doesn't exist else: for gate in conf_dict["gates"]: name = gate["name"] gate_props = {tuple(x): None for x in gate["coupling_map"]} if name in name_mapping: target.add_instruction(name_mapping[name], gate_props) else: custom_gate = Gate(name, len(gate["coupling_map"][0]), []) target.add_instruction(custom_gate, gate_props) measure_props = {(n, ): None for n in range(conf_dict["n_qubits"])} target.add_instruction(Measure(), measure_props) # parse global configuration properties dt = conf_dict.get("dt") if dt: target.dt = dt * 1e-9 if "timing_constraints" in conf_dict: target.granularity = conf_dict["timing_constraints"].get("granularity") target.min_length = conf_dict["timing_constraints"].get("min_length") target.pulse_alignment = conf_dict["timing_constraints"].get( "pulse_alignment") target.aquire_alignment = conf_dict["timing_constraints"].get( "acquire_alignment") # If pulse defaults exists use that as the source of truth if defs_dict is not None: # TODO remove the usage of PulseDefaults as it will be deprecated in the future pulse_defs = PulseDefaults.from_dict(defs_dict) inst_map = pulse_defs.instruction_schedule_map for inst in inst_map.instructions: for qarg in inst_map.qubits_with_instruction(inst): sched = inst_map.get(inst, qarg) if inst in target: try: qarg = tuple(qarg) except TypeError: qarg = (qarg, ) if inst == "measure": for qubit in qarg: target[inst][(qubit, )].calibration = sched else: target[inst][qarg].calibration = sched target.add_instruction(Delay(Parameter("t")), {(bit, ): None for bit in range(target.num_qubits)}) return target
def qs_decomposition(mat, opt_a1=True, decomposer_1q=None, decomposer_2q=None): """ Decomposes unitary matrix into one and two qubit gates using Quantum Shannon Decomposition. ┌───┐ ┌───┐ ┌───┐ ┌───┐ ─┤ ├─ ───────┤ Rz├─────┤ Ry├─────┤ Rz├───── │ │ ≃ ┌───┐└─┬─┘┌───┐└─┬─┘┌───┐└─┬─┘┌───┐ /─┤ ├─ /─┤ ├──□──┤ ├──□──┤ ├──□──┤ ├ └───┘ └───┘ └───┘ └───┘ └───┘ The number of CX gates generated with the decomposition without optimizations is, .. math:: \frac{9}{16} 4^n - frac{3}{2} 2^n If opt_a1=True, the CX count is further reduced by, .. math:: \frac{1}{3} 4^{n - 2} - 1 This decomposition is described in arXiv:quant-ph/0406176. Arguments: mat (ndarray): unitary matrix to decompose opt_a1 (bool): whether to try optimization A.1 from Shende. This should eliminate 1 cnot per call. If True CZ gates are left in the output. If desired these can be further decomposed to CX. decomposer_1q (None or Object): optional 1Q decomposer. If None, uses :class:`~qiskit.quantum_info.synthesis.one_qubit_decomposer.OneQubitEulerDecomser` decomposer_2q (None or Object): optional 2Q decomposer. If None, uses :class:`~qiskit.quantum_info.synthesis.two_qubit_decomposer.TwoQubitBasisDecomposer` with CXGate. Return: QuantumCircuit: Decomposed quantum circuit. """ dim = mat.shape[0] nqubits = int(np.log2(dim)) if np.allclose(np.identity(dim), mat): return QuantumCircuit(nqubits) if dim == 2: if decomposer_1q is None: decomposer_1q = one_qubit_decompose.OneQubitEulerDecomposer() circ = decomposer_1q(mat) elif dim == 4: if decomposer_2q is None: decomposer_2q = two_qubit_decompose.TwoQubitBasisDecomposer(CXGate()) circ = decomposer_2q(mat) else: qr = QuantumRegister(nqubits) circ = QuantumCircuit(qr) dim_o2 = dim // 2 # perform cosine-sine decomposition (u1, u2), vtheta, (v1h, v2h) = scipy.linalg.cossin(mat, separate=True, p=dim_o2, q=dim_o2) # left circ left_circ = _demultiplex(v1h, v2h, opt_a1=opt_a1) circ.append(left_circ.to_instruction(), qr) # middle circ if opt_a1: nangles = len(vtheta) half_size = nangles // 2 # get UCG in terms of CZ circ_cz = _get_ucry_cz(nqubits, (2 * vtheta).tolist()) circ.append(circ_cz.to_instruction(), range(nqubits)) # merge final cz with right-side generic multiplexer u2[:, half_size:] = np.negative(u2[:, half_size:]) else: circ.ucry((2 * vtheta).tolist(), qr[:-1], qr[-1]) # right circ right_circ = _demultiplex(u1, u2, opt_a1=opt_a1) circ.append(right_circ.to_instruction(), qr) return circ
def level_3_pass_manager( pass_manager_config: PassManagerConfig) -> PassManager: """Level 3 pass manager: heavy optimization by noise adaptive qubit mapping and gate cancellation using commutativity rules and unitary synthesis. This pass manager applies the user-given initial layout. If none is given, a search for a perfect layout (i.e. one that satisfies all 2-qubit interactions) is conducted. If no such layout is found, and device calibration information is available, the circuit is mapped to the qubits with best readouts and to CX gates with highest fidelity. The pass manager then transforms the circuit to match the coupling constraints. It is then unrolled to the basis, and any flipped cx directions are fixed. Finally, optimizations in the form of commutative gate cancellation, resynthesis of two-qubit unitary blocks, and redundant reset removal are performed. Note: In simulators where ``coupling_map=None``, only the unrolling and optimization stages are done. Args: pass_manager_config: configuration of the pass manager. Returns: a level 3 pass manager. Raises: TranspilerError: if the passmanager config is invalid. """ basis_gates = pass_manager_config.basis_gates coupling_map = pass_manager_config.coupling_map initial_layout = pass_manager_config.initial_layout layout_method = pass_manager_config.layout_method or 'dense' routing_method = pass_manager_config.routing_method or 'stochastic' translation_method = pass_manager_config.translation_method or 'translator' seed_transpiler = pass_manager_config.seed_transpiler backend_properties = pass_manager_config.backend_properties # 1. Unroll to 1q or 2q gates _unroll3q = Unroll3qOrMore() # 2. Layout on good qubits if calibration info available, otherwise on dense links _given_layout = SetLayout(initial_layout) def _choose_layout_condition(property_set): return not property_set['layout'] _choose_layout_1 = CSPLayout(coupling_map, call_limit=10000, time_limit=60) if layout_method == 'trivial': _choose_layout_2 = TrivialLayout(coupling_map) elif layout_method == 'dense': _choose_layout_2 = DenseLayout(coupling_map, backend_properties) elif layout_method == 'noise_adaptive': _choose_layout_2 = NoiseAdaptiveLayout(backend_properties) elif layout_method == 'sabre': _choose_layout_2 = SabreLayout(coupling_map, max_iterations=4, seed=seed_transpiler) else: raise TranspilerError("Invalid layout method %s." % layout_method) # 3. Extend dag/layout with ancillas using the full coupling map _embed = [ FullAncillaAllocation(coupling_map), EnlargeWithAncilla(), ApplyLayout() ] # 4. Swap to fit the coupling map _swap_check = CheckMap(coupling_map) def _swap_condition(property_set): return not property_set['is_swap_mapped'] _swap = [BarrierBeforeFinalMeasurements()] if routing_method == 'basic': _swap += [BasicSwap(coupling_map)] elif routing_method == 'stochastic': _swap += [ StochasticSwap(coupling_map, trials=200, seed=seed_transpiler) ] elif routing_method == 'lookahead': _swap += [LookaheadSwap(coupling_map, search_depth=5, search_width=6)] elif routing_method == 'sabre': _swap += [ SabreSwap(coupling_map, heuristic='decay', seed=seed_transpiler) ] else: raise TranspilerError("Invalid routing method %s." % routing_method) # 5. Unroll to the basis if translation_method == 'unroller': _unroll = [Unroller(basis_gates)] elif translation_method == 'translator': from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel _unroll = [ UnrollCustomDefinitions(sel, basis_gates), BasisTranslator(sel, basis_gates) ] else: raise TranspilerError("Invalid translation method %s." % translation_method) # 6. Fix any CX direction mismatch _direction_check = [CheckCXDirection(coupling_map)] def _direction_condition(property_set): return not property_set['is_direction_mapped'] _direction = [CXDirection(coupling_map)] # 8. Optimize iteratively until no more change in depth. Removes useless gates # after reset and before measure, commutes gates and optimizes continguous blocks. _depth_check = [Depth(), FixedPoint('depth')] def _opt_control(property_set): return not property_set['depth_fixed_point'] _reset = [RemoveResetInZeroState()] _meas = [OptimizeSwapBeforeMeasure(), RemoveDiagonalGatesBeforeMeasure()] # Choose the first available 2q gate to use in the KAK decomposition. from qiskit.circuit.library.standard_gates import iSwapGate, CXGate, CZGate, RXXGate kak_gate_names = { 'iswap': iSwapGate(), 'cx': CXGate(), 'cz': CZGate(), 'rxx': RXXGate(math.pi / 2) } kak_gate = None kak_gates = set(basis_gates or []).intersection(kak_gate_names.keys()) if kak_gates: kak_gate = kak_gate_names[kak_gates.pop()] _opt = [ Collect2qBlocks(), ConsolidateBlocks(kak_basis_gate=kak_gate), Optimize1qGates(basis_gates), CommutativeCancellation() ] # Build pass manager pm3 = PassManager() pm3.append(_unroll3q) if coupling_map: pm3.append(_given_layout) pm3.append(_choose_layout_1, condition=_choose_layout_condition) pm3.append(_choose_layout_2, condition=_choose_layout_condition) pm3.append(_embed) pm3.append(_reset + _meas) pm3.append(_swap_check) pm3.append(_swap, condition=_swap_condition) pm3.append(_depth_check + _opt + _unroll, do_while=_opt_control) if coupling_map and not coupling_map.is_symmetric: pm3.append(_direction_check) pm3.append(_direction, condition=_direction_condition) pm3.append(_reset) return pm3
def _find_decomposer_2q_from_target(self, target, qubits, pulse_optimize): qubits_tuple = tuple(qubits) reverse_tuple = (qubits[1], qubits[0]) if qubits_tuple in self._decomposer_cache: return self._decomposer_cache[qubits_tuple] matching = {} reverse = {} kak_gates = _find_matching_kak_gates(target) euler_basis_gates = _find_matching_euler_bases(target) decomposers_2q = [] # find all decomposers for kak_gate, euler_basis in product(kak_gates, euler_basis_gates): gate_name = None if isinstance(kak_gate, tuple): gate_name = kak_gate[1] kak_gate = kak_gate[0] if isinstance(kak_gate, RZXGate): backup_optimizer = TwoQubitBasisDecomposer( CXGate(), euler_basis=euler_basis, pulse_optimize=pulse_optimize) decomposer = XXDecomposer(euler_basis=euler_basis, backup_optimizer=backup_optimizer) if gate_name is not None: decomposer.gate_name = gate_name decomposers_2q.append(decomposer) elif kak_gate is not None: decomposer = TwoQubitBasisDecomposer( kak_gate, euler_basis=euler_basis, pulse_optimize=pulse_optimize) if gate_name is not None: decomposer.gate_name = gate_name decomposers_2q.append(decomposer) # Find lowest error matching or reverse decomposer and use that for index, decomposer in enumerate(decomposers_2q): gate_name = getattr(decomposer, "gate_name", decomposer.gate.name) props_dict = target[gate_name] if target.instruction_supported(gate_name, qubits_tuple): if props_dict is None or None in props_dict: error = 0.0 else: error = getattr(props_dict[qubits_tuple], "error", 0.0) if error is None: error = 0.0 matching[index] = error # Skip reverse check if we already have matching elif not matching and target.instruction_supported( gate_name, reverse_tuple): if props_dict is None or None in props_dict: error = 0.0 else: error = getattr(props_dict[reverse_tuple], "error", 0.0) if error is None: error = 0.0 reverse[index] = error preferred_direction = None if matching: preferred_direction = [0, 1] min_error_index = min(matching, key=matching.get) decomposer2q = decomposers_2q[min_error_index] elif reverse: preferred_direction = [1, 0] min_error_index = min(reverse, key=reverse.get) decomposer2q = decomposers_2q[min_error_index] # If no matching or reverse direction is found just pick one, if natural direction is # enforced it will fail later else: decomposer2q = decomposers_2q[0] self._decomposer_cache[qubits_tuple] = (decomposer2q, preferred_direction) return (decomposer2q, preferred_direction)
def _gate_gradient_dict( gate: Gate) -> List[Tuple[List[complex], List[Instruction]]]: r"""Given a parameterized gate U(theta) with derivative dU(theta)/dtheta = sum_ia_iU(theta)V_i. This function returns a:=[a_0, ...] and V=[V_0, ...] Suppose U takes multiple parameters, i.e., U(theta^0, ... theta^k). The returned coefficients and gates are ordered accordingly. Only parameterized Qiskit gates are supported. Args: gate: The gate for which the derivative is being computed. Returns: The coefficients and the gates used for the metric computation for each parameter of the respective gates. [([a^0], [V^0]) ..., ([a^k], [V^k])] Raises: AquaError: If the input gate is controlled by another state but '|1>^{\otimes k}' TypeError: If the input gate is not a supported parametrized gate. """ # pylint: disable=too-many-return-statements if isinstance(gate, PhaseGate): # theta return [([0.5j, -0.5j], [IGate(), CZGate()])] if isinstance(gate, UGate): # theta, lambda, phi return [([-0.5j], [CZGate()]), ([-0.5j], [CZGate()]), ([-0.5j], [CZGate()])] if isinstance(gate, RXGate): # theta return [([-0.5j], [CXGate()])] if isinstance(gate, RYGate): # theta return [([-0.5j], [CYGate()])] if isinstance(gate, RZGate): # theta return [([-0.5j], [CZGate()])] if isinstance(gate, RXXGate): # theta cxx_circ = QuantumCircuit(3) cxx_circ.cx(0, 1) cxx_circ.cx(0, 2) cxx = cxx_circ.to_instruction() return [([-0.5j], [cxx])] if isinstance(gate, RYYGate): # theta cyy_circ = QuantumCircuit(3) cyy_circ.cy(0, 1) cyy_circ.cy(0, 2) cyy = cyy_circ.to_instruction() return [([-0.5j], [cyy])] if isinstance(gate, RZZGate): # theta czz_circ = QuantumCircuit(3) czz_circ.cz(0, 1) czz_circ.cz(0, 2) czz = czz_circ.to_instruction() return [([-0.5j], [czz])] if isinstance(gate, RZXGate): # theta czx_circ = QuantumCircuit(3) czx_circ.cx(0, 2) czx_circ.cz(0, 1) czx = czx_circ.to_instruction() return [([-0.5j], [czx])] if isinstance(gate, ControlledGate): # TODO support arbitrary control states if gate.ctrl_state != 2**gate.num_ctrl_qubits - 1: raise AquaError( 'Function only support controlled gates with control state `1` on all control ' 'qubits.') base_coeffs_gates = LinComb._gate_gradient_dict(gate.base_gate) coeffs_gates = [] # The projectors needed for the gradient of a controlled gate are integrated by a sum # of gates. # The following line generates the decomposition gates. proj_gates_controlled = [[ (-1)**p.count(ZGate()), p ] for p in product([IGate(), ZGate()], repeat=gate.num_ctrl_qubits) ] for base_coeffs, base_gates in base_coeffs_gates: # loop over parameters coeffs = [] gates = [] for phase, proj_gates in proj_gates_controlled: coeffs.extend([ phase * c / (2**gate.num_ctrl_qubits) for c in base_coeffs ]) for base_gate in base_gates: controlled_circ = QuantumCircuit(gate.num_ctrl_qubits + gate.num_qubits) for i, proj_gate in enumerate(proj_gates): if isinstance(proj_gate, ZGate): controlled_circ.cz(0, i + 1) if not isinstance(base_gate, IGate): controlled_circ.append(base_gate, [ 0, range(gate.num_ctrl_qubits + 1, gate.num_ctrl_qubits + gate.num_qubits) ]) gates.append(controlled_circ.to_instruction()) c_g = (coeffs, gates) coeffs_gates.append(c_g) return coeffs_gates raise TypeError('Unrecognized parametrized gate, {}'.format(gate))
def __init__(self): super().__init__( name="FakeMumbaiV2", description="A fake BackendV2 example based on IBM Mumbai", online_date=datetime.datetime.utcnow(), backend_version="0.0.1", ) dt = 0.2222222222222222e-9 self._target = Target(dt=dt) self._phi = Parameter("phi") rz_props = { (0, ): InstructionProperties(duration=0.0, error=0), (1, ): InstructionProperties(duration=0.0, error=0), (2, ): InstructionProperties(duration=0.0, error=0), (3, ): InstructionProperties(duration=0.0, error=0), (4, ): InstructionProperties(duration=0.0, error=0), (5, ): InstructionProperties(duration=0.0, error=0), (6, ): InstructionProperties(duration=0.0, error=0), (7, ): InstructionProperties(duration=0.0, error=0), (8, ): InstructionProperties(duration=0.0, error=0), (9, ): InstructionProperties(duration=0.0, error=0), (10, ): InstructionProperties(duration=0.0, error=0), (11, ): InstructionProperties(duration=0.0, error=0), (12, ): InstructionProperties(duration=0.0, error=0), (13, ): InstructionProperties(duration=0.0, error=0), (14, ): InstructionProperties(duration=0.0, error=0), (15, ): InstructionProperties(duration=0.0, error=0), (16, ): InstructionProperties(duration=0.0, error=0), (17, ): InstructionProperties(duration=0.0, error=0), (18, ): InstructionProperties(duration=0.0, error=0), (19, ): InstructionProperties(duration=0.0, error=0), (20, ): InstructionProperties(duration=0.0, error=0), (21, ): InstructionProperties(duration=0.0, error=0), (22, ): InstructionProperties(duration=0.0, error=0), (23, ): InstructionProperties(duration=0.0, error=0), (24, ): InstructionProperties(duration=0.0, error=0), (25, ): InstructionProperties(duration=0.0, error=0), (26, ): InstructionProperties(duration=0.0, error=0), } self._target.add_instruction(RZGate(self._phi), rz_props) x_props = { (0, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00020056469709026198), (1, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0004387432040599484), (2, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002196765027963209), (3, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0003065541555566093), (4, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002402026686478811), (5, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002162777062721698), (6, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00021981280474256117), (7, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00018585647396926756), (8, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00027053333211825124), (9, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002603116226593832), (10, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00023827406030798066), (11, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00024856063217108685), (12, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002065075637361354), (13, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00024898181450337464), (14, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00017758796319636606), (15, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00016530893922883836), (16, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0003213658218204255), (17, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00024068450432012685), (18, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00026676441863976344), (19, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00017090891698571018), (20, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00021057196071004095), (21, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00030445404779882887), (22, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00019322295843406375), (23, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00030966037392287727), (24, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00023570754161126), (25, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00018367783963229033), (26, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00019630609928571516), } self._target.add_instruction(XGate(), x_props) sx_props = { (0, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00020056469709026198), (1, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0004387432040599484), (2, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002196765027963209), (3, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0003065541555566093), (4, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002402026686478811), (5, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002162777062721698), (6, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00021981280474256117), (7, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00018585647396926756), (8, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00027053333211825124), (9, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002603116226593832), (10, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00023827406030798066), (11, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00024856063217108685), (12, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0002065075637361354), (13, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00024898181450337464), (14, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00017758796319636606), (15, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00016530893922883836), (16, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.0003213658218204255), (17, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00024068450432012685), (18, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00026676441863976344), (19, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00017090891698571018), (20, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00021057196071004095), (21, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00030445404779882887), (22, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00019322295843406375), (23, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00030966037392287727), (24, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00023570754161126), (25, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00018367783963229033), (26, ): InstructionProperties(duration=3.5555555555555554e-08, error=0.00019630609928571516), } self._target.add_instruction(SXGate(), sx_props) chunk_size = 16 cx_props = { (0, 1): InstructionProperties(duration=101 * chunk_size * dt, error=0.030671121181161276), (4, 1): InstructionProperties(duration=70 * chunk_size * dt, error=0.014041986073052737), (4, 7): InstructionProperties(duration=74 * chunk_size * dt, error=0.0052040275323747), (10, 7): InstructionProperties(duration=92 * chunk_size * dt, error=0.005625282141655502), (10, 12): InstructionProperties(duration=84 * chunk_size * dt, error=0.005771827440726435), (15, 12): InstructionProperties(duration=84 * chunk_size * dt, error=0.0050335609425562755), (15, 18): InstructionProperties(duration=64 * chunk_size * dt, error=0.0051374141171115495), (12, 13): InstructionProperties(duration=70 * chunk_size * dt, error=0.011361175954064051), (13, 14): InstructionProperties(duration=101 * chunk_size * dt, error=0.005231334872256355), # From FakeMumbai: (1, 0): InstructionProperties(duration=4.551111111111111e-07, error=0.030671121181161276), (1, 2): InstructionProperties(duration=7.395555555555556e-07, error=0.03420291964205785), (1, 4): InstructionProperties(duration=3.6266666666666663e-07, error=0.014041986073052737), (2, 1): InstructionProperties(duration=7.04e-07, error=0.03420291964205785), (2, 3): InstructionProperties(duration=4.266666666666666e-07, error=0.005618162036535312), (3, 2): InstructionProperties(duration=3.911111111111111e-07, error=0.005618162036535312), (3, 5): InstructionProperties(duration=3.5555555555555553e-07, error=0.006954580732294352), (5, 3): InstructionProperties(duration=3.911111111111111e-07, error=0.006954580732294352), (5, 8): InstructionProperties(duration=1.3155555555555553e-06, error=0.021905829471073668), (6, 7): InstructionProperties(duration=2.4177777777777775e-07, error=0.011018069718028878), (7, 4): InstructionProperties(duration=3.7688888888888884e-07, error=0.0052040275323747), (7, 6): InstructionProperties(duration=2.7733333333333333e-07, error=0.011018069718028878), (7, 10): InstructionProperties(duration=4.337777777777778e-07, error=0.005625282141655502), (8, 5): InstructionProperties(duration=1.351111111111111e-06, error=0.021905829471073668), (8, 9): InstructionProperties(duration=6.897777777777777e-07, error=0.011889378687341773), (8, 11): InstructionProperties(duration=5.902222222222222e-07, error=0.009523844852027258), (9, 8): InstructionProperties(duration=6.542222222222222e-07, error=0.011889378687341773), (11, 8): InstructionProperties(duration=6.257777777777777e-07, error=0.009523844852027258), (11, 14): InstructionProperties(duration=4.053333333333333e-07, error=0.004685421425282804), (12, 10): InstructionProperties(duration=3.9822222222222215e-07, error=0.005771827440726435), (12, 15): InstructionProperties(duration=4.053333333333333e-07, error=0.0050335609425562755), (13, 12): InstructionProperties(duration=5.831111111111111e-07, error=0.011361175954064051), (14, 11): InstructionProperties(duration=3.697777777777778e-07, error=0.004685421425282804), (14, 13): InstructionProperties(duration=3.5555555555555553e-07, error=0.005231334872256355), (14, 16): InstructionProperties(duration=3.484444444444444e-07, error=0.0051117141032224755), (16, 14): InstructionProperties(duration=3.1288888888888885e-07, error=0.0051117141032224755), (16, 19): InstructionProperties(duration=7.537777777777777e-07, error=0.013736796355458464), (17, 18): InstructionProperties(duration=2.488888888888889e-07, error=0.007267536233537236), (18, 15): InstructionProperties(duration=3.413333333333333e-07, error=0.0051374141171115495), (18, 17): InstructionProperties(duration=2.8444444444444443e-07, error=0.007267536233537236), (18, 21): InstructionProperties(duration=4.977777777777778e-07, error=0.007718304749257138), (19, 16): InstructionProperties(duration=7.182222222222222e-07, error=0.013736796355458464), (19, 20): InstructionProperties(duration=4.266666666666666e-07, error=0.005757038521092134), (19, 22): InstructionProperties(duration=3.6266666666666663e-07, error=0.004661878013991871), (20, 19): InstructionProperties(duration=3.911111111111111e-07, error=0.005757038521092134), (21, 18): InstructionProperties(duration=5.333333333333332e-07, error=0.007718304749257138), (21, 23): InstructionProperties(duration=3.911111111111111e-07, error=0.007542515578725928), (22, 19): InstructionProperties(duration=3.271111111111111e-07, error=0.004661878013991871), (22, 25): InstructionProperties(duration=4.835555555555555e-07, error=0.005536735115231589), (23, 21): InstructionProperties(duration=4.266666666666666e-07, error=0.007542515578725928), (23, 24): InstructionProperties(duration=6.613333333333332e-07, error=0.010797784688907186), (24, 23): InstructionProperties(duration=6.257777777777777e-07, error=0.010797784688907186), (24, 25): InstructionProperties(duration=4.337777777777778e-07, error=0.006127506135155392), (25, 22): InstructionProperties(duration=4.48e-07, error=0.005536735115231589), (25, 24): InstructionProperties(duration=4.693333333333333e-07, error=0.006127506135155392), (25, 26): InstructionProperties(duration=3.484444444444444e-07, error=0.0048451525929122385), (26, 25): InstructionProperties(duration=3.1288888888888885e-07, error=0.0048451525929122385), } self.target.add_instruction(CXGate(), cx_props) # Error and duration the same as CX rzx_90_props = { (0, 1): InstructionProperties(duration=101 * chunk_size * dt, error=0.030671121181161276), (4, 1): InstructionProperties(duration=70 * chunk_size * dt, error=0.014041986073052737), (4, 7): InstructionProperties(duration=74 * chunk_size * dt, error=0.0052040275323747), (10, 7): InstructionProperties(duration=92 * chunk_size * dt, error=0.005625282141655502), (10, 12): InstructionProperties(duration=84 * chunk_size * dt, error=0.005771827440726435), (15, 12): InstructionProperties(duration=84 * chunk_size * dt, error=0.0050335609425562755), (15, 18): InstructionProperties(duration=64 * chunk_size * dt, error=0.0051374141171115495), (12, 13): InstructionProperties(duration=70 * chunk_size * dt, error=0.011361175954064051), (13, 14): InstructionProperties(duration=101 * chunk_size * dt, error=0.005231334872256355), } self.target.add_instruction(RZXGate(np.pi / 2), rzx_90_props, name="rzx_90") rzx_45_props = { (0, 1): InstructionProperties(duration=52 * chunk_size * dt, error=0.030671121181161276 / 2), (4, 1): InstructionProperties(duration=37 * chunk_size * dt, error=0.014041986073052737 / 2), (4, 7): InstructionProperties(duration=40 * chunk_size * dt, error=0.0052040275323747 / 2), (10, 7): InstructionProperties(duration=46 * chunk_size * dt, error=0.005625282141655502 / 2), (10, 12): InstructionProperties(duration=45 * chunk_size * dt, error=0.005771827440726435 / 2), (15, 12): InstructionProperties(duration=42 * chunk_size * dt, error=0.0050335609425562755 / 2), (15, 18): InstructionProperties(duration=34 * chunk_size * dt, error=0.0051374141171115495 / 2), (12, 13): InstructionProperties(duration=37 * chunk_size * dt, error=0.011361175954064051 / 2), (13, 14): InstructionProperties(duration=52 * chunk_size * dt, error=0.005231334872256355 / 2), } self.target.add_instruction(RZXGate(np.pi / 4), rzx_45_props, name="rzx_45") rzx_30_props = { (0, 1): InstructionProperties(duration=37 * chunk_size * dt, error=0.030671121181161276 / 3), (4, 1): InstructionProperties(duration=24 * chunk_size * dt, error=0.014041986073052737 / 3), (4, 7): InstructionProperties(duration=29 * chunk_size * dt, error=0.0052040275323747 / 3), (10, 7): InstructionProperties(duration=32 * chunk_size * dt, error=0.005625282141655502 / 3), (10, 12): InstructionProperties(duration=32 * chunk_size * dt, error=0.005771827440726435 / 3), (15, 12): InstructionProperties(duration=29 * chunk_size * dt, error=0.0050335609425562755 / 3), (15, 18): InstructionProperties(duration=26 * chunk_size * dt, error=0.0051374141171115495 / 3), (12, 13): InstructionProperties(duration=24 * chunk_size * dt, error=0.011361175954064051 / 3), (13, 14): InstructionProperties(duration=377 * chunk_size * dt, error=0.005231334872256355 / 3), } self.target.add_instruction(RZXGate(np.pi / 6), rzx_30_props, name="rzx_30") reset_props = {(i, ): InstructionProperties(duration=3676.4444444444443) for i in range(27)} self._target.add_instruction(Reset(), reset_props) meas_props = { (0, ): InstructionProperties(duration=3.552e-06, error=0.02089999999999992), (1, ): InstructionProperties(duration=3.552e-06, error=0.020199999999999996), (2, ): InstructionProperties(duration=3.552e-06, error=0.014100000000000001), (3, ): InstructionProperties(duration=3.552e-06, error=0.03710000000000002), (4, ): InstructionProperties(duration=3.552e-06, error=0.015100000000000002), (5, ): InstructionProperties(duration=3.552e-06, error=0.01869999999999994), (6, ): InstructionProperties(duration=3.552e-06, error=0.013000000000000012), (7, ): InstructionProperties(duration=3.552e-06, error=0.02059999999999995), (8, ): InstructionProperties(duration=3.552e-06, error=0.06099999999999994), (9, ): InstructionProperties(duration=3.552e-06, error=0.02950000000000008), (10, ): InstructionProperties(duration=3.552e-06, error=0.040000000000000036), (11, ): InstructionProperties(duration=3.552e-06, error=0.017299999999999982), (12, ): InstructionProperties(duration=3.552e-06, error=0.04410000000000003), (13, ): InstructionProperties(duration=3.552e-06, error=0.017199999999999993), (14, ): InstructionProperties(duration=3.552e-06, error=0.10119999999999996), (15, ): InstructionProperties(duration=3.552e-06, error=0.07840000000000003), (16, ): InstructionProperties(duration=3.552e-06, error=0.014499999999999957), (17, ): InstructionProperties(duration=3.552e-06, error=0.021299999999999986), (18, ): InstructionProperties(duration=3.552e-06, error=0.022399999999999975), (19, ): InstructionProperties(duration=3.552e-06, error=0.01859999999999995), (20, ): InstructionProperties(duration=3.552e-06, error=0.02859999999999996), (21, ): InstructionProperties(duration=3.552e-06, error=0.021600000000000064), (22, ): InstructionProperties(duration=3.552e-06, error=0.030200000000000005), (23, ): InstructionProperties(duration=3.552e-06, error=0.01970000000000005), (24, ): InstructionProperties(duration=3.552e-06, error=0.03079999999999994), (25, ): InstructionProperties(duration=3.552e-06, error=0.04400000000000004), (26, ): InstructionProperties(duration=3.552e-06, error=0.026800000000000046), } self.target.add_instruction(Measure(), meas_props) self._qubit_properties = { 0: QubitProperties(t1=0.00015987993124584417, t2=0.00016123516590787283, frequency=5073462814.921423), 1: QubitProperties(t1=0.00017271188343294773, t2=3.653713654834547e-05, frequency=4943844681.620448), 2: QubitProperties(t1=7.179635917914033e-05, t2=0.00012399765778639733, frequency=4668157502.363186), 3: QubitProperties(t1=0.0001124203171256432, t2=0.0001879954854434302, frequency=4887315883.214115), 4: QubitProperties(t1=9.568769051084652e-05, t2=6.9955557231525e-05, frequency=5016355075.77537), 5: QubitProperties(t1=9.361326963775646e-05, t2=0.00012561361411231962, frequency=4950539585.866738), 6: QubitProperties(t1=9.735672898365994e-05, t2=0.00012522003396944046, frequency=4970622491.726983), 7: QubitProperties(t1=0.00012117839009784141, t2=0.0001492370106539427, frequency=4889863864.167805), 8: QubitProperties(t1=8.394707006435891e-05, t2=5.5194256398727296e-05, frequency=4769852625.405966), 9: QubitProperties(t1=0.00012392229685657686, t2=5.97129502818714e-05, frequency=4948868138.885028), 10: QubitProperties(t1=0.00011193014813922708, t2=0.00014091085124119432, frequency=4966294754.357908), 11: QubitProperties(t1=0.000124426408667364, t2=9.561432905002298e-05, frequency=4664636564.282378), 12: QubitProperties(t1=0.00012469120424014884, t2=7.1792446286313e-05, frequency=4741461907.952719), 13: QubitProperties(t1=0.00010010942474357871, t2=9.260751861141544e-05, frequency=4879064835.799635), 14: QubitProperties(t1=0.00010793367069728063, t2=0.00020462601085738193, frequency=4774809501.962878), 15: QubitProperties(t1=0.00010814279470918582, t2=0.00014052616328020083, frequency=4860834948.367331), 16: QubitProperties(t1=9.889617874757627e-05, t2=0.00012160357011388956, frequency=4978318747.333388), 17: QubitProperties(t1=8.435212562619916e-05, t2=4.43587633824445e-05, frequency=5000300619.491221), 18: QubitProperties(t1=0.00011719166507869474, t2=5.461866556148401e-05, frequency=4772460318.985625), 19: QubitProperties(t1=0.00013321880066203932, t2=0.0001704632622810825, frequency=4807707035.998121), 20: QubitProperties(t1=9.14192211953385e-05, t2=0.00014298332288799443, frequency=5045028334.669125), 21: QubitProperties(t1=5.548103716494676e-05, t2=9.328101902519704e-05, frequency=4941029753.792485), 22: QubitProperties(t1=0.00017109481586484562, t2=0.00019209594920551097, frequency=4906801587.246266), 23: QubitProperties(t1=0.00010975552427765991, t2=0.00015616813868639905, frequency=4891601685.652732), 24: QubitProperties(t1=0.0001612962696960434, t2=6.940808472789023e-05, frequency=4664347869.784967), 25: QubitProperties(t1=0.00015414506978323392, t2=8.382170181880107e-05, frequency=4742061753.511209), 26: QubitProperties(t1=0.00011828557676958944, t2=0.00016963640893557827, frequency=4961661099.733828), }
def convert_to_target( configuration: BackendConfiguration, properties: BackendProperties = None, defaults: PulseDefaults = None, ) -> Target: """Uses configuration, properties and pulse defaults to construct and return Target class. """ name_mapping = { "id": IGate(), "sx": SXGate(), "x": XGate(), "cx": CXGate(), "rz": RZGate(Parameter("λ")), "reset": Reset(), } custom_gates = {} target = None # Parse from properties if it exsits if properties is not None: qubit_properties = qubit_props_list_from_props(properties=properties) target = Target( num_qubits=configuration.n_qubits, qubit_properties=qubit_properties ) # Parse instructions gates: Dict[str, Any] = {} for gate in properties.gates: name = gate.gate if name in name_mapping: if name not in gates: gates[name] = {} elif name not in custom_gates: custom_gate = Gate(name, len(gate.qubits), []) custom_gates[name] = custom_gate gates[name] = {} qubits = tuple(gate.qubits) gate_props = {} for param in gate.parameters: if param.name == "gate_error": gate_props["error"] = param.value if param.name == "gate_length": gate_props["duration"] = apply_prefix(param.value, param.unit) gates[name][qubits] = InstructionProperties(**gate_props) for gate, props in gates.items(): if gate in name_mapping: inst = name_mapping.get(gate) else: inst = custom_gates[gate] target.add_instruction(inst, props) # Create measurement instructions: measure_props = {} for qubit, _ in enumerate(properties.qubits): measure_props[(qubit,)] = InstructionProperties( duration=properties.readout_length(qubit), error=properties.readout_error(qubit), ) target.add_instruction(Measure(), measure_props) # Parse from configuration because properties doesn't exist else: target = Target(num_qubits=configuration.n_qubits) for gate in configuration.gates: name = gate.name gate_props = ( {tuple(x): None for x in gate.coupling_map} # type: ignore[misc] if hasattr(gate, "coupling_map") else {None: None} ) gate_len = len(gate.coupling_map[0]) if hasattr(gate, "coupling_map") else 0 if name in name_mapping: target.add_instruction(name_mapping[name], gate_props) else: custom_gate = Gate(name, gate_len, []) target.add_instruction(custom_gate, gate_props) target.add_instruction(Measure()) # parse global configuration properties if hasattr(configuration, "dt"): target.dt = configuration.dt if hasattr(configuration, "timing_constraints"): target.granularity = configuration.timing_constraints.get("granularity") target.min_length = configuration.timing_constraints.get("min_length") target.pulse_alignment = configuration.timing_constraints.get("pulse_alignment") target.aquire_alignment = configuration.timing_constraints.get( "acquire_alignment" ) # If a pulse defaults exists use that as the source of truth if defaults is not None: inst_map = defaults.instruction_schedule_map for inst in inst_map.instructions: for qarg in inst_map.qubits_with_instruction(inst): sched = inst_map.get(inst, qarg) if inst in target: try: qarg = tuple(qarg) except TypeError: qarg = (qarg,) if inst == "measure": for qubit in qarg: target[inst][(qubit,)].calibration = sched else: target[inst][qarg].calibration = sched if "delay" not in target: target.add_instruction( Delay(Parameter("t")), {(bit,): None for bit in range(target.num_qubits)} ) return target
return_circuit.append(self.gate, [q[0], q[1]]) return_circuit.compose(decomposition_euler[2 * best_nbasis], [q[0]], inplace=True) return_circuit.compose(decomposition_euler[2 * best_nbasis + 1], [q[1]], inplace=True) return return_circuit def num_basis_gates(self, unitary): """Computes the number of basis gates needed in a decomposition of input unitary """ unitary = np.asarray(unitary, dtype=complex) a, b, c = weyl_coordinates(unitary)[:] traces = [ 4 * ( math.cos(a) * math.cos(b) * math.cos(c) + 1j * math.sin(a) * math.sin(b) * math.sin(c) ), 4 * ( math.cos(np.pi / 4 - a) * math.cos(self.basis.b - b) * math.cos(c) + 1j * math.sin(np.pi / 4 - a) * math.sin(self.basis.b - b) * math.sin(c) ), 4 * math.cos(c), 4, ] return np.argmax([trace_to_fid(traces[i]) * self.basis_fidelity ** i for i in range(4)]) two_qubit_cnot_decompose = TwoQubitBasisDecomposer(CXGate())
equiv_u2.append(HGate(),[q[0]], [] ) equiv_u2.append(RZGate(pi/2),[q[0]], []) equiv_u2.append(HGate(), [q[0]], []) equiv_u2.append(RZGate(phi-(pi/2)),[q[0]], 0) eq_lib.add_equivalence(u2, equiv_u2) q = QuantumRegister(1, 'q') equiv_u1 = QuantumCircuit(q) equiv_u1.append(RZGate(theta), [q[0]], []) eq_lib.add_equivalence(u1, equiv_u1) q = QuantumRegister(3, 'q') equiv_ccx = QuantumCircuit(q) for inst, qargs, cargs in [ (HGate(), [q[2]], []), (CXGate(), [q[1], q[2]],[]), (TdgGate(), [q[2]], []), (CXGate(), [q[0],q[2]], []), (TGate(), [q[2]], []), (CXGate(), [q[1],q[2]], []), (TdgGate(), [q[2]], []), (CXGate(), [q[0],q[2]], []), (CXGate(), [q[0],q[1]], []), (TdgGate(), [q[1]], []), (CXGate(), [q[0],q[1]], []), (TGate(), [q[0]], []), (TGate(), [q[1]], []), (TGate(), [q[2]], []), (HGate(), [q[2]], []) ]: