Skip to content

Commit

Permalink
Bqm export (#13)
Browse files Browse the repository at this point in the history
* add pyqubo optional dep

* add pyqubo deps and doc placeholder

* mocking to_bqm

* bqm feature implementation and testing

* add sampling to bqm testing

* add int mul test, fix qlasskit export

* fix to_bqm exporter and bqm testing

* fix bqm exporting

* fix bqm export bit order

* upgrade test suite for bqm

* fix error logging messages, update todo and readme, bump version, bqm example

* minor fixtures

* linter fix
  • Loading branch information
dakk authored Feb 15, 2024
1 parent 5923d00 commit bed2f1e
Show file tree
Hide file tree
Showing 21 changed files with 591 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
run: |
pip install sphinx sphinx_rtd_theme sphinx_rtd_dark_mode myst_nb
pip install pennylane==0.33.1 pennylane-lightning==0.33.1
pip install sympy qiskit-terra qiskit-aer matplotlib pylatexenc cirq
pip install sympy qiskit-terra qiskit-aer matplotlib pylatexenc cirq pyqubo
python setup.py install
- name: Sphinx build
run: |
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ This tool will be useful for any algorithm that relies on a 'blackbox' function

Qlasskit implements circuit / gate exporters for Qiskit, Cirq, Qasm, Sympy and Pennylane.

Qlasskit also support exporting to Binary Quadratic Models (bqm, ising and qubo) ready to be used in
quantum annealers, ising machines, simulators, etc.

```bash
pip install qlasskit
```
Expand Down
6 changes: 3 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
- [x] Separate tests in directories
- [x] Circuit decompilation
- [x] QuTip Support
- [x] Parameter bind (https://github.com/dakk/qlasskit/issues/10)
- [x] QUBO, Ising and BQM exporter


## Future features
Expand All @@ -113,7 +115,6 @@

### Abstraction support

- [ ] Parameter bind (https://github.com/dakk/qlasskit/issues/10)

### Tools

Expand All @@ -123,5 +124,4 @@

### Experiments

- [ ] Logic2FPGA backend
- [ ] Logic2QUBO / Logic2ISING
- [ ] Logic2FPGA backend
3 changes: 2 additions & 1 deletion docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ API
qlasskit.algorithms.grover.Grover
qlasskit.qcircuit.qcircuit.QCircuit
qlasskit.qcircuit.qcircuitwrapper.QCircuitWrapper
qlasskit.qcircuit.gates
qlasskit.qcircuit.gates
qlasskit.bqm.decode_samples
134 changes: 134 additions & 0 deletions docs/source/bqm.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Binary Quadratic Model: Qubo & Ising "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Any qlassf function can be transformed to a binary quadratic model using the `to_bqm` function. In this example we want factorize the number 15."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Vars: 14 \n",
"Interactions: 41\n"
]
}
],
"source": [
"from qlasskit import qlassf, Qint4, Qint3\n",
"\n",
"\n",
"@qlassf\n",
"def test_factor(a: Qint3, b: Qint3) -> Qint4:\n",
" return Qint4(15) - (a * b)\n",
"\n",
"\n",
"bqm = test_factor.to_bqm()\n",
"\n",
"print(\"Vars:\", bqm.num_variables, \"\\nInteractions:\", bqm.num_interactions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A qlassf function can also be exported as a QUBO model using `to_bqm('qubo')` or as an Ising model using `to_bqm('ising')`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"### Running on simulated sampler annealer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can run a simulated sampler annealer to minimize this function; qlasskit offer a `decode_samples` helper function that translates sample result to the high level types of qlasskit."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'a': 5, 'b': 3}\n"
]
}
],
"source": [
"import neal\n",
"from qlasskit.bqm import decode_samples\n",
"\n",
"sa = neal.SimulatedAnnealingSampler()\n",
"sampleset = sa.sample(bqm, num_reads=10)\n",
"decoded_samples = decode_samples(test_qubo, sampleset)\n",
"best_sample = min(decoded_samples, key=lambda x: x.energy)\n",
"print(best_sample.sample)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The result is 5 and 3 as expected (since 5 times 3 is equal to 15)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Running on DWave annealer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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
}
79 changes: 79 additions & 0 deletions docs/source/example_bqm_tsp.ipynb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/source/exporter.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@
],
"source": [
"# Disabled on docs for a depencency problem\n",
"#qc = hello_world.export(\"qutip\")\n",
"#qc.gates"
"# qc = hello_world.export(\"qutip\")\n",
"# qc.gates"
]
}
],
Expand Down
8 changes: 7 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ Qlasskit
====================================

