示例#1
0
def iterated_entanglement_swap(n_iter):
    # Iterate the entanglement swapping protocol n_iter times
    it_es = Circuit()
    ava = it_es.add_q_register("a", 1)
    bella = it_es.add_q_register("b", 2)
    charlie = it_es.add_q_register("c", 1)
    data = it_es.add_c_register("d", 2)

    # Start with an initial Bell state
    it_es.H(ava[0])
    it_es.CX(ava[0], bella[0])

    for i in range(n_iter):
        if i % 2 == 0:
            # Teleport bella[0] to charlie[0] to give a Bell pair between ava[0] and charlier[0]
            tel_to_c = qtel.copy()
            tel_to_c.rename_units(
                {alice[0]: bella[0], alice[1]: bella[1], bob[0]: charlie[0]}
            )
            it_es.append(tel_to_c)
            it_es.add_gate(OpType.Reset, [bella[0]])
            it_es.add_gate(OpType.Reset, [bella[1]])
        else:
            # Teleport charlie[0] to bella[0] to give a Bell pair between ava[0] and bella[0]
            tel_to_b = qtel.copy()
            tel_to_b.rename_units(
                {alice[0]: charlie[0], alice[1]: bella[1], bob[0]: bella[0]}
            )
            it_es.append(tel_to_b)
            it_es.add_gate(OpType.Reset, [bella[1]])
            it_es.add_gate(OpType.Reset, [charlie[0]])
    # Return the circuit and the qubits expected to share a Bell pair
    if n_iter % 2 == 0:
        return it_es, [ava[0], bella[0]]
    else:
        return it_es, [ava[0], charlie[0]]
示例#2
0
文件: qasm.py 项目: tbcdebug/pytket
class QASMParser(object):
    """Class for parsing OpenQASM files into CQC t|ket> Circuits."""
    def __init__(self):
        self.circuit = Circuit()
        self.register_dict = dict()

    def parse_qasm(self, qasm):
        lines = qasm.splitlines()
        rows = []

        #first, get rid of comments and whitespace lines
        for l in lines:
            i = l.find("//")
            if i != -1:
                s = l[0:i].strip()
            else:
                s = l.strip()
            if s: rows.append(s)

        #now, throw away OPENQASM descriptor etc.
        if not (rows[0].startswith("OPENQASM 2.0")
                and rows[1].startswith('include "qelib1.inc";')):
            raise TypeError(
                "File must declare OPENQASM version and its includes.")
        data = "\n".join(rows[2:])

        #now, separate out the custom gates to deal with elsewhere
        while True:
            i = data.find("gate ")
            if i == -1: break
            j = data.find("}", i)
            if j == -1: raise TypeError("Custom gate definition is invalid.")
            self.parse_custom_gate(data[i:j + 1])  #TODO: deal with custom gate
            data = data[:i] + data[j + 1:]

        #now, parse the regular instructions
        instructions = [s.strip() for s in data.split(";") if s.strip()]
        for i in instructions:
            self.parse_instruction(i)
        return self.circuit

    def parse_custom_gate(self, data):
        raise TypeError("Cannot currently parse custom gates")

    def parse_instruction(self, instruction):
        if instruction.find("->") != -1:
            ###handle measure gates
            ###currently assumes that there is just 1 qb being read to 1 bit
            name_and_qbs, bits = instruction.split("->", 1)
            if (name_and_qbs.find("measure") == -1):
                raise Exception(
                    "Error in parsing: cannot accept a non-Measure gate writing to classical register"
                )
            name_and_qbs = name_and_qbs.replace("measure", "")
            name_and_qbs = name_and_qbs.replace(" ", "")

            name_and_qbs.strip()
            qregname, qbindex = name_and_qbs.split("[")
            qbindex = int(qbindex[0])
            qubit = self.circuit.q_regs[qregname][qbindex]

            bits = bits.replace(" ", "")
            bitreg, bitindex = bits.split("[")
            bitindex = int(bitindex[0])
            bit = self.circuit.c_regs[bitreg][bitindex]

            self.circuit.add_measure(qubit, bit)
            return

        if instruction.find("(") != -1:
            name, rest = instruction.split(") ", 1)
            name = name.replace(" ", "")
        else:
            name, rest = instruction.split(" ", 1)
        args = [s.strip() for s in rest.split(",") if s.strip()]

        #deal with qubit register declarations
        if name == "qreg" or name == "creg":
            regname, size = args[0].split("[", 1)
            regname.strip()
            size = int(size[:-1])
            if name == "qreg":
                self.circuit.add_q_register(regname, size)
            else:
                self.circuit.add_c_register(regname, size)
            return

        #get qubits to append operation to
        qubits = []
        for a in args:
            if "[" in a:
                regname, val = a.split("[", 1)
                val = int(val[:-1])
                qubits.append(self.circuit.q_regs[regname][val])
            else:
                raise Exception(
                    "Unknown error in parsing: Cannot parse argument {}".
                    format(a))

        #if the gate is parameterised, get these parameters
        if name.find("(") != -1:
            name, params = name.split("(", 1)
            if name in PARAM_COMMANDS:
                angles = [s.strip() for s in params.split(",") if s.strip()]
                halfturn_angles = []
                for ang in angles:
                    ang = ang.replace("pi", str(math.pi))
                    try:
                        halfturns = sympify(ang) / math.pi
                        halfturn_angles.append(halfturns)
                    except:
                        raise TypeError("Cannot parse angle: {}".format(ang))
                self.circuit.add_gate(PARAM_COMMANDS[name], halfturn_angles,
                                      qubits, [])

            else:
                raise TypeError("Cannot parse gate of type: {}".format(name))

        else:
            if name in NOPARAM_COMMANDS:
                self.circuit.add_gate(NOPARAM_COMMANDS[name], [], qubits, [])
            else:
                raise TypeError("Cannot parse gate of type: {}".format(name))
