def test_symbolic() -> None:
    pi2 = Symbol("pi2")
    pi3 = Symbol("pi3")

    tkc = Circuit(3, 3, name="test").Ry(pi2, 1).Rx(pi3, 1).CX(1, 0)
    USquashIBM().apply(tkc)

    qc = tk_to_qiskit(tkc)
    tkc2 = qiskit_to_tk(qc)

    assert tkc2.free_symbols() == {pi2, pi3}
    tkc2.symbol_substitution({pi2: pi / 2, pi3: pi / 3})

    backend = Aer.get_backend("statevector_simulator")
    qc = tk_to_qiskit(tkc2)
    assert qc.name == tkc.name
    job = execute([qc], backend)
    state1 = job.result().get_statevector(qc)
    state0 = np.array([[
        0.6252345 + 0.0j,
        0.0 + 0.0j,
        0.0 + 0.0j,
        -0.78000172 + 0.02606021j,
        0.0 + 0.0j,
        0.0 + 0.0j,
        0.0 + 0.0j,
        0.0 + 0.0j,
    ]])
    assert np.allclose(state0, state1, atol=1e-10)
def test_customgate() -> None:
    a = Symbol("a")
    def_circ = Circuit(2)
    def_circ.CZ(0, 1)
    def_circ.Rx(a, 1)
    gate_def = CustomGateDef.define("MyCRx", def_circ, [a])
    circ = Circuit(3)
    circ.Rx(0.1, 0)
    circ.Rx(0.4, 2)
    circ.add_custom_gate(gate_def, [0.2], [0, 1])

    qc1 = tk_to_qiskit(circ)
    newcirc = qiskit_to_tk(qc1)
    print(repr(newcirc))

    qc2 = tk_to_qiskit(newcirc)
    correct_circ = Circuit(3).Rx(0.1, 0).Rx(0.4, 2).CZ(0, 1).Rx(0.2, 1)
    correct_qc = tk_to_qiskit(correct_circ)

    backend = Aer.get_backend("statevector_simulator")
    states = []
    for qc in (qc1, qc2, correct_qc):
        job = execute([qc], backend)
        states.append(job.result().get_statevector(qc))

    assert compare_statevectors(states[0], states[1])
    assert compare_statevectors(states[1], states[2])
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
Ejemplo n.º 4
0
def print_circuit(tk_circuit):
    """Convert circuit to IBM Qiskit supported gates, and print that circuit

    Parameters
    ----------
    tk_circuit : pytket Circuit
        A pytket circuit"""
    print(tk_to_qiskit(tk_circuit))
def test_convert() -> None:
    qc = get_test_circuit(False)
    backend = Aer.get_backend("statevector_simulator")
    job = execute([qc], backend)
    state0 = job.result().get_statevector(qc)
    tkc = qiskit_to_tk(qc)
    assert qc.name == tkc.name
    qc = tk_to_qiskit(tkc)
    assert qc.name == tkc.name
    job = execute([qc], backend)
    state1 = job.result().get_statevector(qc)
    assert np.allclose(state0, state1, atol=1e-10)
