Skip to content

Commit 8cabe62

Browse files
authored
Merge branch 'main' into VFF_PR
2 parents 07437ed + ae3c240 commit 8cabe62

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+752
-246
lines changed

.pylintdict

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ deterministically
112112
diag
113113
dicts
114114
diederik
115+
dill
115116
dimensionality
116117
dir
117118
discretization
@@ -122,6 +123,7 @@ disp
122123
distro
123124
dobsicek
124125
docstring
126+
docstrings
125127
doi
126128
dok
127129
dp
@@ -519,6 +521,7 @@ seealso
519521
semidefinite
520522
sep
521523
serializable
524+
serializablemodelmixin
522525
shalev
523526
shanno
524527
shende
@@ -657,3 +660,4 @@ zz
657660
φ_i
658661
φ_ij
659662
Δ
663+
π

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
[![License](https://img.shields.io/github/license/qiskit-community/qiskit-machine-learning.svg?)](https://opensource.org/licenses/Apache-2.0) <!--- long-description-skip-begin -->
44
[![Current Release](https://img.shields.io/github/release/qiskit-community/qiskit-machine-learning.svg?logo=Qiskit)](https://github.com/qiskit-community/qiskit-machine-learning/releases)
55
[![Build Status](https://github.com/qiskit-community/qiskit-machine-learning/actions/workflows/main.yml/badge.svg)](https://github.com/qiskit-community/qiskit-machine-learning/actions?query=workflow%3A"Machine%20Learning%20Unit%20Tests"+branch%3Amain+event%3Apush)
6-
[![Monthly downloads](https://img.shields.io/pypi/dm/qiskit-machine-learning.svg)](https://pypi.org/project/qiskit-machine-learning/)
76
[![Coverage Status](https://coveralls.io/repos/github/qiskit-community/qiskit-machine-learning/badge.svg?branch=main)](https://coveralls.io/github/qiskit-community/qiskit-machine-learning?branch=main)
87
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/qiskit-machine-learning)
8+
[![Monthly downloads](https://img.shields.io/pypi/dm/qiskit-machine-learning.svg)](https://pypi.org/project/qiskit-machine-learning/)
99
[![Total downloads](https://static.pepy.tech/badge/qiskit-machine-learning)](https://pepy.tech/project/qiskit-machine-learning)
1010
[![Slack Organisation](https://img.shields.io/badge/slack-chat-blueviolet.svg?label=Qiskit%20Slack&logo=slack)](https://slack.qiskit.org)
11+
[![arXiv](https://img.shields.io/badge/arXiv-2505.17756-b31b1b.svg)](https://arxiv.org/abs/2505.17756)
12+
1113
<!--- long-description-skip-end -->
1214

1315
## What is Qiskit Machine Learning?
@@ -21,8 +23,9 @@ on the Qiskit software development kit. As of version `0.7`, Qiskit Machine Lear
2123
by IBM and the [Hartree Center](https://www.hartree.stfc.ac.uk/), part of the UK Science and
2224
Technologies Facilities Council (STFC).
2325

24-
A description of the library structure, features, and domain-specific applications, can be found
25-
in a dedicated [ArXiv paper](https://arxiv.org/abs/2505.17756).
26+
> [!NOTE]
27+
> A description of the library structure, features, and domain-specific applications, can be found
28+
> in a dedicated [ArXiv paper](https://arxiv.org/abs/2505.17756).
2629
2730
The Qiskit Machine Learning framework aims to be:
2831

@@ -117,7 +120,7 @@ Learning module. Let's try an experiment using VQC (Variational Quantum Classifi
117120
train and test samples from a data set to see how accurately the test set can be classified.
118121

119122
```python
120-
from qiskit.circuit.library import TwoLocal, ZZFeatureMap
123+
from qiskit.circuit.library import n_local, zz_feature_map
121124
from qiskit_machine_learning.optimizers import COBYLA
122125
from qiskit_machine_learning.utils import algorithm_globals
123126

@@ -138,8 +141,8 @@ training_features, training_labels, test_features, test_labels = ad_hoc_data(
138141
training_size=training_size, test_size=test_size, n=feature_dim, gap=0.3
139142
)
140143

141-
feature_map = ZZFeatureMap(feature_dimension=feature_dim, reps=2, entanglement="linear")
142-
ansatz = TwoLocal(feature_map.num_qubits, ["ry", "rz"], "cz", reps=3)
144+
feature_map = zz_feature_map(feature_dimension=feature_dim, reps=2, entanglement="linear")
145+
ansatz = n_local(feature_map.num_qubits, ["ry", "rz"], "cz", reps=3)
143146
vqc = VQC(
144147
feature_map=feature_map,
145148
ansatz=ansatz,

docs/tutorials/09_saving_and_loading_models.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@
535535
"metadata": {},
536536
"outputs": [],
537537
"source": [
538-
"original_classifier.save(\"vqc_classifier.model\")"
538+
"original_classifier.to_dill(\"vqc_classifier.model\")"
539539
]
540540
},
541541
{
@@ -555,7 +555,7 @@
555555
"metadata": {},
556556
"outputs": [],
557557
"source": [
558-
"loaded_classifier = VQC.load(\"vqc_classifier.model\")"
558+
"loaded_classifier = VQC.from_dill(\"vqc_classifier.model\")"
559559
]
560560
},
561561
{

qiskit_machine_learning/algorithms/classifiers/qsvc.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This code is part of a Qiskit project.
22
#
3-
# (C) Copyright IBM 2021, 2024.
3+
# (C) Copyright IBM 2021, 2025.
44
#
55
# This code is licensed under the Apache License, Version 2.0. You may
66
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -34,13 +34,24 @@ class QSVC(SVC, SerializableModelMixin):
3434
Read more in the `scikit-learn user guide
3535
<https://scikit-learn.org/stable/modules/svm.html#svm-classification>`_.
3636
37-
**Example**
37+
Examples:
38+
.. code-block::
3839
39-
.. code-block::
40+
from qiskit_machine_learning.kernels import FidelityQuantumKernel
41+
from qiskit_machine_learning.algorithms import QSVC
42+
43+
kernel = FidelityQuantumKernel()
44+
qsvc = QSVC(quantum_kernel=kernel)
45+
qsvc.fit(X_train, y_train)
46+
y_pred = qsvc.predict(X_test)
47+
48+
# Save the trained model
49+
qsvc.to_dill('qsvc_model.dill')
50+
51+
# Load the model for later use
52+
loaded_qsvc = QSVC.from_dill('qsvc_model.dill')
53+
score = loaded_qsvc.score(X_test, y_test)
4054
41-
qsvc = QSVC(quantum_kernel=qkernel)
42-
qsvc.fit(sample_train,label_train)
43-
qsvc.predict(sample_test)
4455
"""
4556

4657
def __init__(self, *, quantum_kernel: Optional[BaseKernel] = None, **kwargs):

qiskit_machine_learning/algorithms/classifiers/vqc.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This code is part of a Qiskit project.
22
#
3-
# (C) Copyright IBM 2021, 2024.
3+
# (C) Copyright IBM 2021, 2025.
44
#
55
# This code is licensed under the Apache License, Version 2.0. You may
66
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -69,14 +69,14 @@ def __init__(
6969
If ``None`` is given, the number of qubits is derived from the
7070
feature map or ansatz. If neither of those is given, raises an exception.
7171
The number of qubits in the feature map and ansatz are adjusted to this
72-
number if required.
72+
number if required and possible (such adjustment is deprecated).
7373
feature_map: The (parametrized) circuit to be used as a feature map for the underlying
74-
QNN. If ``None`` is given, the :class:`~qiskit.circuit.library.ZZFeatureMap`
74+
QNN. If ``None`` is given, the :meth:`~qiskit.circuit.library.zz_feature_map`
7575
is used if the number of qubits is larger than 1. For a single qubit
76-
classification problem the :class:`~qiskit.circuit.library.ZFeatureMap`
76+
classification problem the :meth:`~qiskit.circuit.library.z_feature_map`
7777
is used by default.
7878
ansatz: The (parametrized) circuit to be used as an ansatz for the underlying QNN.
79-
If ``None`` is given then the :class:`~qiskit.circuit.library.RealAmplitudes`
79+
If ``None`` is given then the :meth:`~qiskit.circuit.library.real_amplitudes`
8080
circuit is used.
8181
loss: A target loss function to be used in training. Default value is ``cross_entropy``.
8282
optimizer: An instance of an optimizer or a callable to be used in training.
@@ -108,7 +108,7 @@ def __init__(
108108
"""
109109

110110
num_qubits, feature_map, ansatz = derive_num_qubits_feature_map_ansatz(
111-
num_qubits, feature_map, ansatz
111+
num_qubits, feature_map, ansatz, use_methods=True
112112
)
113113

114114
if output_shape is None:

qiskit_machine_learning/algorithms/inference/qbayesian.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This code is part of a Qiskit project.
22
#
3-
# (C) Copyright IBM 2023, 2024.
3+
# (C) Copyright IBM 2023, 2025.
44
#
55
# This code is licensed under the Apache License, Version 2.0. You may
66
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -19,7 +19,7 @@
1919
from qiskit import QuantumCircuit, ClassicalRegister
2020
from qiskit.quantum_info import Statevector
2121
from qiskit.circuit import Qubit
22-
from qiskit.circuit.library import GroverOperator
22+
from qiskit.circuit.library import grover_operator
2323
from qiskit.primitives import BaseSampler, Sampler, BaseSamplerV2, BaseSamplerV1
2424
from qiskit.transpiler.passmanager import BasePassManager
2525
from qiskit.result import QuasiDistribution
@@ -129,7 +129,7 @@ def __init__(
129129
# True if rejection sampling converged after limit
130130
self._converged = bool()
131131

132-
def _get_grover_op(self, evidence: Dict[str, int]) -> GroverOperator:
132+
def _get_grover_op(self, evidence: Dict[str, int]) -> QuantumCircuit:
133133
"""
134134
Constructs a Grover operator based on the provided evidence. The evidence is used to
135135
determine the "good states" that the Grover operator will amplify.
@@ -161,7 +161,7 @@ def _get_grover_op(self, evidence: Dict[str, int]) -> GroverOperator:
161161
oracle = Statevector(
162162
[int(format(i, f"0{num_qubits}b") in good_states) for i in range(2**num_qubits)]
163163
)
164-
return GroverOperator(oracle, state_preparation=self._circ)
164+
return grover_operator(oracle, state_preparation=self._circ)
165165

166166
def _run_circuit(self, circuit: QuantumCircuit) -> Dict[str, float]:
167167
"""Run the quantum circuit with the sampler."""
@@ -199,7 +199,7 @@ def _run_circuit(self, circuit: QuantumCircuit) -> Dict[str, float]:
199199
return counts
200200

201201
def __power_grover(
202-
self, grover_op: GroverOperator, evidence: Dict[str, int], k: int
202+
self, grover_op: QuantumCircuit, evidence: Dict[str, int], k: int
203203
) -> Tuple[QuantumCircuit, Set[Tuple[Qubit, int]]]:
204204
"""
205205
Applies the Grover operator to the quantum circuit 2^k times, measures the evidence qubits,

qiskit_machine_learning/algorithms/regressors/vqr.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This code is part of a Qiskit project.
22
#
3-
# (C) Copyright IBM 2021, 2024.
3+
# (C) Copyright IBM 2021, 2025.
44
#
55
# This code is licensed under the Apache License, Version 2.0. You may
66
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -52,13 +52,13 @@ def __init__(
5252
If ``None`` then the number of qubits is derived from the
5353
feature map or ansatz, but if neither of these are given an error is raised.
5454
The number of qubits in the feature map and ansatz are adjusted to this
55-
number if required.
55+
number if required and possible (such adjustment is deprecated).
5656
feature_map: The (parametrized) circuit to be used as a feature map for the underlying
57-
QNN. If ``None`` the :class:`~qiskit.circuit.library.ZZFeatureMap`
57+
QNN. If ``None`` the :meth:`~qiskit.circuit.library.zz_feature_map`
5858
is used if the number of qubits is larger than 1. For a single qubit regression
59-
problem the :class:`~qiskit.circuit.library.ZFeatureMap` is used by default.
59+
problem the :meth:`~qiskit.circuit.library.z_feature_map` is used by default.
6060
ansatz: The (parametrized) circuit to be used as an ansatz for the underlying
61-
QNN. If ``None`` then the :class:`~qiskit.circuit.library.RealAmplitudes`
61+
QNN. If ``None`` then the :meth:`~qiskit.circuit.library.real_amplitudes`
6262
circuit is used.
6363
observable: The observable to be measured in the underlying QNN. If ``None``,
6464
use the default :math:`Z^{\otimes num\_qubits}` observable.
@@ -94,7 +94,7 @@ def __init__(
9494
self._estimator = estimator
9595

9696
num_qubits, feature_map, ansatz = derive_num_qubits_feature_map_ansatz(
97-
num_qubits, feature_map, ansatz
97+
num_qubits, feature_map, ansatz, use_methods=True
9898
)
9999

100100
# construct circuit

qiskit_machine_learning/algorithms/serializable_model.py

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This code is part of a Qiskit project.
22
#
3-
# (C) Copyright IBM 2021, 2023.
3+
# (C) Copyright IBM 2021, 2025.
44
#
55
# This code is licensed under the Apache License, Version 2.0. You may
66
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -15,37 +15,70 @@
1515

1616
import dill
1717

18+
from ..utils.deprecation import issue_deprecation_msg
19+
1820

1921
class SerializableModelMixin:
2022
"""
21-
Provides convenient methods for saving and loading models.
23+
Provides convenient methods for saving and loading models via dill serialization.
24+
25+
.. warning::
26+
The legacy :meth:`save` and :meth:`load` methods are deprecated in v0.9.0
27+
and will be removed in a future release. Please use :meth:`to_dill`
28+
and :meth:`from_dill` respectively.
29+
2230
"""
2331

24-
def save(self, file_name: str) -> None:
32+
def to_dill(self, file_name: str) -> None:
2533
"""
2634
Saves this model to the specified file. Internally, the model is serialized via ``dill``.
2735
All parameters are saved, including a primitive instance that is referenced by internal
2836
objects. That means if a model is loaded from a file and is used, for instance, for
2937
inference, the same primitive will be used even if a cloud primitive was used.
3038
39+
.. warning::
40+
Replaces the deprecated :meth:`save` method.
41+
3142
Args:
32-
file_name: a file name or path where to save the model.
43+
file_name: Path where the serialized model will be written.
44+
45+
Example:
46+
.. code-block::
47+
48+
model.to_dill('model_state.dill')
3349
"""
3450
with open(file_name, "wb") as handler:
3551
dill.dump(self, handler)
3652

53+
def save(self, *args) -> None:
54+
"""Backwards compatibility with :meth:`to_dill`, deprecated in v0.9.0."""
55+
issue_deprecation_msg(
56+
msg="SerializableModelMixin.save() is deprecated.",
57+
version="0.9.0",
58+
remedy="Use the to_dill() method instead.",
59+
period="4 months",
60+
)
61+
self.to_dill(*args)
62+
3763
@classmethod
38-
def load(cls, file_name: str) -> Any:
64+
def from_dill(cls, file_name: str) -> Any:
3965
"""
40-
Loads a model from the file. If the loaded model is not an instance of the class whose
66+
Loads a model from a file. If the loaded model is not an instance of the class whose
4167
method was called, then a warning is raised. Nevertheless, the loaded model may be a valid
4268
model.
4369
70+
Replaces the deprecated :meth:`load` method.
71+
4472
Args:
45-
file_name: a file name or path to load a model from.
73+
file_name: Path to the dill file containing the serialized model.
4674
4775
Returns:
48-
A loaded model.
76+
An instance of the model loaded from disk.
77+
78+
Example:
79+
.. code-block::
80+
81+
loaded = MyModel.from_dill('model_state.dill')
4982
5083
Raises:
5184
TypeError: if a loaded model is not an instance of the expected class.
@@ -55,3 +88,14 @@ def load(cls, file_name: str) -> Any:
5588
if not isinstance(model, cls):
5689
raise TypeError(f"Loaded model is of class {type(model)}. Expected class: {cls}.")
5790
return model
91+
92+
@classmethod
93+
def load(cls, *args) -> Any:
94+
"""Backwards compatibility with :meth:`from_dill`, deprecated in v0.9.0."""
95+
issue_deprecation_msg(
96+
msg="SerializableModelMixin.load() is deprecated.",
97+
version="0.9.0",
98+
remedy="Use the from_dill() classmethod instead.",
99+
period="4 months",
100+
)
101+
return cls.from_dill(*args)

qiskit_machine_learning/circuit/library/__init__.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This code is part of a Qiskit project.
22
#
3-
# (C) Copyright IBM 2020, 2024.
3+
# (C) Copyright IBM 2020, 2025.
44
#
55
# This code is licensed under the Apache License, Version 2.0. You may
66
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -28,6 +28,7 @@
2828
:template: autosummary/class_no_inherited_members.rst
2929
3030
RawFeatureVector
31+
raw_feature_vector
3132
3233
Helper circuits
3334
---------------
@@ -38,12 +39,10 @@
3839
:template: autosummary/class_no_inherited_members.rst
3940
4041
QNNCircuit
42+
qnn_circuit
4143
"""
4244

43-
from .raw_feature_vector import RawFeatureVector
44-
from .qnn_circuit import QNNCircuit
45+
from .raw_feature_vector import RawFeatureVector, raw_feature_vector
46+
from .qnn_circuit import QNNCircuit, qnn_circuit
4547

46-
__all__ = [
47-
"RawFeatureVector",
48-
"QNNCircuit",
49-
]
48+
__all__ = ["RawFeatureVector", "raw_feature_vector", "QNNCircuit", "qnn_circuit"]

0 commit comments

Comments
 (0)