Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
bea6ab3
added files from hqs
David-Kreplin Dec 11, 2023
4bcb7e8
black format
David-Kreplin Dec 11, 2023
3944a6b
wip
David-Kreplin Dec 13, 2023
467bd96
first version of automatic selection is working
David-Kreplin Dec 22, 2023
ef9e341
modified parallel primitves
David-Kreplin Dec 22, 2023
ed5a58e
wip
David-Kreplin Jan 3, 2024
e52750c
wip
David-Kreplin Jan 11, 2024
8330894
wip
David-Kreplin Jan 16, 2024
345b079
wip
David-Kreplin Jan 16, 2024
3dbe713
wip
David-Kreplin Jan 17, 2024
51447b5
wip
David-Kreplin Jan 18, 2024
2926adc
cleaning
David-Kreplin Jan 18, 2024
670aaf0
wip
David-Kreplin Jan 24, 2024
126510d
Add more comments
David-Kreplin Feb 5, 2024
15bf55c
bug fix
David-Kreplin Feb 6, 2024
4622136
removed unimportant code
David-Kreplin Feb 6, 2024
994e364
fixed test
David-Kreplin Feb 6, 2024
1f57755
wip
David-Kreplin Feb 6, 2024
b8b4547
ip
David-Kreplin Feb 6, 2024
d366d7d
doc strings fixed
David-Kreplin Feb 6, 2024
b874498
added test for parallel execution
David-Kreplin Feb 7, 2024
80c6758
get everything working with fake backends
David-Kreplin Feb 7, 2024
89efa45
added more tests for automatic selection
David-Kreplin Feb 7, 2024
11f7c9b
add missng testjob
David-Kreplin Feb 7, 2024
16a602c
Merge branch 'develop' into hqs_integration
David-Kreplin Feb 12, 2024
13e1e5c
update off docu and dependencies
David-Kreplin Feb 12, 2024
ca7b813
deleted tests
David-Kreplin Feb 12, 2024
13e6af1
reset of regression_example
David-Kreplin Feb 12, 2024
6a739b6
merge with develop complete
David-Kreplin Jun 18, 2024
af83a71
Merge branch 'develop' into hqs_integration
David-Kreplin Jul 5, 2024
917187a
black
David-Kreplin Jul 5, 2024
7f5dd51
fixed testjobs
David-Kreplin Jul 5, 2024
1f90b90
adjust testjobs
David-Kreplin Jul 5, 2024
81d62bf
black
David-Kreplin Jul 5, 2024
5fa0fc0
remove value checks in tests, since they are not reproduceable
David-Kreplin Jul 10, 2024
e3b5464
black
David-Kreplin Jul 10, 2024
c9350c4
remove result check from test_parallel_primtives.py
David-Kreplin Jul 10, 2024
913fce0
cleaning of test
David-Kreplin Jul 10, 2024
0e57613
black
David-Kreplin Jul 10, 2024
aeee91e
update executor graphic
David-Kreplin Jul 10, 2024
8e158f0
Merge branch 'develop' into hqs_integration
David-Kreplin Jul 12, 2024
10ea8a0
update of the doc
David-Kreplin Jul 12, 2024
4ba9338
Merge branch 'develop' into hqs_integration
David-Kreplin Jul 12, 2024
abb2b86
fix of primitive
David-Kreplin Jul 12, 2024
87ca8ad
Merge branch 'hqs_integration' of github.com:David-Kreplin/squlearn i…
David-Kreplin Jul 12, 2024
444c21b
removed print statement
David-Kreplin Jul 12, 2024
09eb4a8
final run of black
David-Kreplin Jul 12, 2024
4740523
Merge branch 'develop' into hqs_integration
David-Kreplin Aug 19, 2024
40ee7f9
Merge branch 'develop' into hqs_integration
MoritzWillmann Sep 25, 2024
80fbf81
fix test
MoritzWillmann Sep 25, 2024
328a617
fix some stuff
MoritzWillmann Oct 1, 2024
2450b25
Merge branch 'develop' into hqs_integration
MoritzWillmann Oct 1, 2024
d449ea1
Update src/squlearn/util/executor.py
David-Kreplin Oct 9, 2024
9668503
Update src/squlearn/util/execution/backend_auto_selection.py
David-Kreplin Oct 9, 2024
a7e951f
Update src/squlearn/util/execution/backend_auto_selection.py
David-Kreplin Oct 9, 2024
29f76d9
Update src/squlearn/qnn/qnnr.py
David-Kreplin Oct 9, 2024
8e238a6
Update src/squlearn/qnn/qnnc.py
David-Kreplin Oct 9, 2024
05acb18
Update src/squlearn/qnn/lowlevel_qnn_qiskit.py
David-Kreplin Oct 9, 2024
c6baafe
merge develop
David-Kreplin Oct 9, 2024
3924ee4
fix in test
David-Kreplin Oct 9, 2024
2adcb05
renamed AutoSelBack
David-Kreplin Oct 10, 2024
5c7ee54
Merge branch 'develop' into hqs_integration
David-Kreplin Oct 10, 2024
57cb602
fixed merge
David-Kreplin Oct 10, 2024
0672f78
fix pyproject.toml
David-Kreplin Oct 10, 2024
36bf2d6
fix pyproject.toml v2
David-Kreplin Oct 10, 2024
782b884
fix pyproject.toml v3
David-Kreplin Oct 10, 2024
51239b8
update of testjob
David-Kreplin Oct 10, 2024
f43a6c3
black
David-Kreplin Oct 10, 2024
ba3c4d0
fix for testjobs
David-Kreplin Oct 10, 2024
ff7b8e9
fix test
David-Kreplin Oct 10, 2024
85511e5
rechange dependencies
MoritzWillmann Oct 11, 2024
4f75c86
remove IBMQuantum variable in the executor
David-Kreplin Oct 11, 2024
ad6c3fc
fix executor docstring
MoritzWillmann Oct 11, 2024
68115ba
black
MoritzWillmann Oct 11, 2024
851859c
add docstring for select_backend, remove comments
MoritzWillmann Oct 11, 2024
397ce93
rename function
MoritzWillmann Oct 11, 2024
faecce9
change ValueError to TypeError
MoritzWillmann Oct 11, 2024
1c9837f
fix if clauses
MoritzWillmann Oct 11, 2024
628df25
update parallel primitives
MoritzWillmann Oct 11, 2024
ec8178f
rename `parse_openqasm`
MoritzWillmann Oct 11, 2024
a7904d6
clean backend auto selection code
MoritzWillmann Oct 11, 2024
b933adf
black
MoritzWillmann Oct 11, 2024
3d50da9
fix in Qiskit lowleven QNN and fix of IBMQuantum variable in the exec…
David-Kreplin Oct 14, 2024
4b0bd63
merge
David-Kreplin Oct 14, 2024
ccee656
black
David-Kreplin Oct 14, 2024
92e1653
remove metric
MoritzWillmann Oct 14, 2024
30c041b
remove result comparison in parallel primitives
David-Kreplin Oct 14, 2024
4d23e56
make `heuristic` function and add tests
MoritzWillmann Oct 14, 2024
9e55c0d
Merge branch 'hqs_integration' of github.com:David-Kreplin/squlearn i…
MoritzWillmann Oct 14, 2024
0aa0e02
black
MoritzWillmann Oct 14, 2024
6d24227
black tests
MoritzWillmann Oct 14, 2024
5d67b92
rename remote and ibmquantum
MoritzWillmann Oct 14, 2024
c8a24fb
clean backend auto selection
MoritzWillmann Oct 15, 2024
0bb9d5d
add hqaa modes
MoritzWillmann Oct 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<img alt="sQUlearn" src="https://raw.githubusercontent.com/sQUlearn/squlearn/main/docs/_static/logo.png" />
</p>

