Exemplo n.º 1
0
 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)
Exemplo n.º 2
0
 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)
Exemplo n.º 3
0
 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)
Exemplo n.º 4
0
 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),
             ),
         ])
Exemplo n.º 5
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),
            ])
Exemplo n.º 6
0
 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(),
         ])
Exemplo n.º 7
0
 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()])
Exemplo n.º 8
0
 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)
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
 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)
Exemplo n.º 11
0
def gen_tket_pass(optimisepass, backend: str):
    if backend == _BACKEND_FULL:
        return optimisepass
    elif backend == _BACKEND_RIGETTI:
        final_pass = RebaseQuil()
        device = rigetti_device
    elif backend == _BACKEND_GOOGLE:
        final_pass = RebaseCirq()
        device = google_sycamore_device
    elif backend == _BACKEND_IBM:
        final_pass = RebaseIBM()
        device = ibm_rochester_device
    mapper = CXMappingPass(device, GraphPlacement(device))
    total_pass = SequencePass(
        [optimisepass, mapper,
         SynthesiseIBM(), final_pass])
    return total_pass
Exemplo n.º 12
0
# 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

state_backend = ForestStateBackend()
Exemplo n.º 13
0
        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(),
        _cirq_squash,
    ]
)
Exemplo n.º 14
0
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)
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

state_backend = ForestStateBackend()