示例#3
0
# `measure a[0] -> c[0];`
# `measure a[1] -> c[1];`
# `// Correction of Bob's qubit`
# `if(c==1) z b[0];`
# `if(c==3) z b[0];`
# `if(c==2) x b[0];`
# `if(c==3) x b[0];`
#
# This corresponds to the following `pytket` code:

from pytket import Circuit

qtel = Circuit()
alice = qtel.add_q_register("a", 2)
bob = qtel.add_q_register("b", 1)
data = qtel.add_c_register("d", 2)

# Bell state between Alice and Bob:

qtel.H(alice[1])
qtel.CX(alice[1], bob[0])

# Bell measurement of Alice's qubits:

qtel.CX(alice[0], alice[1])
qtel.H(alice[0])
qtel.Measure(alice[0], data[0])
qtel.Measure(alice[1], data[1])

# Correction of Bob's qubit:
# - can be provided with a `qiskit.providers.Aer.noise.NoiseModel` on instantiation to perform a noisy simulation.

# Useful features:
# - support for fast expectation value calculations according to `QubitPauliString`s or `QubitPauliOperator`s.

from pytket import Circuit
from pytket.extensions.qiskit import AerBackend
from itertools import combinations
from qiskit.providers.aer.noise import NoiseModel, depolarizing_error

# Quantum teleportation circuit:

c = Circuit()
alice = c.add_q_register("a", 2)
bob = c.add_q_register("b", 1)
data = c.add_c_register("d", 2)
final = c.add_c_register("f", 1)

# Start in an interesting state:

c.Rx(0.3, alice[0])

# Set up a Bell state between Alice and Bob:

c.H(alice[1]).CX(alice[1], bob[0])

# Measure Alice's qubits in the Bell basis:

c.CX(alice[0], alice[1]).H(alice[0])
c.Measure(alice[0], data[0])
c.Measure(alice[1], data[1])