sQUlearn is a user-friendly, NISQ-ready Python library for quantum machine learning (QML), designed for seamless integration with classical machine learning tools like scikit-learn. The library's dual-layer architecture serves both QML researchers and practitioners, enabling efficient prototyping, experimentation, and pipelining. sQUlearn provides a comprehensive toolset that includes both quantum kernel methods and quantum neural networks, along with features like customizable data encoding strategies, automated execution handling, and specialized kernel regularization techniques. By focusing on NISQ-compatibility and end-to-end automation, sQUlearn aims to bridge the gap between current quantum computing capabilities and practical machine learning applications.
sQUlearn is a user-friendly, NISQ-ready Python library for quantum machine learning (QML), designed for seamless integration with classical machine learning tools like scikit-learn. The library's dual-layer architecture serves both QML researchers and practitioners, enabling efficient prototyping, experimentation, and pipelining. sQUlearn provides a comprehensive tool set that includes both quantum kernel methods and quantum neural networks, along with features like customizable data encoding strategies, automated execution handling, and specialized kernel regularization techniques. By focusing on NISQ-compatibility and end-to-end automation, sQUlearn aims to bridge the gap between current quantum computing capabilities and practical machine learning applications.

sQUlearn offers scikit-learn compatible high-level interfaces for various kernel methods and QNNs. They build on top of the low-level interfaces of the QNN engine and the quantum kernel engine. The executor is used to run experiments on simulated and real backends of the Qiskit or PennyLane frameworks.

