示例#1
0
def run(d, fname):
    
    f = open(fname, "w")
        
    f.write("name,Orig. total,Orig. CNOT,Orig. T,PyZX total,PyZX CNOT,PyZX T,time\n")
    
    for fname in os.listdir(d):

        print("Processing %s..." % fname)
        
        circ = zx.Circuit.load(os.path.join(d, fname)).to_basic_gates()
        num_gates_before = len(circ.gates)
        cnot_count_before = circ.twoqubitcount()
        t_count_before = zx.tcount(circ)
        print("Original:\t Total %d, CNOT %d, T %d" % (num_gates_before, cnot_count_before, t_count_before))
        
        start = time.perf_counter() # start timer
        g = circ.to_graph()
        zx.full_reduce(g,quiet=False)
        g.normalize()
        new_circ = zx.extract_circuit(g).to_basic_gates()
        stop = time.perf_counter() # stop timer
        num_gates_after = len(new_circ.gates)
        cnot_count_after = new_circ.twoqubitcount()
        t_count_after = zx.tcount(new_circ)
        print("Final:\t Total %d, CNOT %d, T %d\n" % (num_gates_after, cnot_count_after, t_count_after))

        f.write("%s,%d,%d,%d,%d,%d,%d,%f\n" % (fname, num_gates_before, cnot_count_before, t_count_before, num_gates_after, cnot_count_after, t_count_after, stop - start))
示例#2
0
def run(d, fname):

    f = open(fname, "w")

    f.write("name,T,2q,total,time\n")

    for fname in os.listdir(d):

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

        circ = zx.Circuit.load(os.path.join(d, fname)).to_basic_gates()

        start = time.perf_counter()
        g = circ.to_graph()
        zx.full_reduce(g, quiet=False)
        g.normalize()
        new_circ = zx.extract_circuit(g).to_basic_gates()
        stop = time.perf_counter()

        total_count = len(new_circ.gates)
        two_count = new_circ.twoqubitcount()
        t_count = zx.tcount(new_circ)

        print("\t Total %d, T %d, CNOT %d\n" %
              (total_count, t_count, two_count))

        f.write("%s,%d,%d,%d,%f\n" %
                (fname, t_count, two_count, total_count, stop - start))

    f.close()
示例#3
0
def test_convert_to_from_pyzx_optimizing_circuit(tequila_circuit, t_reduce):

    pyzx_circuit = convert_to_pyzx(tequila_circuit)

    pyzx_graph = pyzx_circuit.to_graph()

    if t_reduce:
        pyzx.teleport_reduce(pyzx_graph)
        pyzx_circuit_opt = pyzx.Circuit.from_graph(pyzx_graph)
    else:
        pyzx.full_reduce(pyzx_graph)
        pyzx_graph.normalize()
        pyzx_circuit_opt = pyzx.extract_circuit(pyzx_graph.copy())

    # compare_tensors returns True if pyzx_circuit and pyzx_circuit_opt
    # implement the same circuit (up to global phase)
    assert (pyzx.compare_tensors(pyzx_circuit, pyzx_circuit_opt))

    # verify_equality return True if full_reduce() is able to reduce the
    # composition of the circuits to the identity
    assert (pyzx_circuit.verify_equality(pyzx_circuit_opt))

    converted_circuit = convert_from_pyzx(pyzx_circuit_opt)

    wfn1 = simulate(tequila_circuit, backend="symbolic")
    wfn2 = simulate(converted_circuit, backend="symbolic")

    assert (numpy.isclose(wfn1.inner(wfn2), 1.0))