Qlasskit is a Python library that allows quantum developers to write classical algorithms in pure
Python and translate them into unitary operators (gates) for use in quantum circuits.
Python and translate them into unitary operators (gates) for use in quantum circuits supporting a wide
range of quantum frameworks.

Qlasskit also support exporting to Binary Quadratic Models (bqm, ising and qubo) ready to be used in
quantum annealers, ising machines, simulators, etc.

.. toctree::
:maxdepth: 2
Expand All @@ -14,6 +18,7 @@ Python and translate them into unitary operators (gates) for use in quantum circ
parameters.ipynb
algorithms
exporter.ipynb
bqm.ipynb
api

.. toctree::
Expand All @@ -29,6 +34,7 @@ Python and translate them into unitary operators (gates) for use in quantum circ
example_deutsch_jozsa.ipynb
example_unitary_of_f.ipynb
example_big_circuit.ipynb
example_bqm_tsp.ipynb


Indices and tables
Expand Down
10 changes: 7 additions & 3 deletions docs/source/parameters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@
}
],
"source": [
"from qlasskit import qlassf, Parameter \n",
"from qlasskit import qlassf, Parameter\n",
"\n",
"\n",
"@qlassf\n",
"def test(a: Parameter[bool], b: bool) -> bool:\n",
" return a and b\n",
"\n",
"\n",
"qf = test.bind(a=True)\n",
"qf.expressions"
]
Expand Down Expand Up @@ -81,14 +83,16 @@
"source": [
"from qlasskit import Qlist, Qint2, Qint4\n",
"\n",
"\n",
"@qlassf\n",
"def test(a: Parameter[Qlist[Qint2, 4]], b: Qint4) -> Qint4:\n",
" s = Qint4(0)\n",
" for n in a:\n",
" s += n\n",
" return s + b\n",
"\n",
"qf = test.bind(a=[2,1,0,3])\n",
"\n",
"qf = test.bind(a=[2, 1, 0, 3])\n",
"qf.expressions"
]
},
Expand All @@ -110,7 +114,7 @@
}
],
"source": [
"qf.circuit().export().draw('mpl')"
"qf.circuit().export().draw(\"mpl\")"
]
}
],
Expand Down
5 changes: 3 additions & 2 deletions qlasskit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2023 Davide Gessa
# Copyright 2023-2024 Davide Gessa

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -13,14 +13,15 @@
# limitations under the License.
# isort:skip_file

__version__ = "0.1.12"
__version__ = "0.1.15"

from .qcircuit import QCircuit, SupportedFrameworks, SupportedFramework # noqa: F401
from .qlassfun import QlassF, qlassf, qlassfa # noqa: F401
from .ast2ast import ast2ast # noqa: F401
from .ast2logic import exceptions # noqa: F401
from .types import ( # noqa: F401, F403
const_to_qtype,
interpret_as_qtype,
Qtype,
Qint,
Qint2,
Expand Down
9 changes: 5 additions & 4 deletions qlasskit/ast2ast.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2023 Davide Gessa
# Copyright 2023-2024 Davide Gessa

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -137,7 +137,8 @@ def visit_Subscript(self, node):

if not isinstance(tup, ast.Tuple):
raise Exception(
"Not a tuple in ast2ast visit subscript with not constant _sval"
"Not a tuple in ast2ast visit subscript with not constant _sval: "
+ ast.dump(tup)
)

elts = tup.elts
Expand Down Expand Up @@ -402,15 +403,15 @@ def visit_For(self, node): # noqa: C901

def __call_range(self, node):
if not all([isinstance(a, ast.Constant) for a in node.args]):
raise Exception("not handled")
raise Exception("Range call on not constant arguments is not handled")

args = [a.value for a in node.args]
it = list(range(*args))
return it

def __call_len(self, node):
if len(node.args) != 1:
raise Exception("not handled")
raise Exception("Len only receives one argument")

args = self.__unroll_arg(node.args[0])
return ast.Constant(value=len(args))
Expand Down
Loading

0 comments on commit bed2f1e

Please sign in to comment.