Example #1
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)
Example #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()
Example #3
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),
             ),
         ])
Example #4
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),
            ])
Example #5
0
def objective(params):
    circ = ucc(params)
    PauliSimp().apply(circ)
    FullPeepholeOptimise().apply(circ)
    return (get_operator_expectation_value(
        circ, hamiltonian_op, backend, n_shots=4000) +
            nuclear_repulsion_energy)
Example #6
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)
Example #7
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)
Example #8
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(),
         ])
Example #9
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))

        start = time.perf_counter()
        FullPeepholeOptimise().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
        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()
Example #10
0
def ucc(params):
    singles_params = {qps: params[0] * coeff for qps, coeff in singles.items()}
    doubles_params = {qps: params[1] * coeff for qps, coeff in doubles.items()}
    excitation_op = QubitPauliOperator({**singles_params, **doubles_params})
    reference_circ = Circuit(4).X(1).X(3)
    ansatz = gen_term_sequence_circuit(excitation_op, reference_circ)
    GuidedPauliSimp().apply(ansatz)
    FullPeepholeOptimise().apply(ansatz)
    return ansatz
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)
Example #12
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()])
Example #13
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)
Example #14
0
    def _optimize(self, c):
        c_tket = pyzx_to_tk(c)
        FullPeepholeOptimise().apply(c_tket)

        # FIXME: Failing equality!
        # RebasePyZX().apply(c_tket)
        # c_opt = tk_to_pyzx(c_tket)

        # FIXME: Failing equality!
        qasm_str = circuit_to_qasm_str(c_tket)
        c_opt = zx.Circuit.from_qasm(qasm_str)

        return c_opt
Example #15
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)
Example #16
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)
def run(d, fname):

    f = open(fname, "w")

    f.write("name,Orig. total,Orig. CNOT,tket total,tket CNOT,time\n")

    for fname in os.listdir(d):

        print("Processing %s..." % fname)

        # same hack as the one used in run_qiskit.py
        inqasm = open(os.path.join(d, fname), "r")
        tmp = open("copy.qasm", "w")  # hardcoded filename
        p_ccz = re.compile("ccz (.*), (.*), (.*);")
        p_ccx = re.compile("ccx (.*), (.*), (.*);")

        for line in inqasm:
            m1 = p_ccx.match(line)
            m2 = p_ccz.match(line)
            if m1:
                a = m1.group(1)
                b = m1.group(2)
                c = m1.group(3)
                tmp.write("h %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("t %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("tdg %s;\n" % (b))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("t %s;\n" % (a))
                tmp.write("t %s;\n" % (b))
                tmp.write("t %s;\n" % (c))
                tmp.write("h %s;\n" % (c))
            elif m2:
                a = m2.group(1)
                b = m2.group(2)
                c = m2.group(3)
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("t %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("tdg %s;\n" % (b))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("t %s;\n" % (a))
                tmp.write("t %s;\n" % (b))
                tmp.write("t %s;\n" % (c))
            else:
                tmp.write(line)
        tmp.close()
        circ = circuit_from_qasm("copy.qasm")

        num_gates_before = circ.n_gates
        num_CNOTs_before = circ.n_gates_of_type(OpType.CX)
        print("Original:\t Total %d, CNOT %d" %
              (num_gates_before, num_CNOTs_before))

        start = time.perf_counter()  # start timer
        FullPeepholeOptimise().apply(circ)
        stop = time.perf_counter()  # stop timer
        num_gates_after = circ.n_gates
        num_CNOTs_after = circ.n_gates_of_type(OpType.CX)
        print("Final:\t Total %d, CNOT %d\n" %
              (num_gates_after, num_CNOTs_after))
        circuit_to_qasm(circ, fname.split(".")[0] + "_tket.qasm")

        f.write("%s,%d,%d,%d,%d,%f\n" %
                (fname, num_gates_before, num_CNOTs_before, num_gates_after,
                 num_CNOTs_after, stop - start))
Example #18
0
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,
    ]
)

