Skip to content

Commit

Permalink
fast optimizer and big circuit example
Browse files Browse the repository at this point in the history
  • Loading branch information
dakk committed Dec 6, 2023
1 parent 64ebdfc commit 6ffdecb
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 16 deletions.
9 changes: 5 additions & 4 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
- [x] Int arithmetic: mod
- [x] Simon example
- [x] Deutsch-Jozsa example
- [x] Improve performance on big circuits

### Week 4: (11 Dec 23)

Expand All @@ -134,23 +135,23 @@

## Future features

- [ ] Int arithmetic: div
- [ ] Lambda
- [ ] Builtin function: map

### Language support

- [ ] Int arithmetic: div
- [ ] Lambda
- [ ] Builtin function: map
- [ ] Datatype: Char
- [ ] Datatype: Dict
- [ ] Datatype: Float
- [ ] Datatype: Enum
- [ ] While loop
- [ ] Recursion
- [ ] Parameter bind
- [ ] Float arithmetic

### Abstraction support

- [ ] Parameter bind
- [ ] Extract boolean expressions from quantum circuits

### Framwork support
Expand Down
74 changes: 74 additions & 0 deletions docs/source/example_big_circuit.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example: big circuits"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Qlasskit is capable of producing large circuit without any issue. The only thing that you have to do, is to use the `fastOptimizer`, since running CSE is too slow on large expressions lists.\n",
"\n",
"In the next example we are going to create a quantum circuit with 64 `Qint8` in input, and one `Qint8` in output, resulting on a circuit of ~1000 qubits and ~16000 gates in around 2 seconds."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"from qlasskit import Qint8, Qlist, boolopt, qlassfa\n",
"\n",
"@qlassfa(bool_optimizer=boolopt.fastOptimizer)\n",
"def test(message: Qlist[Qint8, 64]) -> Qint8:\n",
" h_val = Qint8(0)\n",
" for c in message:\n",
" h_val = ((h_val >> 4) + c) & 0xFF\n",
" return h_val"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"QCircuit test\t\tGates: 16540\t\tQubits: 1039\n"
]
}
],
"source": [
"print(test.circuit())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "qlasskit_310-env",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Python and translate them into unitary operators (gates) for use in quantum circ
example_simon.ipynb
example_deutsch_jozsa.ipynb
example_unitary_of_f.ipynb
example_big_circuit.ipynb


Indices and tables
Expand Down
6 changes: 5 additions & 1 deletion qlasskit/boolopt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@
# isort:skip_file

from .sympytransformer import SympyTransformer # noqa: F401
from .bool_optimizer import BoolOptimizerProfile, bestWorkingOptimizer # noqa: F401
from .bool_optimizer import ( # noqa: F401
BoolOptimizerProfile,
defaultOptimizer,
fastOptimizer,
)
14 changes: 12 additions & 2 deletions qlasskit/boolopt/bool_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def apply(self, exps):
return exps


bestWorkingOptimizer = BoolOptimizerProfile(
defaultOptimizer = BoolOptimizerProfile(
[
merge_expressions,
apply_cse,
Expand All @@ -95,7 +95,7 @@ def apply(self, exps):
)


bestWorkingOptimizerDebug = BoolOptimizerProfile(
defaultOptimizerDebug = BoolOptimizerProfile(
[
print_step("before"),
merge_expressions,
Expand All @@ -107,3 +107,13 @@ def apply(self, exps):
print_step("after"),
]
)


fastOptimizer = BoolOptimizerProfile(
[
remove_ITE(),
remove_Implies(),
transform_or2xor(),
transform_or2and(),
]
)
4 changes: 4 additions & 0 deletions qlasskit/qcircuit/qcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ def get_key_by_index(self, i: int):
if self.qubit_map[key] == i:
return key
raise Exception(f"Qubit with index {i} not found")

def __repr__(self):
""" Return a string representation of the QCircuit """
return f'QCircuit {self.name}\t\tGates: {self.num_gates}\t\tQubits: {self.num_qubits}'

def __contains__(self, key: Union[str, Symbol, int]):
"""Return True if the circuit contain a qubit with a given name/symbol"""
Expand Down
12 changes: 6 additions & 6 deletions qlasskit/qlassfun.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from .ast2ast import ast2ast
from .ast2logic import Arg, Args, BoolExpList, LogicFun, flatten, translate_ast
from .boolopt import BoolOptimizerProfile, bestWorkingOptimizer
from .boolopt import BoolOptimizerProfile, defaultOptimizer
from .boolopt.bool_optimizer import merge_expressions
from .boolquant import Q # noqa: F403, F401
from .compiler import SupportedCompiler, to_quantum
Expand Down Expand Up @@ -187,7 +187,7 @@ def from_function(
defs: List[LogicFun] = [],
to_compile: bool = True,
compiler: SupportedCompiler = "internal",
bool_optimizer: BoolOptimizerProfile = bestWorkingOptimizer,
bool_optimizer: BoolOptimizerProfile = defaultOptimizer,
uncompute: bool = True,
) -> "QlassF":
"""Create a QlassF from a function or a string containing a function
Expand All @@ -199,7 +199,7 @@ def from_function(
to_compile (boolean, optional): if True, compile to quantum circuit (default: True)
compiler (SupportedCompiler, optional): override default compiler (default: internal)
bool_optimizer (BoolOptimizerProfile, optional): override default optimizer
(default: bestWorkingOptimizer)
(default: defaultOptimizer)
uncompute (bool, optional): whenever uncompute input qubits during compilation
(default: True)
"""
Expand Down Expand Up @@ -228,7 +228,7 @@ def qlassf(
defs: List[QlassF] = [],
to_compile: bool = True,
compiler: SupportedCompiler = "internal",
bool_optimizer: BoolOptimizerProfile = bestWorkingOptimizer,
bool_optimizer: BoolOptimizerProfile = defaultOptimizer,
uncompute: bool = True,
) -> QlassF:
"""Decorator / function creating a QlassF object
Expand All @@ -240,7 +240,7 @@ def qlassf(
to_compile (boolean, optional): if True, compile to quantum circuit (default: True)
compiler (SupportedCompiler, optional): override default compiler (default: internal)
bool_optimizer (BoolOptimizerProfile, optional): override default optimizer
(default: bestWorkingOptimizer)
(default: defaultOptimizer)
uncompute (bool, optional): whenever uncompute input qubits during compilation
(default: True)
"""
Expand All @@ -262,7 +262,7 @@ def qlassfa(
defs: List[QlassF] = [],
to_compile: bool = True,
compiler: SupportedCompiler = "internal",
bool_optimizer: BoolOptimizerProfile = bestWorkingOptimizer,
bool_optimizer: BoolOptimizerProfile = defaultOptimizer,
uncompute: bool = True,
):
"""Decorator with parameters for qlassf"""
Expand Down
4 changes: 3 additions & 1 deletion qlasskit/types/qint.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def mul(cls, tleft: TExp, tright: TExp) -> TExp: # noqa: C901
m = len(tright[1])

if n != m:
raise Exception("Mul works only on same size Qint")
raise Exception(f"Mul works only on same size Qint: {n} != {m}")

product = [False] * (n + m)

Expand Down Expand Up @@ -210,6 +210,8 @@ def mul(cls, tleft: TExp, tright: TExp) -> TExp: # noqa: C901
return Qint12, product
elif (n + m) > 12 and (n + m) <= 16:
return Qint16, product
elif (n + m) > 16:
return Qint16.crop((Qint16, product))

raise Exception(f"Mul result size is too big ({n+m})")

Expand Down
4 changes: 2 additions & 2 deletions test/test_qlassf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from parameterized import parameterized_class

from qlasskit import Qint, Qint2, Qint4, Qint12, QlassF, exceptions, qlassf
from qlasskit.boolopt.bool_optimizer import bestWorkingOptimizerDebug
from qlasskit.boolopt.bool_optimizer import defaultOptimizerDebug

from . import utils
from .utils import COMPILATION_ENABLED, ENABLED_COMPILERS, compute_and_compare_results
Expand All @@ -34,7 +34,7 @@ def test_debug_optimizer(self):
qf = qlassf(
"def t(a: bool) -> bool: return a",
to_compile=COMPILATION_ENABLED,
bool_optimizer=bestWorkingOptimizerDebug,
bool_optimizer=defaultOptimizerDebug,
)
compute_and_compare_results(self, qf)

Expand Down

0 comments on commit 6ffdecb

Please sign in to comment.