Exemplo n.º 1
0
def decompose_circuit(tk_circuit, decomposition_lvl):
    """Function to decompose circuit, with decomposition_lvl 1 decomposing BRIDGEs and 2 decomposing as much as possible (SWAPs).

    While normal pytket Circuits may contain bridge gates, these are not compatible with IBM Qiskit architectures. Therefore,
    one might have to decompose the circuit before converting it to an IBM Qiskit compatible version.

    Parameters
    ----------
    tk_circuit : pytket Circuit
        A pytket circuit
    decomposition_lvl : integer
        use 1 to decompose BRIDGEs, 2 to decompose as far as possible including SWAPs

    Returns
    -------
    pytket Circuit
        A pytket circuit decomposed
    """
    cu = CompilationUnit(tk_circuit)
    # 1 to decompose BRIDGE gates, 2 to decompose as far as possible (includes acceptable SWAPs!)
    if decomposition_lvl == 1:
        seqpass = SequencePass([DecomposeMultiQubitsIBM()])
    elif decomposition_lvl == 2:
        seqpass = SequencePass(
            [DecomposeMultiQubitsIBM(),
             DecomposeSingleQubitsIBM()])
    # apply decomposition and return the resulting circuit
    seqpass.apply(cu)
    return cu.circuit
Exemplo n.º 2
0
def run(d,fname):
    
    f = open(fname, "w")
    
    f.write("name,1q,2q,total,time\n")
    
    for fname in os.listdir(d):

        print("Processing %s..." % fname)
        
        circ = circuit_from_qasm(os.path.join(d, fname))

        # Other useful optimizations include OptimisePhaseGadgets and PauliSimp.
        # We exclude them here because they make performance worse on our benchmarks.
        seq_pass=SequencePass([FullPeepholeOptimise(), RemoveRedundancies()])

        start = time.perf_counter()
        seq_pass.apply(circ)
        stop = time.perf_counter()

        total_count = circ.n_gates
        two_count = circ.n_gates_of_type(OpType.CX)
        one_count = total_count - two_count

        # note: could potentially convert to other gate sets here with RebaseCustom

        print("\t Total %d, 1q %d, CNOT %d\n" % (total_count, one_count, two_count))

        f.write("%s,%d,%d,%d,%f\n" % (fname, one_count, two_count, total_count, stop - start))
        
    f.close()
Exemplo n.º 3
0
def predicate_route_device(my_circuit, my_device):
    gp = GraphPlacement(my_device)
    gp.place(my_circuit)
    cu = CompilationUnit(my_circuit, [ConnectivityPredicate(my_device)])
    routing_passes = SequencePass(
        [RoutingPass(my_device),
         DecomposeSwapsToCXs(my_device, False)])
    routing_passes.apply(cu)
    return cu.circuit, cu.check_all_predicates()
Exemplo n.º 4
0
def place_on_device(
    circuit: cirq.Circuit,
    device: cirq.google.XmonDevice,
) -> Tuple[cirq.Circuit, Dict[cirq.Qid, cirq.Qid], Dict[cirq.Qid, cirq.Qid]]:
    """Place a circuit on an device.

    Converts a circuit to a new circuit that respects the adjacency of a given
    device and is equivalent to the given circuit up to qubit ordering.

    Args:
        circuit: The circuit to place on a grid.
        device: The device to place the circuit on.

    Returns:
        routed_circuit: The new circuit
        initial_map: Initial placement of qubits
        final_map: The final placement of qubits after action of the circuit
    """
    index_to_qubit = sorted(device.qubit_set())
    qubit_to_index = {q: i for i, q in enumerate(index_to_qubit)}
    tk_circuit = pytket.cirq.cirq_to_tk(circuit)
    tk_device = _device_to_tket_device(device, qubit_to_index)

    unit = CompilationUnit(tk_circuit, [ConnectivityPredicate(tk_device)])
    passes = SequencePass(
        [PlacementPass(GraphPlacement(tk_device)),
         RoutingPass(tk_device)])
    passes.apply(unit)
    valid = unit.check_all_predicates()
    if not valid:
        raise RuntimeError("Routing failed")

    initial_map = {
        cirq.LineQubit(_tk_to_i(n1)): index_to_qubit[_tk_to_i(n2)]
        for n1, n2 in unit.initial_map.items()
    }
    final_map = {
        cirq.LineQubit(_tk_to_i(n1)): index_to_qubit[_tk_to_i(n2)]
        for n1, n2 in unit.final_map.items()
    }
    routed_circuit = pytket.cirq.tk_to_cirq(unit.circuit)
    routed_circuit = routed_circuit.transform_qubits(
        lambda q: index_to_qubit[q.x])

    return routed_circuit, initial_map, final_map