clifford_pass_0 = SequencePass(
    [FlattenRegisters(), DecomposeBoxes(), _partial_clifford_rebase]
)
clifford_pass_1 = SequencePass(
    [
        FlattenRegisters(),
        DecomposeBoxes(),
        SynthesiseIBM(),
        RemoveRedundancies(),
Example #19
0
qi = QuantumInstance(backend, noise_model=model, seed_transpiler=2, seed_simulator=2)

grover_optimizer = GroverOptimizer(6, num_iterations=10, quantum_instance=qi)
results = grover_optimizer.solve(qp)
print("x={}".format(results.x))
print("fval={}".format(results.fval))
print("n_circs={}".format(len(results.operation_counts)))

# We can insert compilation passes from `pytket` into Qiskit as `TranspilerPass`es, compose with others to form a `PassManager`, and embed into the `QuantumInstance`.

from pytket.passes import FullPeepholeOptimise
from pytket.extensions.qiskit.tket_pass import TketPass
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import Unroller

tp = TketPass(FullPeepholeOptimise())
pm = PassManager([Unroller(["cx", "p", "u"]), tp])
qi = QuantumInstance(backend, pass_manager=pm, noise_model=model, seed_simulator=2)

grover_optimizer = GroverOptimizer(6, num_iterations=10, quantum_instance=qi)
results = grover_optimizer.solve(qp)
print("x={}".format(results.x))
print("fval={}".format(results.fval))
print("n_circs={}".format(len(results.operation_counts)))

# For this particular run, the case of compiling with Qiskit converged with fewer circuit executions but the additional noise incurred in running the circuit caused the optimiser to miss the global optimum, whereas the case for `pytket` eventually reached the true minimum value.
#
# When using `TketPass` there is a conversion between `qiskit.DAGCircuit` and `pytket.Circuit`, meaning the circuit needs to be in a form suitable for conversion (i.e. the gates used have to be supported by both `qiskit` and `pytket`). If you encounter any issues with using this, we recommend using `Unroller(['cx', 'u1', 'u2', 'u3'])` and `RebaseIBM` at the point before conversion to guarantee appropriate gates are used.

from pytket.passes import RebaseIBM, SequencePass
Example #20
0
    from qiskit import QuantumCircuit
    from qiskit.compiler import transpile
    from qiskit.transpiler import CouplingMap

    if comp_pass == _PASS_FULLPASS:  # Default
        comp_pass = _PASS_QISO3

outfile = "{set}Results_{comp}_{cpass}_{back}.csv".format(
    set=set_outfile_str[test_set],
    comp=compiler_outfile_str[compiler],
    cpass=pass_outfile_str[comp_pass],
    back=backend_outfile_str[backend])

### optimisation passes:
tketpass = FullPeepholeOptimise()
if compiler == _COMPILER_TKET and comp_pass == _PASS_CHEMPASS:
    tketpass = SequencePass([PauliSimp(), FullPeepholeOptimise()])

all_to_all_coupling = list()
for i in range(53):
    for j in range(i + 1, 53):
        all_to_all_coupling.append([i, j])

rigetti_coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7],
                    [7, 0], [8, 9], [9, 10], [10, 11], [11, 12], [12, 13],
                    [13, 14], [14, 15], [15, 8], [2, 15], [3, 14]]

google_coupling = [[0, 5], [1, 5], [1, 6], [2, 6], [2, 7], [3, 8], [3, 9],
                   [4, 9], [4, 10], [5, 11], [5, 12], [6, 12], [6, 13],
                   [7, 13], [7, 14], [8, 14], [8, 15], [9, 15], [9, 16],
Example #21
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)
Example #22
0
        # Start timer
        start = time.time()
        circ = Circuit(nb_qubits)

        h = 1.0
        Jz = 1.0
        for i in range(nb_steps):
            # Using Heisenberg Hamiltonian:
            for q in range(nb_qubits):
                circ.add_pauliexpbox(PauliExpBox([Pauli.X], -h * step_size),
                                     [q])
            for q in range(nb_qubits - 1):
                circ.add_pauliexpbox(
                    PauliExpBox([Pauli.Z, Pauli.Z], -Jz * step_size),
                    [q, q + 1])

        # Compile to gates
        backend = AerStateBackend()
        circ = backend.get_compiled_circuit(circ)

        # Apply optimization
        FullPeepholeOptimise().apply(circ)

        end = time.time()

        data.append(end - start)

    print('n_qubits =', nb_qubits, '; Elapsed time =', mean(data), '+/-',
          stdev(data), '[secs]')
    # for com in circ: # equivalently, circ.get_commands()
    #   print(com.op, com.op.type, com.args)