def test_Unitary2qBox() -> None:
    c = Circuit(2)
    u = np.asarray([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
    ubox = Unitary2qBox(u)
    c.add_unitary2qbox(ubox, 0, 1)
    # Convert to qiskit
    qc = tk_to_qiskit(c)
    # Verify that unitary from simulator is correct
    back = Aer.get_backend("unitary_simulator")
    job = execute(qc, back).result()
    a = job.get_unitary(qc)
    assert np.allclose(a, u)
Ejemplo n.º 7
0
def circuit_to_ibm(tk_circuit):
    """Convert circuit to IBM Qiskit compatible verison, given pytket circuit

    Parameters
    ----------
    tk_circuit : pytket Circuit
        A pytket circuit

    Returns
    -------
    pytket Circuit
        An IBM Qiskit compatible pytket circuit"""
    return tk_to_qiskit(tk_circuit)
def test_measures() -> None:
    qc = get_test_circuit(True)
    backend = Aer.get_backend("qasm_simulator")
    job = execute([qc], backend, seed_simulator=7)
    counts0 = job.result().get_counts(qc)
    tkc = qiskit_to_tk(qc)
    qc = tk_to_qiskit(tkc)
    job = execute([qc], backend, seed_simulator=7)
    counts1 = job.result().get_counts(qc)
    for result, count in counts1.items():
        result_str = result.replace(" ", "")
        if counts0[result_str] != count:
            assert False
Ejemplo n.º 9
0
    def transpile(self):

        if self.level != 0:
            qc = transpile(self.qc,
                           basis_gates=['id', 'x', 'sx', 'rz', 'cx', 'reset'])
            tket_qc = qiskit_to_tk(qc)
            self.backend_tket.compile_circuit(tket_qc, optimisation_level=2)
            qc = tk_to_qiskit(tket_qc)
        else:
            qc = self.qc

        transpiled_qc = transpile(circuits=qc,
                                  backend=self.backend,
                                  basis_gates=None,
                                  seed_transpiler=1,
                                  optimization_level=self.level)

        return transpiled_qc
def test_tketpass() -> None:
    qc = get_test_circuit(False, False)
    tkpass = FullPeepholeOptimise()
    back = Aer.get_backend("unitary_simulator")
    for _ in range(12):
        tkc = qiskit_to_tk(qc)
        print(tkc.phase)
        tkpass.apply(tkc)
        print(tkc.phase)
    qc1 = tk_to_qiskit(tkc)
    res = execute(qc1, back).result()
    u1 = res.get_unitary(qc1)
    qispass = TketPass(tkpass)
    pm = PassManager(qispass)
    qc2 = pm.run(qc)
    res = execute(qc2, back).result()
    u2 = res.get_unitary(qc2)
    assert np.allclose(u1, u2)
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 assert_equivalence(
    circuits: List[Union[Circuit, QuantumCircuit]],
    require_qk_conversions_equality: bool = True,
    require_tk_equality: bool = True,
) -> None:
    """Given a list of circuits (either tket or qiskit), simulate them to calculate
    unitary matrices, and fail if they are not all almost equal.
    Also, (unless require_tk_equality is false), assert that
    all tket circuits are equal.
    If require_qk_conversions_equality is true,
    treat qk->tk conversions as if they were originally tk circuits and test
    for equality (rather than just equivalence), if require_tk_equality is true.
    """
    assert len(circuits) >= 2
    tk_circuits = []

    # We want unique circuit names, otherwise it confuses the Qiskit backend.
    names: Set[str] = set()
    for nn in range(len(circuits)):
        if isinstance(circuits[nn], Circuit):
            if require_tk_equality:
                tk_circuits.append(circuits[nn])
            # Of course, use the tket simulator directly once available.
            # But not yet, so need to convert to qiskit circuits.
            circuits[nn] = tk_to_qiskit(circuits[nn])
        elif require_qk_conversions_equality and require_tk_equality:
            tk_circuits.append(qiskit_to_tk(circuits[nn]))
        names.add(circuits[nn].name)
    assert len(names) == len(circuits)
    assert_tket_circuits_identical(tk_circuits)

    backend = Aer.get_backend("unitary_simulator")
    job = execute(circuits, backend)
    unitaries = [job.result().get_unitary(circ) for circ in circuits]
    for nn in range(1, len(circuits)):
        # Default np.allclose is very lax here, so use strict tolerances
        assert np.allclose(unitaries[0], unitaries[nn], atol=1e-14, rtol=0.0)
def test_condition_errors() -> None:
    with pytest.raises(Exception) as errorinfo:
        c = Circuit(2, 2)
        c.X(0, condition_bits=[0], condition_value=1)
        tk_to_qiskit(c)
    assert "OpenQASM conditions must be an entire register" in str(
        errorinfo.value)
    with pytest.raises(Exception) as errorinfo:
        c = Circuit(2, 2)
        b = c.add_c_register("b", 2)
        c.X(Qubit(0), condition_bits=[b[0], Bit(0)], condition_value=1)
        tk_to_qiskit(c)
    assert "OpenQASM conditions can only use a single register" in str(
        errorinfo.value)
    with pytest.raises(Exception) as errorinfo:
        c = Circuit(2, 2)
        c.X(0, condition_bits=[1, 0], condition_value=1)
        tk_to_qiskit(c)
    assert "OpenQASM conditions must be an entire register in order" in str(
        errorinfo.value)
Ejemplo n.º 14
0
# Connect to a simulator:

backend = AerBackend()

# Make a ZZ measurement of the Bell pair:

bell_test = es.copy()
bell_test.Measure(ava[0], data[0])
bell_test.Measure(charlie[0], data[1])

# Run the experiment:

backend.compile_circuit(bell_test)
from pytket.extensions.qiskit import tk_to_qiskit

print(tk_to_qiskit(bell_test))
handle = backend.process_circuit(bell_test, n_shots=2000)
counts = backend.get_result(handle).get_counts()

print(counts)

# This is good, we have got roughly 50/50 measurement results of 00 and 11 under the ZZ operator. But there are many other states beyond the Bell state that also generate this distribution, so to gain more confidence in our claim about the state we should make more measurements that also characterise it, i.e. perform state tomography.
#
# Here, we will demonstrate a naive approach to tomography that makes 3^n measurement circuits for an n-qubit state. More elaborate methods also exist.

from pytket.pauli import Pauli, QubitPauliString
from pytket.utils import append_pauli_measurement, probs_from_counts
from itertools import product
from scipy.linalg import lstsq, eigh
import numpy as np
Ejemplo n.º 15
0
    """
    Args:
        n_orbitals (int) = number of qubits/spin orbitals from MolecularData 
        n_electrons (int) = number of electrons from MolecularData
    Returns:
        circ (pytket.circuit.Circuit object) = in T1 configuration from H**O->LUMO
    """
    circ = Circuit(n_orbitals)
    
    for i in range(n_electrons-1): # for all but one electrons
        circ.X(i) # rotates from |0> to |1>
    circ.X(n_electrons) # rotate from |0> to |1> for the triplet spin orbital

    return circ


ref_circ_library = {
    's0': s0_circ,
    't1': t1_circ
}


if __name__ == "__main__":
    n_orbitals = 12
    n_electrons = 4
    ref = 's0'

    gen_ref_circ = ref_circ_library[ref]

    print(tk_to_qiskit(gen_ref_circ(n_orbitals, n_electrons)))
Ejemplo n.º 16
0
def print_tkcirc_via_qiskit(tkcirc):
    qiskit_qcirc = tk_to_qiskit(tkcirc)
    print(qiskit_qcirc)
Ejemplo n.º 17
0
#
# Let's use Qiskit's visualizer to see the effect on a circuit:

from pytket.extensions.qiskit import tk_to_qiskit

circ = Circuit(3)
circ.X(0).Y(1).CX(0,
                  1).Z(0).Rx(1.3,
                             1).CX(0,
                                   1).Rz(0.4,
                                         0).Ry(0.53,
                                               0).H(1).H(2).Rx(1.5,
                                                               2).Rx(0.5,
                                                                     2).H(2)

print(tk_to_qiskit(circ))

cu = CompilationUnit(circ)
reppass.apply(cu)
circ1 = cu.circuit

print(tk_to_qiskit(circ1))

# If we want to repeat a pass until the circuit satisfies some desired property, we first define a boolean function to test for that property, and then pass this function to the constructor of a `RepeatUntilSatisfied` pass:

from pytket.passes import RepeatUntilSatisfiedPass


def no_CX(circ):
    return circ.n_gates_of_type(OpType.CX) == 0
Ejemplo n.º 18
0
# We've now seen how to create custom Architectures using indexing and nodes, how to use our built in Architecture generators for typical connectivity graphs, how to create custom Devices using our QubitErrorContainers, and how to automatically generate a Device object for a real quantum computer straight from IBM.
#
# Let's now see how we can use these objects are used for Routing circuits - we create a circuit for Routing to our original architectures and assume the only primitive constraint is the ```CX``` gate, which can only be executed on an edge in our coupling map.

from pytket import Circuit

example_circuit = Circuit(4)
example_circuit.CX(0, 1).CX(0, 2).CX(1, 2).CX(3, 2).CX(0, 3)
for gate in example_circuit:
    print(gate)

# We can also visualise the `Circuit` using, for example, IBM Qiskit's `QuantumCircuit` printer. To do this, we must use the `pytket.extensions.qiskit` subpackage and import a method from within Qiskit.

from pytket.extensions.qiskit import tk_to_qiskit

print(tk_to_qiskit(example_circuit))

# This circuit can not be executed on any of our Architectures without modification. We can see this by looking at the circuits interaction graph, a graph where nodes are logical qubits and edges are some two-qubit gate.

interaction_edges = [(0, 1), (0, 2), (1, 2), (3, 2), (0, 3)]
draw_graph(interaction_edges)

draw_graph(simple_coupling_map)

# Sometimes we can route a circuit just by labelling the qubits to nodes of our Architecture such that the interaction graph matches a subgraph of the Architecture - unfortunately this isn't possible here.
#
# Let's call ```pytket```'s automatic routing method, route our circuit for the first Architecture we made, and have a look at our new circuit:

from pytket.routing import route

simple_modified_circuit = route(example_circuit, simple_architecture)
Ejemplo n.º 19
0
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)

state = state_backend.get_state(tk_circ)
print(state)
Ejemplo n.º 20
0
G = Graph(c)
G.get_DAG()

# The small numbers (0 and 1) shown at the entry to and exit from the two-qubit gates represent "port numbers" on the gates; these allow us to track individual qubits, which may be placed in a different order on entry and exit in order to simplify the layout.
#
# The `Graph` class also has methods to save this image to a file and to open it in a PDF viewer.
#
# We can also view the qubit connectivity graph of a circuit:

G.get_qubit_graph()

# ### Via Qiskit

from pytket.extensions.qiskit import tk_to_qiskit

print(tk_to_qiskit(c))

# ### Via Cirq

from pytket.extensions.cirq import tk_to_cirq

print(tk_to_cirq(c))

# (Note that Cirq cannot represent all gates diagrammatically.)

# ### Via Latex

# We can create a Latex document containing a diagram of the circuit using the `to_latex_file()` method. This uses the `quantikz` library. The document can be viewed on its own or the Latex can easily be copied and pasted into a larger document.

c.to_latex_file("c.tex")