示例#4
0
def pivot_anneal(g,
                 iters=1000,
                 temp=25,
                 cool=0.005,
                 score=g_score,
                 cong_ps=[0.5, 0.5],
                 lc_select=uniform_weights,
                 pivot_select=uniform_weights,
                 full_reduce_prob=0.1,
                 reset_prob=0.0,
                 quiet=False):
    g_best = g.copy()
    sz = score(g_best)
    sz_best = sz

    best_scores = list()

    for i in tqdm(range(iters), desc="annealing...", disable=quiet):

        g1 = g.copy()

        cong_method = np.random.choice(["LC", "PIVOT"], 1, p=cong_ps)[0]

        if cong_method == "PIVOT":
            apply_rand_pivot(g1, weight_func=pivot_select)
        else:
            apply_rand_lc(g1, weight_func=lc_select)

        # probabilistically full_reduce:
        if random.uniform(0, 1) < full_reduce_prob:
            zx.full_reduce(g1)
        sz1 = score(g1)

        best_scores.append(sz_best)

        if temp != 0: temp *= 1.0 - cool
        # if i % 50 == 0:
        # print(i)
        # print(temp)

        if sz1 < sz or \
            (temp != 0 and random.random() < math.exp((sz - sz1)/temp)):
            # if temp != 0: temp *= 1.0 - cool

            sz = sz1
            g = g1.copy()
            if sz < sz_best:
                # print("NEW BEST")
                g_best = g.copy()
                sz_best = sz
        elif random.uniform(0, 1) < reset_prob:
            g = g_best.copy()

    return g_best, best_scores