Example #23
0
energy = objective(arg_values)
print(energy)

# This is now the simplest form that this operation can take, but it isn't necessarily the most effective. When we decompose the ansatz circuit into basic gates, it is still very expensive. We can employ some of the circuit simplification passes available in `pytket` to reduce its size and improve fidelity in practice.
#
# A good example is to decompose each `PauliExpBox` into basic gates and then apply `FullPeepholeOptimise`, which defines a compilation strategy utilising all of the simplifications in `pytket` that act locally on small regions of a circuit. We can examine the effectiveness by looking at the number of two-qubit gates before and after simplification, which tends to be a good indicator of fidelity for near-term systems where these gates are often slow and inaccurate.

from pytket import OpType
from pytket.passes import FullPeepholeOptimise

test_circuit = ucc(arg_values)

print("CX count before", test_circuit.n_gates_of_type(OpType.CX))
print("CX depth before", test_circuit.depth_by_type(OpType.CX))

FullPeepholeOptimise().apply(test_circuit)

print("CX count after FPO", test_circuit.n_gates_of_type(OpType.CX))
print("CX depth after FPO", test_circuit.depth_by_type(OpType.CX))

# These simplification techniques are very general and are almost always beneficial to apply to a circuit if you want to eliminate local redundancies. But UCC ansätze have extra structure that we can exploit further. They are defined entirely out of exponentiated tensors of Pauli matrices, giving the regular structure described by the `PauliExpBox`es. Under many circumstances, it is more efficient to not synthesise these constructions individually, but simultaneously in groups. The `PauliSimp` pass finds the description of a given circuit as a sequence of `PauliExpBox`es and resynthesises them (by default, in groups of commuting terms). This can cause great change in the overall structure and shape of the circuit, enabling the identification and elimination of non-local redundancy.

from pytket.passes import PauliSimp

test_circuit = ucc(arg_values)

print("CX count before", test_circuit.n_gates_of_type(OpType.CX))
print("CX depth before", test_circuit.depth_by_type(OpType.CX))

PauliSimp().apply(test_circuit)
Example #24
0
def run_on_nam_benchmarks(fname):

    f = open(fname, "w")
    d = "nam-benchmarks"

    f.write("name, num gates before, num gates after\n")

    for fname in os.listdir(d):

        print("Processing %s..." % fname)

        # same hack as the one used in run_qiskit.py
        inqasm = open("nam-benchmarks/%s" % fname, "r")
        tmp = open("copy.qasm", "w")  # hardcoded filename
        p_ccz = re.compile("ccz (.*), (.*), (.*);")
        p_ccx = re.compile("ccx (.*), (.*), (.*);")

        for line in inqasm:
            m1 = p_ccx.match(line)
            m2 = p_ccz.match(line)
            if m1:
                a = m1.group(1)
                b = m1.group(2)
                c = m1.group(3)
                tmp.write("h %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("t %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("tdg %s;\n" % (b))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("t %s;\n" % (a))
                tmp.write("t %s;\n" % (b))
                tmp.write("t %s;\n" % (c))
                tmp.write("h %s;\n" % (c))
            elif m2:
                a = m2.group(1)
                b = m2.group(2)
                c = m2.group(3)
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("t %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("tdg %s;\n" % (b))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("t %s;\n" % (a))
                tmp.write("t %s;\n" % (b))
                tmp.write("t %s;\n" % (c))
            else:
                tmp.write(line)
        tmp.close()
        circ = circuit_from_qasm("copy.qasm")

        num_gates_before = circ.n_gates
        print("\nORIGINAL: %d gates" % (num_gates_before))

        FullPeepholeOptimise().apply(circ)
        num_gates_after = circ.n_gates
        print("OPTIMIZED: %d gates\n" % (num_gates_after))