Expand Down Expand Up @@ -39,7 +39,7 @@ pip install .[examples]
```

## Contribute to sQUlearn
Thanks for considering to contribute to sQUlearn! Please read our [contribution guidelines](https://github.com/sQUlearn/squlearn/blob/main/.github/CONTRIBUTING.md) before you submit a pull request.
Thanks for considering contributing to sQUlearn! Please read our [contribution guidelines](https://github.com/sQUlearn/squlearn/blob/main/.github/CONTRIBUTING.md) before you submit a pull request.

---
## License
Expand All @@ -61,11 +61,6 @@ For general questions regarding sQUlearn, use the [GitHub Discussions](https://g
---
## Acknowledgements

This project was supported by the German Federal Ministry
of Economic Affairs and Climate Action through the
projects AutoQML (grant no. 01MQ22002A) and AQUAS
(grant no. 01MQ22003D), as well as the German Federal
Ministry of Education and Research through the project
H2Giga Degrad-EL3 (grant no. 03HY110D).
This project was supported by the German Federal Ministry of Economic Affairs and Climate Action through the projects AutoQML (grant no. 01MQ22002A) and AQUAS (grant no. 01MQ22003D), as well as the German Federal Ministry of Education and Research through the project H2Giga Degrad-EL3 (grant no. 03HY110D).

---
---
Binary file modified docs/_static/util/executor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,12 @@ def setup(app):

# intersphinx
intersphinx_mapping = {
"qiskit": ("https://docs.quantum.ibm.com/api/qiskit/", None),
"pennylane": ("https://docs.pennylane.ai/en/stable/", None),
"qiskit": ("https://docs.quantum.ibm.com/api/qiskit/1.1/", None),
"qiskit-aer": ("https://qiskit.github.io/qiskit-aer/", None),
"qiskit-ibm-runtime": ("https://docs.quantum.ibm.com/api/qiskit-ibm-runtime/0.27/", None),
"scipy": ("https://docs.scipy.org/doc/scipy/", None),
"sklearn": ("https://scikit-learn.org/stable/", None),
"sklearn": ("https://scikit-learn.org/1.4/", None),
}

suppress_warnings = ["myst.header", "config.cache"]
Expand Down
2 changes: 2 additions & 0 deletions docs/modules/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ Execution Tools
:template: class.rst

Executor
util.executor.ExecutorEstimator
util.executor.ExecutorSampler


Core
Expand Down
245 changes: 194 additions & 51 deletions docs/user_guide/executor.rst

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@ classifiers = [
]
keywords = ["quantum", "machine learning", "qml"]
dependencies = [
"bayesian-optimization>=1.4.3",
"dill>=0.3",
"numpy>=1.17,<2.0",
"qiskit>=0.43.0,<1.1.0",
"mapomatic>=0.10.0",
"networkx>=3.0",
"numpy>=1.17",
"pennylane>=0.34.0",
"qiskit>=0.43.0,<1.2.0",
"qiskit-aer>=0.12.0",
"qiskit-algorithms>=0.3.0",
"qiskit-ibm-runtime>=0.15.1",
"qiskit-ibm-runtime>=0.15.1,<0.28.0",
"qiskit-machine-learning>=0.6.1",
"pennylane>=0.34.0",
"scipy>=1.5",
"scikit-learn>=1.0,<1.4.2",
"bayesian-optimization>=1.4.3",
"tqdm>=4.0",
]
requires-python = ">=3.9"
Expand All @@ -60,6 +62,7 @@ examples = [
]
docs = [
"ipykernel",
"jupyter-sphinx",
"matplotlib>=3.5",
"myst-parser",
"nbsphinx",
Expand All @@ -69,7 +72,6 @@ docs = [
"sphinxcontrib-spelling",
"sphinx-rtd-theme<3.0.0",
"sphinx-sitemap",
"jupyter-sphinx",
]

[project.urls]
Expand Down
5 changes: 5 additions & 0 deletions src/squlearn/kernel/matrix/fidelity_kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ def __init__(
self._enc_circ = self._encoding_circuit.get_circuit(
self._feature_vector, self._parameter_vector
)

# Automatic select backend if not chosen
if not self._executor.backend_chosen:
self._enc_circ, _ = self._executor.select_backend(self._enc_circ)

if self._executor.is_statevector:
if self._parameter_vector is None:
self._quantum_kernel = FidelityStatevectorKernel(
Expand Down
1 change: 1 addition & 0 deletions src/squlearn/observables/observable_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def set_map(self, qubit_map: Union[list, dict], num_all_qubits: int):
qubits are mapped to the output qubits.
num_all_qubits (int): The total number of qubits in the system.
"""

self._qubit_map = qubit_map
self._num_all_qubits = num_all_qubits
self._is_mapped = True
Expand Down
13 changes: 12 additions & 1 deletion src/squlearn/qnn/base_qnn.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ class BaseQNN(BaseEstimator, ABC):
callback (Union[Callable, str, None], default=None): A callback for the optimization loop.
Can be either a Callable, "pbar" (which uses a :class:`tqdm.tqdm` process bar) or None.
If None, the optimizers (default) callback will be used.
primitive : The Qiskit primitive that is utilized in the qnn, if a Qiskit backend
is used in the executor (not supported for PennyLane backends)
Default primitive is the one specified in the executor initialization,
if nothing is specified, the estimator will used.
Possible values are ``"estimator"`` or ``"sampler"``.
"""

def __init__(
Expand All @@ -65,6 +70,7 @@ def __init__(
caching: bool = True,
pretrained: bool = False,
callback: Union[Callable, str, None] = None,
primitive: Union[str, None] = None,
**kwargs,
) -> None:
super().__init__()
Expand Down Expand Up @@ -117,6 +123,7 @@ def __init__(
self.caching = caching
self.pretrained = pretrained

self.primitive = primitive
self.executor = executor

self.shot_control = shot_control
Expand Down Expand Up @@ -324,7 +331,11 @@ def _fit(self, X, y, weights: np.ndarray = None) -> None:

def _initialize_lowlevel_qnn(self):
self._qnn = LowLevelQNN(
self.encoding_circuit, self.operator, self.executor, caching=self.caching
self.encoding_circuit,
self.operator,
self.executor,
caching=self.caching,
primitive=self.primitive,
)

def _validate_input(self, X, y, incremental, reset):
Expand Down
3 changes: 3 additions & 0 deletions src/squlearn/qnn/lowlevel_qnn.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ def __new__(
):

if executor.quantum_framework == "pennylane":
if "primitive" in kwargs:
RuntimeError("Warning: Primitive argument is not supported for PennyLane")
kwargs.pop("primitive")
return LowLevelQNNPennyLane(
parameterized_quantum_circuit, observable, executor, *args, **kwargs
)
Expand Down
70 changes: 60 additions & 10 deletions src/squlearn/qnn/lowlevel_qnn_qiskit.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

from .lowlevel_qnn_base import LowLevelQNNBase

import copy


class Expec:
"""Data structure that holds the set-up of derivative of the expectation value.
Expand Down Expand Up @@ -275,6 +277,9 @@ class LowLevelQNNQiskit(LowLevelQNNBase):
executor (Executor) : Executor that is used for the evaluation of the QNN
caching : Caching of the result for each `x`, `param`, `param_op` combination
(default = True)
primitive (str): Primitive that is used for the evaluation of the QNN. Possible values are
``"estimator"`` or ``"sampler"``. If None, the primitive is set according to the
executor. (default = None)

Attributes:
-----------
Expand All @@ -300,25 +305,65 @@ def __init__(
operator: Union[ObservableBase, list],
executor: Executor,
caching=True,
primitive: Union[str, None] = None,
) -> None:

parameterized_quantum_circuit = TranspiledEncodingCircuit(
parameterized_quantum_circuit, executor.backend
)
self.caching = caching

if executor.backend_chosen:
# Skip transpilation for parallel qpu execution
if not executor.qpu_parallelization:
parameterized_quantum_circuit = TranspiledEncodingCircuit(
parameterized_quantum_circuit, executor.backend
)
else:
# Automatically select backend (also returns a TranspiledEncodingCircuit except
# for parallel qpu execution)
parameterized_quantum_circuit, _ = executor.select_backend(
parameterized_quantum_circuit
)

super().__init__(parameterized_quantum_circuit, operator, executor)

self.caching = caching
self.operator = copy.deepcopy(operator)

# Set-Up Executor
if self._executor.optree_executor == "estimator":
self._estimator = self._executor.get_estimator()
self._sampler = None
else:
self._sampler = self._executor.get_sampler()
self._estimator = None
self._set_primitive(primitive)

# Initialize derivative classes
self._initilize_derivative()

def _set_primitive(self, primitive: Union[str, None] = None) -> None:
"""
Sets the primitive for evaluating the of the QNN.

Args:
primitive (str): Primitive that is used for the evaluation of the QNN.
Can be ``"estimator"`` or ``"sampler"``. If None, the primitive is set
according to the executor. (default = None)

"""
if primitive is None:
if self._executor.optree_executor == "estimator":
self._estimator = self._executor.get_estimator()
self._sampler = None
self._primitive = "estimator"
else:
self._sampler = self._executor.get_sampler()
self._estimator = None
self._primitive = "sampler"
else:
if primitive.lower() == "estimator":
self._estimator = self._executor.get_estimator()
self._sampler = None
self._primitive = "estimator"
elif primitive.lower() == "sampler":
self._sampler = self._executor.get_sampler()
self._estimator = None
self._primitive = "sampler"
else:
raise ValueError("Unknown primitive:", primitive)

def get_params(self, deep: bool = True) -> dict:
"""Returns the dictionary of the hyper-parameters of the QNN.

Expand All @@ -327,6 +372,7 @@ def get_params(self, deep: bool = True) -> dict:

"""
params = dict(num_qubits=self.num_qubits)
params["primitive"] = self._primitive

if deep:
params.update(self._pqc.get_params())
Expand Down Expand Up @@ -360,6 +406,10 @@ def set_params(self, **params) -> None:
f"Valid parameters are {sorted(valid_params)!r}."
)

if "primitive" in params:
self._set_primitive(params["primitive"])
params.pop("primitive")

# Set parameters of the PQC
dict_pqc = {}
for key, value in params.items():
Expand Down
5 changes: 5 additions & 0 deletions src/squlearn/qnn/qnnc.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ class QNNClassifier(BaseQNN, ClassifierMixin):
callback (Union[Callable, str, None], default=None): A callback for the optimization loop.
Can be either a Callable, "pbar" (which uses a :class:`tqdm.tqdm` process bar) or None.
If None, the optimizers (default) callback will be used.
primitive (Union[str,None], default=None): The primitive that is utilized in the qnn.
Default primitive is the one specified in the executor initialization, if nothing is
specified, the estimator will used. Possible values are ``"estimator"`` or
``"sampler"``.

See Also
--------
Expand Down Expand Up @@ -115,6 +119,7 @@ def __init__(
caching: bool = True,
pretrained: bool = False,
callback: Union[Callable, str, None] = "pbar",
primitive: Union[str, None] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
6 changes: 6 additions & 0 deletions src/squlearn/qnn/qnnr.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ class QNNRegressor(BaseQNN, RegressorMixin):
callback (Union[Callable, str, None], default=None): A callback for the optimization loop.
Can be either a Callable, "pbar" (which uses a :class:`tqdm.tqdm` process bar) or None.
If None, the optimizers (default) callback will be used.
primitive (Union[str,None], default=None): The primitive that is utilized in the qnn.
Default primitive is the one specified in the executor initialization, if nothing is
specified, the estimator will used. Possible values are ``"estimator"`` or
``"sampler"``.

See Also
--------
Expand Down Expand Up @@ -165,6 +169,7 @@ def __init__(
caching: bool = True,
pretrained: bool = False,
callback: Union[Callable, str, None] = "pbar",
primitive: Union[str, None] = None,
**kwargs,
) -> None:
super().__init__(
Expand All @@ -185,6 +190,7 @@ def __init__(
caching=caching,
pretrained=pretrained,
callback=callback,
primitive=primitive,
**kwargs,
)

Expand Down
9 changes: 9 additions & 0 deletions src/squlearn/util/execution/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from .backend_auto_selection import AutoSelectionBackend
from .parallel_estimator import ParallelEstimator
from .parallel_sampler import ParallelSampler

__all__ = [
"AutoSelectionBackend",
"ParallelEstimator",
"ParallelSampler",
]
Loading