def g_score(g):
    g_tmp = g.copy()

    # FIXME: VERY EXPENSIVE. only to enable circuit extraction.
    # A better strategy would be to probailistically full_reduce

    zx.full_reduce(g_tmp)
    c = zx.extract_circuit(g_tmp.copy()).to_basic_gates()
    c = zx.basic_optimization(c)

    return c_score(c)
    """
def rand_lc(c, g, reduce_prob=0.1):
    g_tmp = g.copy()
    apply_rand_lc(g_tmp)

    # Note the work around to not always full_reduce the graph itself!
    g_fr = g_tmp.copy()
    zx.full_reduce(g_fr)
    c_new = zx.extract_circuit(g_fr.copy()).to_basic_gates()
    c_new = zx.basic_optimization(c_new)
    if random.uniform(0, 1) < reduce_prob:
        g_tmp = g_fr.copy()
    return True, (c_new, g_tmp)
def full_reduce(c, g):
    # FIXME: Should really be using g_tmp here?
    orig_tcount = c.tcount()
    orig_2qubitcount = c.twoqubitcount()

    zx.full_reduce(g)
    c_opt = zx.extract_circuit(g.copy())

    opt_tcount = c_opt.tcount()
    opt_2qubitcount = c_opt.twoqubitcount()
    if orig_tcount == opt_tcount and orig_2qubitcount == opt_2qubitcount:
        return False, (c, g)
    return True, (c_opt, g)
示例#8
0
    def optimize(self):
        """
      Optimize the circuit using PyZX full_reduce optimization function
    """
        # transforming the PyZX circuit to a graph
        graph = self.circuit_zx.to_graph()
        zx.full_reduce(graph, quiet=True)

        # Optimizing the graph
        graph.normalize()

        # Extracting the circuit from the optimized graph
        self.circuit_zx = zx.extract_circuit(graph.copy())
        return self.circuit_zx
示例#9
0
def run(d, fname):

    f = open(fname, "w")

    f.write("name,T,2q,total,time\n")

    for fname in os.listdir(d):

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

        circ = zx.Circuit.load(os.path.join(d, fname)).to_basic_gates()

        start = time.perf_counter()
        g = circ.to_graph()
        zx.full_reduce(g)
        g.normalize()
        opt_circ = zx.extract_circuit(g).to_basic_gates()
        stop = time.perf_counter()
        elapsed = stop - start
        if elapsed < TIMEOUT:
            try:  # try to run full_optimize, cancelling after 10 minutes - elapsed
                with time_limit(TIMEOUT - round(elapsed)):
                    opt_circ = zx.full_optimize(opt_circ)
                    stop = time.perf_counter()
            except TimeoutException:
                print("\tfull_optimize is slow; only running full_reduce")
        else:
            print("\tfull_optimize is slow; only running full_reduce")

        total_count = len(opt_circ.gates)
        two_count = opt_circ.twoqubitcount()
        t_count = zx.tcount(opt_circ)

        print("\tTotal %d, T %d, 2-qubit %d\n" %
              (total_count, t_count, two_count))

        f.write("%s,%d,%d,%d,%f\n" %
                (fname, t_count, two_count, total_count, stop - start))

    f.close()
def qiskit_transpiler_pass(qasm):
    """
    Class for parsing OPENQASM source files from a Qiskit QuantumCircuit,
    optimizing within PyZX, and converting back to OPENQASM that can be
    reconstructed into a Qiskit QuantumCircuit.
    """
    # Call to a parent class of QASMParser to parse Qiskit's OPENQASM
    p = QiskitQASMParser()
    circ_list, whichpyzx = p.qiskitparse(qasm)
    graph_list = [circ_list[w].to_graph() for w in whichpyzx]
    [pyzx.full_reduce(g) for g in graph_list]
    pyzx_circ_list = [pyzx.extract.streaming_extract(g) for g in graph_list]
    pyzx_circ_list = [
        pyzx.optimize.basic_optimization(new_c.to_basic_gates())
        for new_c in pyzx_circ_list
    ]
    pyzx_qasm = [new_c.to_basic_gates().to_qasm() for new_c in pyzx_circ_list]
    # Verify with compare_tensor that all PyZX optimizations correctly simplify
    passedAll = True
    for i in range(len(pyzx_circ_list)):
        try:
            assert (
                True
            )  #assert(pyzx.compare_tensors(pyzx_circ_list[i], circ_list[whichpyzx[i]], False))
        except AssertionError:
            passedAll = False
    if not passedAll:
        return None
    # Ignore all register declarations and map registers back to the input qasm
    pyzx_qasm = [
        "\n".join([
            '' if line.startswith("qreg") else line
            for line in circ.splitlines()[2:]
        ]) for circ in pyzx_qasm
    ]
    for i in range(len(pyzx_qasm)):
        circ_list[whichpyzx[i]] = pyzx_qasm[i]
    qasm_string = 'OPENQASM 2.0;\ninclude "qelib1.inc";\n' + "\n".join(
        circ_list)
    sorted_registers = sorted(p.registers.items(), key=lambda x: x[1][0])
    poss = [m.start() for m in re.finditer('q\[', qasm_string)]
    registered_qasm = ''
    prev_pos = 0
    for pos in poss:
        registered_qasm += qasm_string[prev_pos:pos]
        prev_pos = pos + qasm_string[pos:].find(']')
        id = int(qasm_string[pos + 2:prev_pos])
        leq_list = list(filter(lambda x: (x[1][0] <= id), sorted_registers))
        registered_qasm += leq_list[-1][0] + '[' + str(id - leq_list[-1][1][0])
    registered_qasm += qasm_string[prev_pos:]
    return registered_qasm
示例#11
0
 def _optimize(self, c):
     g = c.to_graph()
     zx.full_reduce(g, quiet=True)
     c_opt = zx.extract_circuit(g.copy()) # FIXME: maybe don't need g.copy()?
     return c_opt
示例#12
0
    N_QUBITS = 5
    DEPTH = 100
    c = zx.generate.CNOT_HAD_PHASE_circuit(qubits=N_QUBITS,
                                           depth=DEPTH,
                                           clifford=False)
    print("----- initial -----")
    print(c.stats())

    # zx.draw(c)
    plt.show()
    plt.close('all')

    g = c.to_graph()

    g_fr = g.copy()
    zx.full_reduce(g_fr)
    c_fr = zx.extract_circuit(g_fr.copy()).to_basic_gates()
    c_fr = zx.basic_optimization(c_fr)
    # note: we don't reset g_fr here because for any future annealing, we'd really optimize after the graph produced by full_reduce, rather than something resulting from extraction
    print("\n----- full_reduce + basic_optimization -----")
    print(c_fr.stats())

    g_just_tr = g.copy()
    zx.teleport_reduce(g_just_tr)
    c_just_tr = zx.Circuit.from_graph(g_just_tr.copy()).to_basic_gates()
    print("\n----- teleport_reduce -----")
    print(c_just_tr.stats())

    g_tr = g.copy()
    zx.teleport_reduce(g_tr)
    c_tr = zx.Circuit.from_graph(g_tr.copy()).to_basic_gates()
    improvement_after = { x: list() for x in range(0, N_ITERS, INTERVAL) }

    REDUCE_METHOD = "TR"

    for c in tqdm(cs, desc="Circuits..."):
        g = c.to_graph()

        g_tmp = g.copy()

        if REDUCE_METHOD == "TR":
            zx.teleport_reduce(g_tmp)
            c_tr = zx.Circuit.from_graph(g_tmp.copy()).to_basic_gates()
            c_tr = zx.basic_optimization(c_tr)
            g_simp = c_tr.to_graph()
        elif REDUCE_METHOD == "FR":
            zx.full_reduce(g_tmp)
            g_simp = g_tmp.copy()
        else:
            raise RuntimeError(f"Invalid REDUCE_METHOD: {REDUCE_METHOD}")

        to_graph_like(g_simp)

        _, scores = pivot_anneal(g_simp, iters=N_ITERS)
        final_score = scores[-1]
        for x in range(0, N_ITERS, INTERVAL):
            if final_score < scores[x]:
                improvement_after[x].append(1)
            else:
                improvement_after[x].append(0)

示例#14
0
    # plt.show()
    cs_thresholded = [(f, c) for (f, c) in bench_cs if c.qubits <= QUBIT_THRESHOLD]
    print(f"{len(bench_cs)} benchmark circuits, {len(cs_thresholded)} of which have at most {QUBIT_THRESHOLD} qubits")

    reductions = dict()

    for (f, c) in cs_thresholded[:3]:

        init_score = c_score(c)
        g = c.to_graph()
        g_tmp = g.copy()

        if METHOD == "FR":
            g_opt = g_tmp.copy()

            zx.full_reduce(g_opt)
            c_opt = zx.extract_circuit(g_opt.copy()).to_basic_gates()
            c_opt = zx.basic_optimization(c_opt)

            opt_score = c_score(c_opt)
        elif METHOD == "TR":
            g_opt = g_tmp.copy()

            zx.teleport_reduce(g_opt)
            c_opt = zx.Circuit.from_graph(g_opt.copy()).to_basic_gates()
            c_opt = zx.basic_optimization(c_opt)

            opt_score = c_score(c_opt)
            # g_opt = c_opt.to_graph()
        elif METHOD == "qiskit":
            c_opt = QISKIT_OPT._optimize(c.copy())
        print("Can convert from original graph back to circuit")
    except:
        print("Can NOT convert from original graph back to circuit")

    successes = 0
    for _ in tqdm(range(1000)):
        c = zx.generate.CNOT_HAD_PHASE_circuit(qubits=N_QUBITS, depth=DEPTH, clifford=False)
        g = c.to_graph()
        zx.full_reduce(g)
        try:
            c_opt = zx.Circuit.from_graph(g)
            successes += 1
        except:
            continue
    print(f"Number of successes: {successes}")
    """

    # The below tests the graph-likeness utilities
    for _ in tqdm(range(100),
                  desc="Verifying equality with [to_graph_like]..."):
        c = zx.generate.CNOT_HAD_PHASE_circuit(qubits=N_QUBITS,
                                               depth=DEPTH,
                                               clifford=False)
        g = c.to_graph()
        g1 = g.copy()
        to_graph_like(g1)
        zx.full_reduce(g1)
        c1 = zx.extract_circuit(g1.copy())
        assert (c.verify_equality(c1))
    print("[to_graph_like] appears to maintain equality!")