def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) if optimisation_level == 0: return SequencePass([ DecomposeBoxes(), FlattenRegisters(), RenameQubitsPass(self._qm), ionq_pass, ]) elif optimisation_level == 1: return SequencePass([ DecomposeBoxes(), SynthesiseIBM(), FlattenRegisters(), RenameQubitsPass(self._qm), ionq_pass, ]) else: return SequencePass([ DecomposeBoxes(), FullPeepholeOptimise(), FlattenRegisters(), RenameQubitsPass(self._qm), ionq_pass, SquashCustom( ionq_singleqs, lambda a, b, c: Circuit(1).Rz(c, 0).Rx(b, 0).Rz(a, 0), ), ])
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) if optimisation_level == 0: return SequencePass([ FlattenRegisters(), RenameQubitsPass(self._qm), DecomposeBoxes(), _aqt_rebase(), ]) elif optimisation_level == 1: return SequencePass([ DecomposeBoxes(), SynthesiseIBM(), FlattenRegisters(), RenameQubitsPass(self._qm), _aqt_rebase(), RemoveRedundancies(), EulerAngleReduction(OpType.Ry, OpType.Rx), ]) else: return SequencePass([ DecomposeBoxes(), FullPeepholeOptimise(), FlattenRegisters(), RenameQubitsPass(self._qm), _aqt_rebase(), RemoveRedundancies(), EulerAngleReduction(OpType.Ry, OpType.Rx), ])
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) if optimisation_level == 0: return SequencePass( [DecomposeClassicalExp(), DecomposeBoxes(), RebaseHQS()]) elif optimisation_level == 1: return SequencePass([ DecomposeClassicalExp(), DecomposeBoxes(), SynthesiseIBM(), RebaseHQS(), RemoveRedundancies(), SquashHQS(), ]) else: return SequencePass([ DecomposeClassicalExp(), DecomposeBoxes(), FullPeepholeOptimise(), RebaseHQS(), RemoveRedundancies(), SquashHQS(), ])
def test_conditions() -> None: box_c = Circuit(2, 2) box_c.Z(0) box_c.Y(1, condition_bits=[0, 1], condition_value=1) box_c.Measure(0, 0, condition_bits=[0, 1], condition_value=0) box = CircBox(box_c) u = np.asarray([[0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1], [1, 0, 0, 0]]) ubox = Unitary2qBox(u) c = Circuit(2, 2, name="c") b = c.add_c_register("b", 1) c.add_circbox( box, [Qubit(0), Qubit(1), Bit(0), Bit(1)], condition_bits=[b[0]], condition_value=1, ) c.add_unitary2qbox(ubox, Qubit(0), Qubit(1), condition_bits=[b[0]], condition_value=0) c2 = c.copy() qc = tk_to_qiskit(c) c1 = qiskit_to_tk(qc) assert len(c1.get_commands()) == 2 DecomposeBoxes().apply(c) DecomposeBoxes().apply(c1) assert c == c1 c2.Z(1, condition=reg_eq(b, 1)) qc = tk_to_qiskit(c2) c1 = qiskit_to_tk(qc) assert len(c1.get_commands()) == 3
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) if optimisation_level == 0: return SequencePass([DecomposeBoxes(), RebaseIBM()]) elif optimisation_level == 1: return SequencePass([DecomposeBoxes(), SynthesiseIBM()]) else: return SequencePass([DecomposeBoxes(), FullPeepholeOptimise()])
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) passes = [DecomposeBoxes()] if optimisation_level == 1: passes.append(SynthesiseIBM()) elif optimisation_level == 2: passes.append(FullPeepholeOptimise()) passes.append(self._rebase_pass) if self._device_type == _DeviceType.QPU: passes.append( CXMappingPass( self._tket_device, NoiseAwarePlacement(self._tket_device), directed_cx=False, delay_measures=True, )) # If CX weren't supported by the device then we'd need to do another # rebase_pass here. But we checked above that it is. if optimisation_level == 1: passes.extend([RemoveRedundancies(), self._squash_pass]) if optimisation_level == 2: passes.extend([ CliffordSimp(False), SynthesiseIBM(), self._rebase_pass, self._squash_pass, ]) return SequencePass(passes)
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) passlist = [DecomposeBoxes()] if optimisation_level == 0: passlist.append(self._rebase_pass) elif optimisation_level == 1: passlist.append(SynthesiseIBM()) else: passlist.append(FullPeepholeOptimise()) if self._noise_model and self._device: passlist.append( CXMappingPass( self._device, NoiseAwarePlacement(self._device), directed_cx=True, delay_measures=False, )) if optimisation_level == 0: passlist.append(self._rebase_pass) elif optimisation_level == 1: passlist.append(SynthesiseIBM()) else: passlist.extend([CliffordSimp(False), SynthesiseIBM()]) return SequencePass(passlist)
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) passlist = [ DecomposeBoxes(), FlattenRegisters(), ] if optimisation_level == 1: passlist.append(SynthesiseIBM()) elif optimisation_level == 2: passlist.append(FullPeepholeOptimise()) passlist.append( CXMappingPass( self._device, NoiseAwarePlacement(self._device), directed_cx=False, delay_measures=True, )) if optimisation_level == 2: passlist.append(CliffordSimp(False)) if optimisation_level > 0: passlist.append(SynthesiseIBM()) passlist.append(RebaseQuil()) if optimisation_level > 0: passlist.append(EulerAngleReduction(OpType.Rx, OpType.Rz)) return SequencePass(passlist)
def ucc(params): ansatz = Circuit(4) ansatz.X(1).X(3) add_excitation(ansatz, singles_a, params[0]) add_excitation(ansatz, singles_b, params[1]) add_excitation(ansatz, doubles, params[2]) DecomposeBoxes().apply(ansatz) return ansatz
def test_boxes() -> None: c = Circuit(2) c.S(0) c.H(1) c.CX(0, 1) cbox = CircBox(c) d = Circuit(3, name="d") d.add_circbox(cbox, [0, 1]) d.add_circbox(cbox, [1, 2]) u = np.asarray([[0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1], [1, 0, 0, 0]]) ubox = Unitary2qBox(u) d.add_unitary2qbox(ubox, 0, 1) qsc = tk_to_qiskit(d) d1 = qiskit_to_tk(qsc) assert len(d1.get_commands()) == 3 DecomposeBoxes().apply(d) DecomposeBoxes().apply(d1) assert d == d1
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) passlist = [DecomposeBoxes(), FlattenRegisters()] if optimisation_level == 1: passlist.append(SynthesiseIBM()) elif optimisation_level == 2: passlist.append(FullPeepholeOptimise()) passlist.append(RebaseQuil()) if optimisation_level > 0: passlist.append(EulerAngleReduction(OpType.Rx, OpType.Rz)) return SequencePass(passlist)
def h2_JW_sto3g_ansatz(): symbols = [Symbol("s0"), Symbol("s1"), Symbol("s2")] ansatz = Circuit(4) # Initialise in Hartree-Fock state ansatz.X(0) ansatz.X(1) # Single excitations ansatz.add_pauliexpbox( PauliExpBox([Pauli.X, Pauli.Z, Pauli.Y, Pauli.I], -symbols[0]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.Y, Pauli.Z, Pauli.X, Pauli.I], symbols[0]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.I, Pauli.X, Pauli.Z, Pauli.Y], -symbols[1]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.I, Pauli.Y, Pauli.Z, Pauli.X], symbols[1]), [0, 1, 2, 3] ) # Double excitations ansatz.add_pauliexpbox( PauliExpBox([Pauli.X, Pauli.X, Pauli.X, Pauli.Y], -symbols[2]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.X, Pauli.X, Pauli.Y, Pauli.X], -symbols[2]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.X, Pauli.Y, Pauli.X, Pauli.X], symbols[2]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.Y, Pauli.X, Pauli.X, Pauli.X], symbols[2]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.X, Pauli.Y, Pauli.Y, Pauli.Y], -symbols[2]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.Y, Pauli.X, Pauli.Y, Pauli.Y], -symbols[2]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.Y, Pauli.Y, Pauli.X, Pauli.Y], symbols[2]), [0, 1, 2, 3] ) ansatz.add_pauliexpbox( PauliExpBox([Pauli.Y, Pauli.Y, Pauli.Y, Pauli.X], symbols[2]), [0, 1, 2, 3] ) # Synthesise structures into primitive gates DecomposeBoxes().apply(ansatz) return ansatz, symbols
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: """ A suggested compilation pass that will guarantee the resulting circuit will be suitable to run on this backend with as few preconditions as possible. :param optimisation_level: The level of optimisation to perform during compilation. Level 0 just solves the device constraints without optimising. Level 1 additionally performs some light optimisations. Level 2 adds more intensive optimisations that can increase compilation time for large circuits. Defaults to 1. :type optimisation_level: int, optional :return: Compilation pass guaranteeing required predicates. :rtype: BasePass """ assert optimisation_level in range(3) cx_circ = Circuit(2) cx_circ.Sdg(0) cx_circ.V(1) cx_circ.Sdg(1) cx_circ.Vdg(1) cx_circ.add_gate(OpType.ZZMax, [0, 1]) cx_circ.Vdg(1) cx_circ.Sdg(1) cx_circ.add_phase(0.5) def sq(a, b, c): circ = Circuit(1) if c != 0: circ.Rz(c, 0) if b != 0: circ.Rx(b, 0) if a != 0: circ.Rz(a, 0) return circ rebase = RebaseCustom({OpType.ZZMax}, cx_circ, {OpType.Rx, OpType.Ry, OpType.Rz}, sq) squash = SquashCustom({OpType.Rz, OpType.Rx, OpType.Ry}, sq) seq = [DecomposeBoxes()] # Decompose boxes into basic gates if optimisation_level == 1: seq.append(SynthesiseIBM()) # Optional fast optimisation elif optimisation_level == 2: seq.append(FullPeepholeOptimise()) # Optional heavy optimisation seq.append(rebase) # Map to target gate set if optimisation_level != 0: seq.append( squash) # Optionally simplify 1qb gate chains within this gate set return SequencePass(seq)
def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) passlist = [DecomposeBoxes()] if optimisation_level == 0: passlist.append(self._rebase_pass) elif optimisation_level == 1: passlist.append(SynthesiseIBM()) elif optimisation_level == 2: passlist.append(FullPeepholeOptimise()) passlist.append( CXMappingPass( self._device, NoiseAwarePlacement(self._device), directed_cx=False, delay_measures=(not self._mid_measure), )) if optimisation_level == 1: passlist.append(SynthesiseIBM()) if optimisation_level == 2: passlist.extend([CliffordSimp(False), SynthesiseIBM()]) if not self._legacy_gateset: passlist.extend([self._rebase_pass, RemoveRedundancies()]) return SequencePass(passlist)
OpType.Rx, OpType.Ry, OpType.Z, OpType.X, OpType.Y, OpType.V, OpType.Vdg, OpType.S, OpType.Sdg, OpType.H, }, _tk1_to_phasedxrz_clifford, ) regular_pass_0 = SequencePass( [FlattenRegisters(), DecomposeBoxes(), RebaseCirq()]) regular_pass_1 = SequencePass([ FlattenRegisters(), DecomposeBoxes(), SynthesiseIBM(), RebaseCirq(), RemoveRedundancies(), _cirq_squash, ]) regular_pass_2 = SequencePass([ FlattenRegisters(), DecomposeBoxes(), FullPeepholeOptimise(), RebaseCirq(), RemoveRedundancies(),
# Now that we have a circuit, `pytket` can take this and start operating on it directly. For example, we can apply some basic compilation passes to simplify it. from pytket.extensions.qiskit import qiskit_to_tk, tk_to_qiskit tk_circ = qiskit_to_tk(state_prep_circ) from pytket.passes import ( SequencePass, CliffordSimp, DecomposeBoxes, KAKDecomposition, SynthesiseIBM, ) DecomposeBoxes().apply(tk_circ) optimise = SequencePass([KAKDecomposition(), CliffordSimp(False), SynthesiseIBM()]) optimise.apply(tk_circ) # Display the optimised circuit: print(tk_to_qiskit(tk_circ)) # The Backends in `pytket` abstract away the differences between different devices and simulators as much as possible, allowing painless switching between them. The `pytket_pyquil` package provides two Backends: `ForestBackend` encapsulates both running on physical devices via Rigetti QCS and simulating those devices on the QVM, and `ForestStateBackend` acts as a wrapper to the pyQuil Wavefunction Simulator. # # Both of these still have a few restrictions on the circuits that can be run. Each only supports a subset of the gate types available in `pytket`, and a real device or associated simulation will have restricted qubit connectivity. The Backend objects will contain a default compilation pass that will statisfy these constraints as much as possible, with minimal or no optimisation. # # The `ForestStateBackend` will allow us to view the full statevector (wavefunction) expected from a perfect execution of the circuit. from pytket.extensions.pyquil import ForestStateBackend
tk_circ = qiskit_to_tk(q_circ) backend = FakeMelbourne() coupling_list = backend.configuration().coupling_map coupling_map = CouplingMap(coupling_list) characterisation = process_characterisation(backend) directed_arc = Device( characterisation.get("NodeErrors", {}), characterisation.get("EdgeErrors", {}), characterisation.get("Architecture", Architecture([])), ) comp_tk = tk_circ.copy() DecomposeBoxes().apply(comp_tk) FullPeepholeOptimise().apply(comp_tk) CXMappingPass(directed_arc, NoiseAwarePlacement(directed_arc), directed_cx=True, delay_measures=True).apply(comp_tk) DecomposeSwapsToCXs(directed_arc).apply(comp_tk) cost = lambda c: c.n_gates_of_type(OpType.CX) comp = RepeatWithMetricPass( SequencePass( [CommuteThroughMultis(), RemoveRedundancies(), CliffordSimp(False)]), cost) comp.apply(comp_tk) SynthesiseIBM().apply(comp_tk)
OpType.Rz, OpType.Rx, OpType.Ry, OpType.Z, OpType.X, OpType.Y, OpType.V, OpType.Vdg, OpType.S, OpType.Sdg, OpType.H, }, _tk1_to_phasedxrz_clifford, ) regular_pass_0 = SequencePass([FlattenRegisters(), DecomposeBoxes(), RebaseCirq()]) regular_pass_1 = SequencePass( [ FlattenRegisters(), DecomposeBoxes(), SynthesiseIBM(), RebaseCirq(), RemoveRedundancies(), _cirq_squash, ] ) regular_pass_2 = SequencePass( [ FlattenRegisters(), DecomposeBoxes(), FullPeepholeOptimise(),