Exemplo n.º 5
0
def place_on_device(
    circuit: cirq.Circuit,
    device: cg.XmonDevice,
) -> Tuple[cirq.Circuit, Dict[cirq.Qid, cirq.Qid], Dict[cirq.Qid, cirq.Qid]]:
    """Place a circuit on an device.

    Converts a circuit to a new circuit that respects the adjacency of a given
    device and is equivalent to the given circuit up to qubit ordering.

    Args:
        circuit: The circuit to place on a grid.
        device: The device to place the circuit on.

    Returns:
        routed_circuit: The new circuit
        initial_map: Initial placement of qubits
        final_map: The final placement of qubits after action of the circuit
    """
    tk_circuit = pytket.extensions.cirq.cirq_to_tk(circuit)
    tk_device = _device_to_tket_device(device)

    unit = CompilationUnit(tk_circuit, [ConnectivityPredicate(tk_device)])
    passes = SequencePass(
        [PlacementPass(GraphPlacement(tk_device)),
         RoutingPass(tk_device)])
    passes.apply(unit)
    valid = unit.check_all_predicates()
    if not valid:
        raise RuntimeError("Routing failed")

    initial_map = {
        tk_to_cirq_qubit(n1): tk_to_cirq_qubit(n2)
        for n1, n2 in unit.initial_map.items()
    }
    final_map = {
        tk_to_cirq_qubit(n1): tk_to_cirq_qubit(n2)
        for n1, n2 in unit.final_map.items()
    }
    routed_circuit = pytket.extensions.cirq.tk_to_cirq(unit.circuit)

    return routed_circuit, initial_map, final_map
Exemplo n.º 6
0
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()
state_backend.compile_circuit(tk_circ)
Exemplo n.º 7
0
                          (15, 16), (16, 17), (17, 18), (18, 19), (19, 20),
                          (20, 21), (21, 22), (12, 23), (16, 24), (20, 25),
                          (23, 26), (24, 30), (25, 34), (26, 27), (27, 28),
                          (28, 29), (29, 30), (30, 31), (31, 32), (32, 33),
                          (33, 34), (34, 35), (35, 36), (28, 37), (32, 38),
                          (36, 39), (37, 42), (38, 46), (39, 50), (40, 41),
                          (41, 42), (42, 43), (43, 44), (44, 45), (45, 46),
                          (46, 47), (47, 48), (48, 49), (49, 50), (40, 51),
                          (44, 52), (48, 53), (51, 54), (52, 58), (53, 62),
                          (54, 55), (55, 56), (56, 57), (57, 58), (58, 59),
                          (59, 60), (60, 61), (61, 62), (62, 63), (63, 64),
                          (56, 65), (60, 66), (64, 67), (65, 70), (66, 74),
                          (67, 78), (68, 69), (69, 70), (70, 71), (71, 72),
                          (72, 73), (73, 74), (74, 75), (75, 76), (76, 77),
                          (77, 78), (68, 79), (72, 80), (76, 81)]

tk_circuit = pytket.cirq.cirq_to_tk(circuit)
tk_device = _device_connection_list_to_tket_device(device_connection_list)

unit = CompilationUnit(tk_circuit, [ConnectivityPredicate(tk_device)])

passes = SequencePass([
    PlacementPass(GraphPlacement(tk_device)),
    RoutingPass(tk_device, bridge_lookahead=0, bridge_interactions=0)
])  # NO BRIDGE
passes.apply(unit)
valid = unit.check_all_predicates()

assert valid

routed_circuit = pytket.cirq.tk_to_cirq(unit.circuit)
Exemplo n.º 8
0
print(circ.get_commands())

# ## Combining passes

# There are various ways to combine the elementary passes into more complex ones.
#
# To combine several passes in sequence, we use a `SequencePass`:

from pytket.passes import SequencePass, OptimisePhaseGadgets

seqpass = SequencePass([DecomposeMultiQubitsIBM(), OptimisePhaseGadgets()])

# This pass will apply the two transforms in succession:

cu = CompilationUnit(circ)
seqpass.apply(cu)
circ1 = cu.circuit
print(circ1.get_commands())

# The `apply()` method for an elementary pass returns a boolean indicating whether or not the pass had any effect on the circuit. For a `SequencePass`, the return value indicates whether _any_ of the constituent passes had some effect.
#
# A `RepeatPass` repeatedly calls `apply()` on a pass until it returns `False`, indicating that there was no effect:

from pytket.passes import CommuteThroughMultis, RemoveRedundancies, RepeatPass

seqpass = SequencePass([CommuteThroughMultis(), RemoveRedundancies()])
reppass = RepeatPass(seqpass)

# This pass will repeatedly apply `CommuteThroughMultis` (which commutes single-qubit operations through multi-qubit operations where possible towards the start of the circuit) and `RemoveRedundancies` (which cancels inverse pairs, merges coaxial rotations and removes redundant gates before measurement) until neither pass has any effect on the circuit.
#
# Let's use Qiskit's visualizer to see the effect on a circuit: