Skip to content

Commit

Permalink
new example, minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
dakk committed Oct 26, 2023
1 parent e9c2a02 commit 9cd1dc9
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 73 deletions.
123 changes: 56 additions & 67 deletions docs/source/howitworks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,66 +14,55 @@ For instance, let assume we have the following function:

.. code-block:: python
def f_comp(n: Qint4) -> bool:
return n > 3 or n == 7
def f_comp(b: bool, n: Qint2) -> Qint2:
for i in range(3):
n += (1 if b else 2)
return n
If we compile the whole function to a quantum circuit, we obtain the following circuit, created by
this boolean expression `n.2 | n.3 | (n.0 & n.1 & n.2 & ~n.3)`:
If we compile the whole function to a quantum circuit, we obtain the following quantum circuit:

.. code-block:: text
f_comp
q_0: ───░─────────────────────■─────────────────
░ │
q_1: ───░─────────────────────■─────────────────
░ │
q_2: ───░──────■──────────────■─────────────────
░ │ │
q_3: ───░──────┼────■─────────┼─────────────────
░ ┌─┴─┐ │ ┌───┐ │
q_4: ───░────┤ X ├──┼──┤ X ├──┼─────────■───────
░ └───┘┌─┴─┐├───┤ │ │
q_5: ───░─────────┤ X ├┤ X ├──■─────────■───────
░ └───┘└───┘┌─┴─┐┌───┐ │
q_6: ───░───────────────────┤ X ├┤ X ├──■───────
░ └───┘└───┘┌─┴─┐┌───┐
q_7: ───░─────────────────────────────┤ X ├┤ X ├
░ └───┘└───┘
While if we decompose the function in 3 operations `n==7`, `n>3`, `a and b`, we obtain something like
the following circuit (qubit uncomputing is disabled to show the real number of gates):
q_0: ───░──────■────■────■────■────■────■────■─────────────────
░ │ ┌─┴─┐ │ ┌─┴─┐ │ │ │
q_1: ───░──────■──┤ X ├──■──┤ X ├──■────┼────┼────■────────────
░ │ └───┘ │ └───┘ │ │ │ │
q_2: ───░──────┼─────────┼─────────┼────┼────┼────┼────■───────
░ │ │ │ ┌─┴─┐ │ ┌─┴─┐ │
q_3: ───░──────┼─────────┼─────────┼──┤ X ├──┼──┤ X ├──┼───────
░ ┌─┴─┐ ┌─┴─┐ ┌─┴─┐└───┘┌─┴─┐└───┘┌─┴─┐┌───┐
q_4: ───░────┤ X ├─────┤ X ├─────┤ X ├─────┤ X ├─────┤ X ├┤ X ├
░ └───┘ └───┘ └───┘ └───┘ └───┘└───┘
.. code-block:: text
= > |
q_0: ─░─────────────■───░───────────────────────────░──────────────────────────
░ │ ░ ░
q_1: ─░─────────────■───░───────────────────────────░──────────────────────────
░ │ ░ ░
q_2: ─░─────────────■───░───■───────────────────────░──────────────────────────
░ │ ░ │ ░
q_3: ─░───■─────────┼───░───┼────■──────────────────░──────────────────────────
░ ┌─┴─┐┌───┐ │ ░ │ │ ░
q_4: ─░─┤ X ├┤ X ├──■───░───┼────┼──────────────────░──────────────────────────
░ └───┘└───┘┌─┴─┐ ░ │ │ ░
q_5: ─░───────────┤ X ├─░───┼────┼──────────────────░───■──────────────────────
░ └───┘ ░ │ │ ░ │
q_6: ─░─────────────────░───┼────┼──────────────────░───┼──────────────────────
░ ░ ┌─┴─┐ │ ┌───┐ ░ │
q_7: ─░─────────────────░─┤ X ├──┼──┤ X ├──■────────░───┼──────────────────────
░ ░ └───┘┌─┴─┐├───┤ │ ░ │
q_8: ─░─────────────────░──────┤ X ├┤ X ├──■────────░───┼──────────────────────
░ ░ └───┘└───┘┌─┴─┐┌───┐ ░ │
q_9: ─░─────────────────░────────────────┤ X ├┤ X ├─░───┼────■─────────────────
░ ░ └───┘└───┘ ░ ┌─┴─┐ │ ┌───┐
q_10: ─░─────────────────░───────────────────────────░─┤ X ├──┼──┤ X ├──■───────
░ ░ ░ └───┘┌─┴─┐├───┤ │
q_11: ─░─────────────────░───────────────────────────░──────┤ X ├┤ X ├──■───────
░ ░ ░ └───┘└───┘┌─┴─┐┌───┐
q_12: ─░─────────────────░───────────────────────────░────────────────┤ X ├┤ X ├
░ ░ ░ └───┘└───┘
While if we write three separate sums, compiling them separately, we obtain something like the
following circuit:

.. code-block:: text
q_0: ─░───■────■────■──────────────────░───■────■────■──────────────────░───■────■────■─────────────────
░ │ │ │ ░ │ │ │ ░ │ │ │
q_1: ─░───■────┼────┼────■─────────────░───┼────┼────┼──────────────────░───┼────┼────┼─────────────────
░ │ │ │ │ ░ │ │ │ ░ │ │ │
q_2: ─░───┼────┼────┼────┼────■────────░───┼────┼────┼──────────────────░───┼────┼────┼─────────────────
░ │ ┌─┴─┐ │ ┌─┴─┐ │ ░ │ │ │ ░ │ │ │
q_3: ─░───┼──┤ X ├──┼──┤ X ├──┼────────░───■────┼────┼────■─────────────░───┼────┼────┼─────────────────
░ ┌─┴─┐└───┘┌─┴─┐└───┘┌─┴─┐┌───┐ ░ │ │ │ │ ░ │ │ │
q_4: ─░─┤ X ├─────┤ X ├─────┤ X ├┤ X ├─░───┼────┼────┼────┼────■────────░───┼────┼────┼─────────────────
░ └───┘ └───┘ └───┘└───┘ ░ │ ┌─┴─┐ │ ┌─┴─┐ │ ░ │ │ │
q_5: ─░────────────────────────────────░───┼──┤ X ├──┼──┤ X ├──┼────────░───■────┼────┼────■────────────
░ ░ ┌─┴─┐└───┘┌─┴─┐└───┘┌─┴─┐┌───┐ ░ │ │ │ │
q_6: ─░────────────────────────────────░─┤ X ├─────┤ X ├─────┤ X ├┤ X ├─░───┼────┼────┼────┼────■───────
░ ░ └───┘ └───┘ └───┘└───┘ ░ │ ┌─┴─┐ │ ┌─┴─┐ │
q_7: ─░────────────────────────────────░────────────────────────────────░───┼──┤ X ├──┼──┤ X ├──┼───────
░ ░ ░ ┌─┴─┐└───┘┌─┴─┐└───┘┌─┴─┐┌───┐
q_8: ─░────────────────────────────────░────────────────────────────────░─┤ X ├─────┤ X ├─────┤ X ├┤ X ├
░ ░ ░ └───┘ └───┘ └───┘└───┘
As we can see from the circuit drawings, qlasskit approach needs half the number of qubits and approximately half the number of gates.


AST Traslator
Expand Down Expand Up @@ -117,17 +106,17 @@ The previous example function `f`, is translated to the following quantum circui

.. code-block:: text
q_0: ───────────────────
q_1: ───────────────────
q_2: ──■──────────────┼──
q_3: ──┼────■───────────
┌─┴─┐ ┌───┐ │
q_4: ┤ X ├──┼──┤ X ├────
───┘┌─┴─┐├───┤ │
q_5: ─────┤ X ├┤ X ├────
└───┘└───┘┌─┴─┐
q_6: ───────────────┤ X ├
└───
q_0: ──────────────────────────────────────────────■──────────
q_1: ──────────────────────────────────────────────■──────────
┌───┐ ┌───┐┌───┐ ┌───┐
q_2: ┤ X ├────┼────────■────┤ X ├┤ X ├─────────────┼─────┤ X ├
├───┤ └───┘├───┤ │ └───┘
q_3: ┤ X ├────┼────────┼──────■──┤ X ├─────────────┼──────────
└───┘ │ ┌─┴─┐└───┘ │ │
q_4: ─────────┼────────┼────┤ X ├─────────┼─────────┼──────────
───┴───┐ │ └─┬─┘ │ ┌───┴────
q_5: ─────┤ Rx(π) ├────■──────┼───────────■─────┤ Rx(-π) ├────
└──────┘┌───┴───┐ │ ┌───┴────┐└────────┘
q_6: ──────────────┤ Rx(π) ├──■───────┤ Rx(-π) ├───────────────
└───────┘ └────────┘
35 changes: 35 additions & 0 deletions examples/ex1_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from qiskit import QuantumCircuit

from qlasskit import Qint2, qlassf

INTSIZ = 2

@qlassf
def f1(b: bool, n: Qint2) -> Qint2:
return n + (1 if b else 2)

@qlassf
def f_comp(b: bool, n: Qint2) -> Qint2:
for i in range(3):
n += (1 if b else 2)
return n


print(f_comp.expressions)
gate = f_comp.gate()
qc = QuantumCircuit(gate.num_qubits)
qc.barrier(label="f_comp")
qc.append(gate, list(range(gate.num_qubits)))
print(qc.decompose().draw("text"))
print(qc.decompose().count_ops())


gate1 = f1.gate()
qc = QuantumCircuit(gate.num_qubits*3)

for i in range(3):
qc.barrier(label="=")
qc.append(gate1, [0] + list(range(1+i * INTSIZ, 1+i*INTSIZ+INTSIZ*2)))

print(qc.decompose().draw("text"))
print(qc.decompose().count_ops())
4 changes: 2 additions & 2 deletions qlasskit/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from sympy import Symbol
from sympy.logic import ITE, And, Implies, Not, Or, Xor
from sympy.logic.boolalg import Boolean, BooleanFalse, BooleanTrue
from sympy.logic.boolalg import Boolean, BooleanFalse, BooleanTrue #, to_anf

from .. import QCircuit
from ..ast2logic.typing import Arg, Args, BoolExpList
Expand Down Expand Up @@ -84,8 +84,8 @@ def __init__(self):
pass

def _symplify_exp(self, exp):
# exp = simplify_logic(exp)
exp = optimizer(exp)
# exp = to_anf(exp, deep=False)
return exp

def compile(
Expand Down
7 changes: 4 additions & 3 deletions qlasskit/compiler/tweedledumcompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,12 @@ def twcircuit_to_qcircuit(twc):
class TweedledumCompiler(Compiler):
"""Compile using tweedledum synthesis library"""

def compile(self, name, args: Args, returns: Arg, exprs: BoolExpList) -> QCircuit:
def compile(self, name, args: Args, returns: Arg, exprs: BoolExpList) -> QCircuit: # noqa: C901
exprs = [(symb, self._symplify_exp(exp)) for symb, exp in exprs]

_logic_network = sympy_to_logic_network(name, args, returns, exprs)

sy = xag_synth(_logic_network)
sy = parity_decomp(sy)
# print(exprs)
# print(sy)

qc = QCircuit(sy.num_qubits(), native=sy)
Expand Down Expand Up @@ -127,6 +125,9 @@ def compile(self, name, args: Args, returns: Arg, exprs: BoolExpList) -> QCircui
qc.x(u)
qb.append(u)

if op == "rx":
op = "x"
angle = None
qc.mctrl_gate(op, qb[0:-1], qb[-1], angle)

for u, pol in qubits:
Expand Down
2 changes: 1 addition & 1 deletion qlasskit/qcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def __init__(self, num_qubits=0, name="qc", native=None):

for x in range(num_qubits):
self.qubit_map[f"q{x}"] = x

self.__native = native

def get_key_by_index(self, i: int):
Expand Down
5 changes: 5 additions & 0 deletions test/test_qlassf_for_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ def test_for_1it(self):
f = "def test(a: Qint2) -> Qint2:\n\tfor x in range(1):\n\t\ta += 1\n\treturn a"
qf = qlassf(f, to_compile=COMPILATION_ENABLED)
compute_and_compare_results(self, qf)

def test_for_4it(self):
f = "def test(a: Qint2) -> Qint2:\n\tfor x in range(4):\n\t\ta += 1\n\treturn a"
qf = qlassf(f, to_compile=COMPILATION_ENABLED)
compute_and_compare_results(self, qf)

def test_for_3it(self):
f = "def test(a: Qint2) -> Qint2:\n\tfor i in range(3):\n\t\ta += i\n\treturn a"
Expand Down

0 comments on commit 9cd1dc9

Please sign in to comment.