From 90aa3cc58e20551964c282151dc1b645b10ae000 Mon Sep 17 00:00:00 2001 From: woodsp-ibm Date: Thu, 5 Jun 2025 14:07:49 -0400 Subject: [PATCH 1/4] Deprecate BlueprintCircuit based circuit usage --- README.md | 6 +- .../algorithms/classifiers/vqc.py | 12 +- .../algorithms/inference/qbayesian.py | 10 +- .../algorithms/regressors/vqr.py | 12 +- .../circuit/library/__init__.py | 13 +- .../circuit/library/qnn_circuit.py | 118 +++++++++++++++++- .../circuit/library/raw_feature_vector.py | 81 +++++++++++- .../kernels/base_kernel.py | 16 ++- .../neural_networks/estimator_qnn.py | 39 +++--- .../neural_networks/sampler_qnn.py | 29 +++-- qiskit_machine_learning/optimizers/qnspsa.py | 8 +- qiskit_machine_learning/optimizers/spsa.py | 8 +- .../utils/adjust_num_qubits.py | 66 +++++++++- ...st_fidelity_quantum_kernel_pegasos_qsvc.py | 8 +- .../test_fidelity_quantum_kernel_qsvc.py | 6 +- .../test_neural_network_classifier.py | 20 +-- .../classifiers/test_pegasos_qsvc.py | 8 +- test/algorithms/classifiers/test_qsvc.py | 8 +- test/algorithms/classifiers/test_vqc.py | 17 +-- .../test_fidelity_quantum_kernel_qsvr.py | 6 +- .../test_neural_network_regressor.py | 12 +- test/algorithms/regressors/test_qsvr.py | 6 +- test/algorithms/regressors/test_vqr.py | 7 +- test/circuit/library/test_qnn_circuit.py | 62 ++++++++- .../library/test_raw_feature_vector.py | 108 +++++++++++++++- test/connectors/test_torch_connector.py | 12 +- test/connectors/test_torch_networks.py | 12 +- test/gradients/test_estimator_gradient.py | 10 +- test/gradients/test_sampler_gradient.py | 12 +- .../test_fidelity_qkernel_trainer.py | 8 +- test/kernels/test_fidelity_qkernel.py | 8 +- .../test_fidelity_statevector_kernel.py | 8 +- .../test_trainable_fidelity_qkernel.py | 6 +- .../test_effective_dimension.py | 8 +- test/neural_networks/test_estimator_qnn_v1.py | 10 +- test/neural_networks/test_estimator_qnn_v2.py | 10 +- test/neural_networks/test_sampler_qnn.py | 12 +- test/optimizers/test_gradient_descent.py | 6 +- test/optimizers/test_optimizers.py | 4 +- test/optimizers/test_spsa.py | 10 +- .../test_compute_uncompute.py | 6 +- .../test_compute_uncompute_v2.py | 6 +- test/utils/test_adjust_num_qubits.py | 10 +- 43 files changed, 641 insertions(+), 203 deletions(-) diff --git a/README.md b/README.md index 7266f4f4d..abf1d65d0 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Learning module. Let's try an experiment using VQC (Variational Quantum Classifi train and test samples from a data set to see how accurately the test set can be classified. ```python -from qiskit.circuit.library import TwoLocal, ZZFeatureMap +from qiskit.circuit.library import n_local, zz_feature_map from qiskit_machine_learning.optimizers import COBYLA from qiskit_machine_learning.utils import algorithm_globals @@ -138,8 +138,8 @@ training_features, training_labels, test_features, test_labels = ad_hoc_data( training_size=training_size, test_size=test_size, n=feature_dim, gap=0.3 ) -feature_map = ZZFeatureMap(feature_dimension=feature_dim, reps=2, entanglement="linear") -ansatz = TwoLocal(feature_map.num_qubits, ["ry", "rz"], "cz", reps=3) +feature_map = zz_feature_map(feature_dimension=feature_dim, reps=2, entanglement="linear") +ansatz = n_local(feature_map.num_qubits, ["ry", "rz"], "cz", reps=3) vqc = VQC( feature_map=feature_map, ansatz=ansatz, diff --git a/qiskit_machine_learning/algorithms/classifiers/vqc.py b/qiskit_machine_learning/algorithms/classifiers/vqc.py index caffee3b4..159659401 100644 --- a/qiskit_machine_learning/algorithms/classifiers/vqc.py +++ b/qiskit_machine_learning/algorithms/classifiers/vqc.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -69,14 +69,14 @@ def __init__( If ``None`` is given, the number of qubits is derived from the feature map or ansatz. If neither of those is given, raises an exception. The number of qubits in the feature map and ansatz are adjusted to this - number if required. + number if required and possible (such adjustment is deprecated). feature_map: The (parametrized) circuit to be used as a feature map for the underlying - QNN. If ``None`` is given, the :class:`~qiskit.circuit.library.ZZFeatureMap` + QNN. If ``None`` is given, the :meth:`~qiskit.circuit.library.zz_feature_map` is used if the number of qubits is larger than 1. For a single qubit - classification problem the :class:`~qiskit.circuit.library.ZFeatureMap` + classification problem the :meth:`~qiskit.circuit.library.z_feature_map` is used by default. ansatz: The (parametrized) circuit to be used as an ansatz for the underlying QNN. - If ``None`` is given then the :class:`~qiskit.circuit.library.RealAmplitudes` + If ``None`` is given then the :meth:`~qiskit.circuit.library.real_amplitudes` circuit is used. loss: A target loss function to be used in training. Default value is ``cross_entropy``. optimizer: An instance of an optimizer or a callable to be used in training. @@ -108,7 +108,7 @@ def __init__( """ num_qubits, feature_map, ansatz = derive_num_qubits_feature_map_ansatz( - num_qubits, feature_map, ansatz + num_qubits, feature_map, ansatz, use_methods=True ) if output_shape is None: diff --git a/qiskit_machine_learning/algorithms/inference/qbayesian.py b/qiskit_machine_learning/algorithms/inference/qbayesian.py index 425f76b5a..4e8d02255 100644 --- a/qiskit_machine_learning/algorithms/inference/qbayesian.py +++ b/qiskit_machine_learning/algorithms/inference/qbayesian.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2023, 2024. +# (C) Copyright IBM 2023, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,7 +19,7 @@ from qiskit import QuantumCircuit, ClassicalRegister from qiskit.quantum_info import Statevector from qiskit.circuit import Qubit -from qiskit.circuit.library import GroverOperator +from qiskit.circuit.library import grover_operator from qiskit.primitives import BaseSampler, Sampler, BaseSamplerV2, BaseSamplerV1 from qiskit.transpiler.passmanager import BasePassManager from qiskit.result import QuasiDistribution @@ -129,7 +129,7 @@ def __init__( # True if rejection sampling converged after limit self._converged = bool() - def _get_grover_op(self, evidence: Dict[str, int]) -> GroverOperator: + def _get_grover_op(self, evidence: Dict[str, int]) -> QuantumCircuit: """ Constructs a Grover operator based on the provided evidence. The evidence is used to determine the "good states" that the Grover operator will amplify. @@ -161,7 +161,7 @@ def _get_grover_op(self, evidence: Dict[str, int]) -> GroverOperator: oracle = Statevector( [int(format(i, f"0{num_qubits}b") in good_states) for i in range(2**num_qubits)] ) - return GroverOperator(oracle, state_preparation=self._circ) + return grover_operator(oracle, state_preparation=self._circ) def _run_circuit(self, circuit: QuantumCircuit) -> Dict[str, float]: """Run the quantum circuit with the sampler.""" @@ -199,7 +199,7 @@ def _run_circuit(self, circuit: QuantumCircuit) -> Dict[str, float]: return counts def __power_grover( - self, grover_op: GroverOperator, evidence: Dict[str, int], k: int + self, grover_op: QuantumCircuit, evidence: Dict[str, int], k: int ) -> Tuple[QuantumCircuit, Set[Tuple[Qubit, int]]]: """ Applies the Grover operator to the quantum circuit 2^k times, measures the evidence qubits, diff --git a/qiskit_machine_learning/algorithms/regressors/vqr.py b/qiskit_machine_learning/algorithms/regressors/vqr.py index 1057223b1..94b72b5b6 100644 --- a/qiskit_machine_learning/algorithms/regressors/vqr.py +++ b/qiskit_machine_learning/algorithms/regressors/vqr.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -52,13 +52,13 @@ def __init__( If ``None`` then the number of qubits is derived from the feature map or ansatz, but if neither of these are given an error is raised. The number of qubits in the feature map and ansatz are adjusted to this - number if required. + number if required and possible (such adjustment is deprecated). feature_map: The (parametrized) circuit to be used as a feature map for the underlying - QNN. If ``None`` the :class:`~qiskit.circuit.library.ZZFeatureMap` + QNN. If ``None`` the :meth:`~qiskit.circuit.library.zz_feature_map` is used if the number of qubits is larger than 1. For a single qubit regression - problem the :class:`~qiskit.circuit.library.ZFeatureMap` is used by default. + problem the :meth:`~qiskit.circuit.library.z_feature_map` is used by default. ansatz: The (parametrized) circuit to be used as an ansatz for the underlying - QNN. If ``None`` then the :class:`~qiskit.circuit.library.RealAmplitudes` + QNN. If ``None`` then the :meth:`~qiskit.circuit.library.real_amplitudes` circuit is used. observable: The observable to be measured in the underlying QNN. If ``None``, use the default :math:`Z^{\otimes num\_qubits}` observable. @@ -94,7 +94,7 @@ def __init__( self._estimator = estimator num_qubits, feature_map, ansatz = derive_num_qubits_feature_map_ansatz( - num_qubits, feature_map, ansatz + num_qubits, feature_map, ansatz, use_methods=True ) # construct circuit diff --git a/qiskit_machine_learning/circuit/library/__init__.py b/qiskit_machine_learning/circuit/library/__init__.py index a1e317c2e..a3f312869 100644 --- a/qiskit_machine_learning/circuit/library/__init__.py +++ b/qiskit_machine_learning/circuit/library/__init__.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2020, 2024. +# (C) Copyright IBM 2020, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -28,6 +28,7 @@ :template: autosummary/class_no_inherited_members.rst RawFeatureVector + raw_feature_vector Helper circuits --------------- @@ -38,12 +39,10 @@ :template: autosummary/class_no_inherited_members.rst QNNCircuit + qnn_circuit """ -from .raw_feature_vector import RawFeatureVector -from .qnn_circuit import QNNCircuit +from .raw_feature_vector import RawFeatureVector, raw_feature_vector +from .qnn_circuit import QNNCircuit, qnn_circuit -__all__ = [ - "RawFeatureVector", - "QNNCircuit", -] +__all__ = ["RawFeatureVector", "raw_feature_vector", "QNNCircuit", "qnn_circuit"] diff --git a/qiskit_machine_learning/circuit/library/qnn_circuit.py b/qiskit_machine_learning/circuit/library/qnn_circuit.py index 7385a8f46..5658c3dd2 100644 --- a/qiskit_machine_learning/circuit/library/qnn_circuit.py +++ b/qiskit_machine_learning/circuit/library/qnn_circuit.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2023, 2024. +# (C) Copyright IBM 2023, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -21,11 +21,115 @@ from qiskit_machine_learning import QiskitMachineLearningError from ...utils import derive_num_qubits_feature_map_ansatz +from ...utils.deprecation import issue_deprecation_msg + + +def qnn_circuit( + num_qubits: int | None = None, + feature_map: QuantumCircuit | None = None, + ansatz: QuantumCircuit | None = None, +): + """ + The qnn_circuit creates a QuantumCircuit that is a composition of a feature map + and an ansatz circuit. Also returned are the feature map and ansatz parameters for + use for inputs and weights as needed for a neural network, such as + :class:`~qiskit-machine-learning.neural_networks.SamplerQNN`. + + If only the number of qubits is provided the :meth:`~qiskit.circuit.library.real_amplitudes` + ansatz and the :meth:`~qiskit.circuit.library.zz_feature_map` feature map are used. If the + number of qubits is 1 the :meth:`~qiskit.circuit.library.z_feature_map` is used. If only a + feature map is provided, the :meth:`~qiskit.circuit.library.real_amplitudes` ansatz with the + corresponding number of qubits is used. If only an ansatz is provided the + :meth:`~qiskit.circuit.library.zz_feature_map` with the corresponding number of qubits is used. + + At least one parameter has to be provided. If a feature map and an ansatz is provided, the + number of qubits must be the same. + + Example: + + .. code-block:: python + + from qiskit_machine_learning.circuit.library import qnn_circuit + qnn_qc, fm_params, anz_params = qnn_circuit(2) + qnn_qc.draw(fold=60) + # ┌───┐┌─────────────┐ » + # q_0: ┤ H ├┤ P(2.0*x[0]) ├──■──» + # ├───┤├─────────────┤┌─┴─┐» + # q_1: ┤ H ├┤ P(2.0*x[1]) ├┤ X ├» + # └───┘└─────────────┘└───┘» + # « ┌───┐» + # «q_0: ──────────────────────────────────■──┤ H ├» + # « ┌──────────────────────────────┐┌─┴─┐├───┤» + # «q_1: ┤ P(2.0*(x[0] - π)*(x[1] - π)) ├┤ X ├┤ H ├» + # « └──────────────────────────────┘└───┘└───┘» + # « ┌─────────────┐ » + # «q_0: ┤ P(2.0*x[0]) ├──■──────────────────────────────────» + # « ├─────────────┤┌─┴─┐┌──────────────────────────────┐» + # «q_1: ┤ P(2.0*x[1]) ├┤ X ├┤ P(2.0*(x[0] - π)*(x[1] - π)) ├» + # « └─────────────┘└───┘└──────────────────────────────┘» + # « ┌──────────┐ ┌──────────┐ ┌──────────┐» + # «q_0: ──■──┤ Ry(θ[0]) ├──■──┤ Ry(θ[2]) ├──■──┤ Ry(θ[4]) ├» + # « ┌─┴─┐├──────────┤┌─┴─┐├──────────┤┌─┴─┐├──────────┤» + # «q_1: ┤ X ├┤ Ry(θ[1]) ├┤ X ├┤ Ry(θ[3]) ├┤ X ├┤ Ry(θ[5]) ├» + # « └───┘└──────────┘└───┘└──────────┘└───┘└──────────┘» + # « ┌──────────┐ + # «q_0: ──■──┤ Ry(θ[6]) ├ + # « ┌─┴─┐├──────────┤ + # «q_1: ┤ X ├┤ Ry(θ[7]) ├ + # « └───┘└──────────┘ + print(fm_params) + # ParameterView([ParameterVectorElement(x[0]), ParameterVectorElement(x[1])]) + print(anz_params) + # ParameterView([ParameterVectorElement(θ[0]), ParameterVectorElement(θ[1]), + # ParameterVectorElement(θ[2]), ParameterVectorElement(θ[3]), + # ParameterVectorElement(θ[4]), ParameterVectorElement(θ[5]), + # ParameterVectorElement(θ[6]), ParameterVectorElement(θ[7])]) + + Although all arguments to qnn_circuit default to None at least one must be provided, + to determine the number of qubits from. + + If more than one is passed: + + 1) If num_qubits is provided the feature map and/or ansatz circuits supplied must be the + same number of qubits. + + 2) If num_qubits is not provided the feature_map and ansatz must be set to the same number + of qubits. + + Args: + num_qubits: Number of qubits, a positive integer. Optional if feature_map or ansatz is + provided, otherwise required. If not provided num_qubits defaults from the + sizes of feature_map and/or ansatz. + feature_map: A feature map. Optional if num_qubits or ansatz is provided, otherwise + required. If not provided defaults to + :meth:`~qiskit.circuit.library.zz_feature_map` or + :meth:`~qiskit.circuit.library.z_feature_map` if num_qubits is determined + to be 1. + ansatz: An ansatz. Optional if num_qubits or feature_map is provided, otherwise + required. If not provided defaults to + :meth:`~qiskit.circuit.library.real_amplitudes`. + + Returns: + The composed feature map and ansatz circuit, the feature map parameters and the + ansatz parameters. + + Raises: + QiskitMachineLearningError: If a valid number of qubits cannot be derived from the \ + provided input arguments. + """ + # Check if circuit is constructed with valid configuration and set properties accordingly. + num_qubits, feature_map, ansatz = derive_num_qubits_feature_map_ansatz( + num_qubits, feature_map, ansatz, use_methods=True + ) + qc = QuantumCircuit(num_qubits) + qc.compose(feature_map, inplace=True) + qc.compose(ansatz, inplace=True) + return qc, feature_map.parameters, ansatz.parameters class QNNCircuit(BlueprintCircuit): """ - The QNN circuit is a blueprint circuit that wraps feature map and ansatz circuits. + (DEPRECATED) The QNN circuit is a blueprint circuit that wraps feature map and ansatz circuits. It can be used to simplify the composition of these two. If only the number of qubits is provided the :class:`~qiskit.circuit.library.RealAmplitudes` @@ -119,6 +223,16 @@ def __init__( """ super().__init__() + + issue_deprecation_msg( + msg="QNNCircuit, a BlueprintCircuit based class, is deprecated", + version="0.9.0", + remedy="Use qnn_circuit instead of QNNCircuit but note " + "that later adjustment of the number of qubits, or updating " + "the feature map and/or ansatz is not possible anymore.", + period="4 months", + ) + self._feature_map = feature_map self._ansatz = ansatz # Check if circuit is constructed with valid configuration and set properties accordingly. diff --git a/qiskit_machine_learning/circuit/library/raw_feature_vector.py b/qiskit_machine_learning/circuit/library/raw_feature_vector.py index bdb0cd460..6ce3a6bcd 100644 --- a/qiskit_machine_learning/circuit/library/raw_feature_vector.py +++ b/qiskit_machine_learning/circuit/library/raw_feature_vector.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2020, 2024. +# (C) Copyright IBM 2020, 2025 # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -24,8 +24,10 @@ ) from qiskit.circuit.library import BlueprintCircuit +from ...utils.deprecation import issue_deprecation_msg -class RawFeatureVector(BlueprintCircuit): + +def raw_feature_vector(feature_dimension: int) -> QuantumCircuit: """The raw feature vector circuit. This circuit acts as parameterized initialization for statevectors with ``feature_dimension`` @@ -41,6 +43,72 @@ class RawFeatureVector(BlueprintCircuit): Examples: + .. code-block:: + + from qiskit_machine_learning.circuit.library import RawFeatureVector + circuit = RawFeatureVector(4) + print(circuit.num_qubits) + # prints: 2 + + print(circuit.draw(output='text')) + # prints: + # ┌───────────────────────────────────────────────┐ + # q_0: ┤0 ├ + # │ Parameterizedinitialize(x[0],x[1],x[2],x[3]) │ + # q_1: ┤1 ├ + # └───────────────────────────────────────────────┘ + + print(circuit.ordered_parameters) + # prints: [Parameter(p[0]), Parameter(p[1]), Parameter(p[2]), Parameter(p[3])] + + import numpy as np + state = np.array([1, 0, 0, 1]) / np.sqrt(2) + bound = circuit.assign_parameters(state) + print(bound) + # prints: + # ┌───────────────────────────────────────────────┐ + # q_0: ┤0 ├ + # │ Parameterizedinitialize(0.70711,0,0,0.70711) │ + # q_1: ┤1 ├ + # └───────────────────────────────────────────────┘ + + Args: + feature_dimension: The feature dimension from which the number of + qubits is inferred as ``n_qubits = log2(feature_dim)`` + + Raises: + ValueError: If ``feature_dimension`` is not a power of 2. + + Returns: + The raw feature + """ + num_qubits = np.log2(feature_dimension) + if int(num_qubits) != num_qubits: + raise ValueError("feature_dimension must be a power of 2!") + + ordered_parameters = ParameterVector("x", feature_dimension) + placeholder = ParameterizedInitialize(ordered_parameters[:]) + qc = QuantumCircuit(num_qubits) + qc.append(placeholder, qc.qubits) + return qc + + +class RawFeatureVector(BlueprintCircuit): + """(DEPRECATED) The raw feature vector circuit. + + This circuit acts as parameterized initialization for statevectors with ``feature_dimension`` + dimensions, thus with ``log2(feature_dimension)`` qubits. The circuit contains a + placeholder instruction that can only be synthesized/defined when all parameters are bound. + + In ML, this circuit can be used to load the training data into qubit amplitudes. It does not + apply an kernel transformation (therefore, it is a "raw" feature vector). + + Since initialization is implemented via a ``QuantumCircuit.initialize()`` call, this circuit + can't be used with gradient based optimizers, one can see a warning that gradients can't be + computed. + + Examples: + .. code-block:: from qiskit_machine_learning.circuit.library import RawFeatureVector @@ -81,6 +149,15 @@ def __init__(self, feature_dimension: Optional[int]) -> None: """ super().__init__() + issue_deprecation_msg( + msg="RawFeatureVector, a BlueprintCircuit based class, is deprecated", + version="0.9.0", + remedy="Use raw_feature_vector instead but note that later " + "adjustment of the feature dimension (i,e updating num qubits) is not " + "possible anymore.", + period="4 months", + ) + self._ordered_parameters = ParameterVector("x") if feature_dimension is not None: self.feature_dimension = feature_dimension diff --git a/qiskit_machine_learning/kernels/base_kernel.py b/qiskit_machine_learning/kernels/base_kernel.py index 672a89679..f2dd886a6 100644 --- a/qiskit_machine_learning/kernels/base_kernel.py +++ b/qiskit_machine_learning/kernels/base_kernel.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2023. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -20,6 +20,8 @@ from qiskit import QuantumCircuit from qiskit.circuit.library import ZZFeatureMap +from ..utils.deprecation import issue_deprecation_msg + class BaseKernel(ABC): r""" @@ -54,6 +56,18 @@ def __init__(self, *, feature_map: QuantumCircuit = None, enforce_psd: bool = Tr Default ``True``. """ if feature_map is None: + # Note: when removing None it should be done in all the derived classes as well + # along with an appropriate update to the docstring in each case + issue_deprecation_msg( + msg="Passing None as a feature_map is deprecated", + version="0.9.0", + remedy="Pass a feature map with the required number of qubits to match " + "the features. Later any adjustment of the number of qubits will be " + "removed from Qiskit as circuits based on BlueprintCircuit, " + "like ZZFeatureMap to which this defaults, which could do this, " + "have been deprecated.", + period="4 months", + ) feature_map = ZZFeatureMap(2) self._num_features = feature_map.num_parameters diff --git a/qiskit_machine_learning/neural_networks/estimator_qnn.py b/qiskit_machine_learning/neural_networks/estimator_qnn.py index 99409afe1..4a70731a0 100644 --- a/qiskit_machine_learning/neural_networks/estimator_qnn.py +++ b/qiskit_machine_learning/neural_networks/estimator_qnn.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -49,38 +49,40 @@ class EstimatorQNN(NeuralNetwork): their expectation value(s). Quite often, a combined quantum circuit is used. Such a circuit is built from two circuits: a feature map, it provides input parameters for the network, and an ansatz (weight parameters). - In this case a :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` can be passed as - circuit to simplify the composition of a feature map and ansatz. - If a :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` is passed as circuit, the - input and weight parameters do not have to be provided, because these two properties are taken - from the :class:`~qiskit_machine_learning.circuit.library.QNNCircuit`. + In this case a :meth:`~qiskit_machine_learning.circuit.library.qnn_circuit` can be used to + simplify the composition of a feature map and ansatz. + Use of the :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` being passed as circuit, + the input and weight parameters do not have to be provided, because these two properties are taken + from the :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` is deprecated. Example: .. code-block:: from qiskit import QuantumCircuit - from qiskit.circuit.library import ZZFeatureMap, RealAmplitudes - from qiskit_machine_learning.circuit.library import QNNCircuit + from qiskit.circuit.library import zz_feature_map, real_amplitudes + from qiskit_machine_learning.circuit.library import qnn_circuit from qiskit_machine_learning.neural_networks import EstimatorQNN num_qubits = 2 # Using the QNNCircuit: - # Create a parametrized 2 qubit circuit composed of the default ZZFeatureMap feature map - # and RealAmplitudes ansatz. - qnn_qc = QNNCircuit(num_qubits) + # Create a parametrized 2 qubit circuit composed of the default zz_feature_map feature map + # and real_amplitudes ansatz. + qnn_qc, fm_params, anz_params = qnn_circuit(num_qubits) qnn = EstimatorQNN( - circuit=qnn_qc + circuit=qnn_qc, + input_params=fm_params, + weight_params=anz_params ) qnn.forward(input_data=[1, 2], weights=[1, 2, 3, 4, 5, 6, 7, 8]) # Explicitly specifying the ansatz and feature map: - feature_map = ZZFeatureMap(feature_dimension=num_qubits) - ansatz = RealAmplitudes(num_qubits=num_qubits) + feature_map = zz_feature_map(feature_dimension=num_qubits) + ansatz = real_amplitudes(num_qubits=num_qubits) qc = QuantumCircuit(num_qubits) qc.compose(feature_map, inplace=True) @@ -124,7 +126,7 @@ def __init__( :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` is passed, the ``input_params`` and ``weight_params`` do not have to be provided, because these two properties are taken from the - :class:`~qiskit_machine_learning.circuit.library.QNNCircuit`. + :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` (DEPRECATED). estimator: The estimator used to compute neural network's results. If ``None``, a default instance of the reference estimator, :class:`~qiskit.primitives.Estimator`, will be used. @@ -201,6 +203,13 @@ def __init__( self._observables = observables if isinstance(circuit, QNNCircuit): + issue_deprecation_msg( + msg="Using QNNCircuit here is deprecated", + version="0.9.0", + remedy="Use qnn_circuit (instead) of QNNCircuit and pass " + "explicitly the input and weight parameters.", + period="4 months", + ) self._input_params = list(circuit.input_parameters) self._weight_params = list(circuit.weight_parameters) else: diff --git a/qiskit_machine_learning/neural_networks/sampler_qnn.py b/qiskit_machine_learning/neural_networks/sampler_qnn.py index 43c91dc5c..dc4947f8f 100644 --- a/qiskit_machine_learning/neural_networks/sampler_qnn.py +++ b/qiskit_machine_learning/neural_networks/sampler_qnn.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -67,7 +67,7 @@ class SamplerQNN(NeuralNetwork): circuit to simplify the composition of a feature map and ansatz. If a :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` is passed as circuit, the input and weight parameters do not have to be provided, because these two properties are taken - from the :class:`~qiskit_machine_learning.circuit.library.QNNCircuit`. + from the :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` is deprecated. The output can be set up in different formats, and an optional post-processing step can be used to interpret or map the sampler's raw output in a particular context (e.g. mapping @@ -95,8 +95,8 @@ class SamplerQNN(NeuralNetwork): .. code-block:: python from qiskit import QuantumCircuit - from qiskit.circuit.library import ZZFeatureMap, RealAmplitudes - from qiskit_machine_learning.circuit.library import QNNCircuit + from qiskit.circuit.library import zz_feature_map, real_amplitudes + from qiskit_machine_learning.circuit.library import qnn_circuit from qiskit_machine_learning.neural_networks import SamplerQNN num_qubits = 2 @@ -105,12 +105,14 @@ class SamplerQNN(NeuralNetwork): def parity(x): return f"{bin(x)}".count("1") % 2 - # Example 1: Using the QNNCircuit class - # QNNCircuit automatically combines a feature map and an ansatz into a single circuit - qnn_qc = QNNCircuit(num_qubits) + # Example 1: Using the qnn_circuit + # qnn_circuit automatically combines a feature map and an ansatz into a single circuit + qnn_qc, fm_params, anz_params = qnn_circuit(num_qubits) qnn = SamplerQNN( circuit=qnn_qc, # Note that this is a QNNCircuit instance + input_params=fm_params, + weight_params=anz_params, interpret=parity, output_shape=2 # Reshape by the number of classical registers ) @@ -120,8 +122,8 @@ def parity(x): # Example 2: Explicitly specifying the feature map and ansatz # Create a feature map and an ansatz separately - feature_map = ZZFeatureMap(feature_dimension=num_qubits) - ansatz = RealAmplitudes(num_qubits=num_qubits) + feature_map = zz_feature_map(feature_dimension=num_qubits) + ansatz = real_amplitudes(num_qubits=num_qubits) # Compose the feature map and ansatz manually (otherwise done within QNNCircuit) qc = QuantumCircuit(num_qubits) @@ -174,7 +176,7 @@ def __init__( :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` is passed, the `input_params` and `weight_params` do not have to be provided, because these two properties are taken from the - :class:`~qiskit_machine_learning.circuit.library.QNNCircuit`. + :class:`~qiskit_machine_learning.circuit.library.QNNCircuit` (DEPRECATED). sampler: The sampler primitive used to compute the neural network's results. If ``None`` is given, a default instance of the reference sampler defined by :class:`~qiskit.primitives.Sampler` will be used. @@ -241,6 +243,13 @@ def __init__( self._org_circuit = circuit if isinstance(circuit, QNNCircuit): + issue_deprecation_msg( + msg="Using QNNCircuit here is deprecated", + version="0.9.0", + remedy="Use qnn_circuit (instead) of QNNCircuit and pass " + "explicitly the input and weight parameters.", + period="4 months", + ) self._input_params = list(circuit.input_parameters) self._weight_params = list(circuit.weight_parameters) else: diff --git a/qiskit_machine_learning/optimizers/qnspsa.py b/qiskit_machine_learning/optimizers/qnspsa.py index 3d2b91381..9ffbd9edb 100644 --- a/qiskit_machine_learning/optimizers/qnspsa.py +++ b/qiskit_machine_learning/optimizers/qnspsa.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -56,18 +56,18 @@ class QNSPSA(SPSA): Examples: This short example runs QN-SPSA for the ground state calculation of the ``Z ^ Z`` - observable where the ansatz is a ``PauliTwoDesign`` circuit. + observable where the ansatz is a ``pauli_two_design`` circuit. .. code-block:: python import numpy as np from qiskit_machine_learning.optimizers import QNSPSA - from qiskit.circuit.library import PauliTwoDesign + from qiskit.circuit.library import pauli_two_design from qiskit.primitives import Estimator, Sampler from qiskit.quantum_info import Pauli # problem setup - ansatz = PauliTwoDesign(2, reps=1, seed=2) + ansatz = pauli_two_design(2, reps=1, seed=2) observable = Pauli("ZZ") initial_point = np.random.random(ansatz.num_parameters) diff --git a/qiskit_machine_learning/optimizers/spsa.py b/qiskit_machine_learning/optimizers/spsa.py index 08146ed5d..331f6ffe1 100644 --- a/qiskit_machine_learning/optimizers/spsa.py +++ b/qiskit_machine_learning/optimizers/spsa.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2018, 2024. +# (C) Copyright IBM 2018, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -83,17 +83,17 @@ class SPSA(Optimizer): Examples: This short example runs SPSA for the ground state calculation of the ``Z ^ Z`` - observable where the ansatz is a ``PauliTwoDesign`` circuit. + observable where the ansatz is a ``pauli_two_design`` circuit. .. code-block:: python import numpy as np from qiskit_machine_learning.optimizers import SPSA - from qiskit.circuit.library import PauliTwoDesign + from qiskit.circuit.library import pauli_two_design from qiskit.primitives import Estimator from qiskit.quantum_info import SparsePauliOp - ansatz = PauliTwoDesign(2, reps=1, seed=2) + ansatz = pauli_two_design(2, reps=1, seed=2) observable = SparsePauliOp("ZZ") initial_point = np.random.random(ansatz.num_parameters) estimator = Estimator() diff --git a/qiskit_machine_learning/utils/adjust_num_qubits.py b/qiskit_machine_learning/utils/adjust_num_qubits.py index 84ae8eb85..7b0825a32 100644 --- a/qiskit_machine_learning/utils/adjust_num_qubits.py +++ b/qiskit_machine_learning/utils/adjust_num_qubits.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -16,8 +16,10 @@ from qiskit import QuantumCircuit from qiskit.circuit.library import RealAmplitudes, ZFeatureMap, ZZFeatureMap +from qiskit.circuit.library import real_amplitudes, z_feature_map, zz_feature_map from ..exceptions import QiskitMachineLearningError +from ..utils.deprecation import issue_deprecation_msg # pylint: disable=invalid-name @@ -25,10 +27,13 @@ def derive_num_qubits_feature_map_ansatz( num_qubits: int | None = None, feature_map: QuantumCircuit | None = None, ansatz: QuantumCircuit | None = None, + use_methods: bool = False, ) -> Tuple[int, QuantumCircuit, QuantumCircuit]: """ Derives a correct number of qubits, feature map, and ansatz from the parameters. + With `use_methods` set False (default): + If the number of qubits is not ``None``, then the feature map and ansatz are adjusted to this number of qubits if required. If such an adjustment fails, an error is raised. Also, if the feature map or ansatz or both are ``None``, then :class:`~qiskit.circuit.library.ZZFeatureMap` @@ -42,12 +47,30 @@ def derive_num_qubits_feature_map_ansatz( :class:`~qiskit.circuit.library.ZZFeatureMap` or :class:`~qiskit.circuit.library.RealAmplitudes` are created respectively. + With `use_methods` set True: + + If the number of qubits is not ``None``, then the feature map and ansatz are adjusted to this + number of qubits if required. If such an adjustment fails, an error is raised. Also, if the + feature map or ansatz or both are ``None``, then :meth:`~qiskit.circuit.library.zz_feature_map` + and :meth:`~qiskit.circuit.library.real_amplitudes` are created respectively. If there's just + one qubit, :meth:`~qiskit.circuit.library.z_feature_map` is created instead. + + If the number of qubits is ``None``, then the number of qubits is derived from the feature map + or ansatz. Both the feature map and ansatz in this case must have the same number of qubits. + If the number of qubits of the feature map is not the same as the number of qubits of + the ansatz, an error is raised. If only one of the feature map and ansatz are ``None``, then + :meth:`~qiskit.circuit.library.zz_feature_map` or :class:`~qiskit.circuit.library.rea_amplitudes` + are created respectively. + If all the parameters are none an error is raised. Args: num_qubits: Number of qubits. feature_map: A feature map. ansatz: An ansatz. + use_methods: True (default) use deprecated BlueprintBased circuits such + as ZZFeatureMap, ZFeatureMap and RealAmplitudes. When False uses the + method "replacements" that provide back immutable circuits. Returns: A tuple of number of qubits, feature map, and ansatz. All are not none. @@ -56,6 +79,19 @@ def derive_num_qubits_feature_map_ansatz( QiskitMachineLearningError: If correct values can not be derived from the parameters. """ + if not use_methods: + issue_deprecation_msg( + msg="Using BlueprintCircuit based classes is deprecated", + version="0.9.0", + remedy="Use QnnCircuit (instead) of QNNCircuit or is you " + "are using this method directly set use_methods to True. " + "When using methods later adjustment of the number of qubits is not " + "possible and if not as circuits based on BlueprintCircuit, " + "like ZZFeatureMap to which this defaults, which could do this, " + "have been deprecated.", + period="4 months", + ) + # check num_qubits, feature_map, and ansatz if num_qubits in (0, None) and feature_map is None and ansatz is None: raise QiskitMachineLearningError( @@ -67,12 +103,22 @@ def derive_num_qubits_feature_map_ansatz( if feature_map.num_qubits != num_qubits: _adjust_num_qubits(feature_map, "feature map", num_qubits) else: - feature_map = ZFeatureMap(num_qubits) if num_qubits == 1 else ZZFeatureMap(num_qubits) + if use_methods: + feature_map = ( + z_feature_map(num_qubits) if num_qubits == 1 else zz_feature_map(num_qubits) + ) + else: + feature_map = ( + ZFeatureMap(num_qubits) if num_qubits == 1 else ZZFeatureMap(num_qubits) + ) if ansatz is not None: if ansatz.num_qubits != num_qubits: _adjust_num_qubits(ansatz, "ansatz", num_qubits) else: - ansatz = RealAmplitudes(num_qubits) + if use_methods: + ansatz = real_amplitudes(num_qubits) + else: + ansatz = RealAmplitudes(num_qubits) else: if feature_map is not None and ansatz is not None: if feature_map.num_qubits != ansatz.num_qubits: @@ -83,10 +129,20 @@ def derive_num_qubits_feature_map_ansatz( num_qubits = feature_map.num_qubits elif feature_map is not None: num_qubits = feature_map.num_qubits - ansatz = RealAmplitudes(num_qubits) + if use_methods: + ansatz = real_amplitudes(num_qubits) + else: + ansatz = RealAmplitudes(num_qubits) else: num_qubits = ansatz.num_qubits - feature_map = ZFeatureMap(num_qubits) if num_qubits == 1 else ZZFeatureMap(num_qubits) + if use_methods: + feature_map = ( + z_feature_map(num_qubits) if num_qubits == 1 else zz_feature_map(num_qubits) + ) + else: + feature_map = ( + ZFeatureMap(num_qubits) if num_qubits == 1 else ZZFeatureMap(num_qubits) + ) return num_qubits, feature_map, ansatz diff --git a/test/algorithms/classifiers/test_fidelity_quantum_kernel_pegasos_qsvc.py b/test/algorithms/classifiers/test_fidelity_quantum_kernel_pegasos_qsvc.py index 123bf3aa6..e5ce4efc5 100644 --- a/test/algorithms/classifiers/test_fidelity_quantum_kernel_pegasos_qsvc.py +++ b/test/algorithms/classifiers/test_fidelity_quantum_kernel_pegasos_qsvc.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,7 +18,7 @@ from test import QiskitMachineLearningTestCase import numpy as np -from qiskit.circuit.library import ZFeatureMap +from qiskit.circuit.library import z_feature_map from sklearn.datasets import make_blobs from sklearn.preprocessing import MinMaxScaler @@ -40,7 +40,7 @@ def setUp(self): # number of steps performed during the training procedure self.tau = 100 - self.feature_map = ZFeatureMap(feature_dimension=self.q, reps=1) + self.feature_map = z_feature_map(feature_dimension=self.q, reps=1) sample, label = make_blobs( n_samples=20, n_features=2, centers=2, random_state=3, shuffle=True @@ -56,7 +56,7 @@ def setUp(self): # The same for a 4-dimensional example # number of qubits is equal to the number of features self.q_4d = 4 - self.feature_map_4d = ZFeatureMap(feature_dimension=self.q_4d, reps=1) + self.feature_map_4d = z_feature_map(feature_dimension=self.q_4d, reps=1) sample_4d, label_4d = make_blobs( n_samples=20, n_features=self.q_4d, centers=2, random_state=3, shuffle=True diff --git a/test/algorithms/classifiers/test_fidelity_quantum_kernel_qsvc.py b/test/algorithms/classifiers/test_fidelity_quantum_kernel_qsvc.py index c56ad53e5..8ebe01f77 100644 --- a/test/algorithms/classifiers/test_fidelity_quantum_kernel_qsvc.py +++ b/test/algorithms/classifiers/test_fidelity_quantum_kernel_qsvc.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,7 +18,7 @@ from test import QiskitMachineLearningTestCase import numpy as np -from qiskit.circuit.library import ZZFeatureMap +from qiskit.circuit.library import zz_feature_map from qiskit_machine_learning.utils import algorithm_globals from qiskit_machine_learning.algorithms import QSVC, SerializableModelMixin @@ -34,7 +34,7 @@ def setUp(self): algorithm_globals.random_seed = 10598 - self.feature_map = ZZFeatureMap(feature_dimension=2, reps=2) + self.feature_map = zz_feature_map(feature_dimension=2, reps=2) self.sample_train = np.asarray( [ diff --git a/test/algorithms/classifiers/test_neural_network_classifier.py b/test/algorithms/classifiers/test_neural_network_classifier.py index 4cb40dae8..428915f90 100644 --- a/test/algorithms/classifiers/test_neural_network_classifier.py +++ b/test/algorithms/classifiers/test_neural_network_classifier.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -25,7 +25,7 @@ import scipy from ddt import ddt, data, idata, unpack from qiskit.circuit import QuantumCircuit -from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap +from qiskit.circuit.library import real_amplitudes, zz_feature_map from scipy.optimize import minimize from qiskit_machine_learning.optimizers import COBYLA, L_BFGS_B, SPSA, Optimizer @@ -93,8 +93,8 @@ def test_classifier_with_estimator_qnn(self, opt, loss, cb_flag): callback, history = self._create_callback(cb_flag) num_inputs = 2 - feature_map = ZZFeatureMap(num_inputs) - ansatz = RealAmplitudes(num_inputs, reps=1) + feature_map = zz_feature_map(num_inputs) + ansatz = real_amplitudes(num_inputs, reps=1) qc = QuantumCircuit(num_inputs) qc.compose(feature_map, inplace=True) @@ -136,8 +136,8 @@ def _verify_callback_values(self, callback, history, num_weights): def _create_sampler_qnn(self, output_shape=2) -> tuple[SamplerQNN, int, int]: num_inputs = 2 - feature_map = ZZFeatureMap(num_inputs) - ansatz = RealAmplitudes(num_inputs, reps=1) + feature_map = zz_feature_map(num_inputs) + ansatz = real_amplitudes(num_inputs, reps=1) # construct circuit qc = QuantumCircuit(num_inputs) @@ -361,8 +361,8 @@ def test_save_load(self, qnn_type): labels = np.array([-1, -1, 1, 1]) num_qubits = 2 - feature_map = ZZFeatureMap(num_qubits) - ansatz = RealAmplitudes(num_qubits, reps=1) + feature_map = zz_feature_map(num_qubits) + ansatz = real_amplitudes(num_qubits, reps=1) qc = QuantumCircuit(num_qubits) qc.compose(feature_map, inplace=True) qc.compose(ansatz, inplace=True) @@ -508,8 +508,8 @@ def test_untrained(self): def test_callback_setter(self): """Test the callback setter.""" num_qubits = 2 - feature_map = ZZFeatureMap(num_qubits) - ansatz = RealAmplitudes(num_qubits) + feature_map = zz_feature_map(num_qubits) + ansatz = real_amplitudes(num_qubits) qc = QuantumCircuit(2) qc.compose(feature_map, inplace=True) qc.compose(ansatz, inplace=True) diff --git a/test/algorithms/classifiers/test_pegasos_qsvc.py b/test/algorithms/classifiers/test_pegasos_qsvc.py index 936ca2901..49ddcc255 100644 --- a/test/algorithms/classifiers/test_pegasos_qsvc.py +++ b/test/algorithms/classifiers/test_pegasos_qsvc.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -21,7 +21,7 @@ from sklearn.datasets import make_blobs from sklearn.preprocessing import MinMaxScaler -from qiskit.circuit.library import ZFeatureMap +from qiskit.circuit.library import z_feature_map from qiskit_machine_learning.utils import algorithm_globals from qiskit_machine_learning.algorithms import PegasosQSVC, SerializableModelMixin @@ -40,7 +40,7 @@ def setUp(self): # number of steps performed during the training procedure self.tau = 100 - self.feature_map = ZFeatureMap(feature_dimension=self.q, reps=1) + self.feature_map = z_feature_map(feature_dimension=self.q, reps=1) sample, label = make_blobs( n_samples=20, n_features=2, centers=2, random_state=3, shuffle=True @@ -56,7 +56,7 @@ def setUp(self): # The same for a 4-dimensional example # number of qubits is equal to the number of features self.q_4d = 4 - self.feature_map_4d = ZFeatureMap(feature_dimension=self.q_4d, reps=1) + self.feature_map_4d = z_feature_map(feature_dimension=self.q_4d, reps=1) sample_4d, label_4d = make_blobs( n_samples=20, n_features=self.q_4d, centers=2, random_state=3, shuffle=True diff --git a/test/algorithms/classifiers/test_qsvc.py b/test/algorithms/classifiers/test_qsvc.py index 5b543c783..5d7489873 100644 --- a/test/algorithms/classifiers/test_qsvc.py +++ b/test/algorithms/classifiers/test_qsvc.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,7 +19,7 @@ import numpy as np -from qiskit.circuit.library import ZZFeatureMap +from qiskit.circuit.library import zz_feature_map from qiskit_machine_learning.utils import algorithm_globals from qiskit_machine_learning.algorithms import QSVC, SerializableModelMixin from qiskit_machine_learning.kernels import FidelityQuantumKernel @@ -36,7 +36,7 @@ def setUp(self): algorithm_globals.random_seed = 10598 - self.feature_map = ZZFeatureMap(feature_dimension=2, reps=2) + self.feature_map = zz_feature_map(feature_dimension=2, reps=2) self.sample_train = np.asarray( [ @@ -97,7 +97,7 @@ def test_save_load(self): features = np.array([[0, 0], [0.1, 0.2], [1, 1], [0.9, 0.8]]) labels = np.array([0, 0, 1, 1]) - quantum_kernel = FidelityQuantumKernel(feature_map=ZZFeatureMap(2)) + quantum_kernel = FidelityQuantumKernel(feature_map=zz_feature_map(2)) classifier = QSVC(quantum_kernel=quantum_kernel) classifier.fit(features, labels) diff --git a/test/algorithms/classifiers/test_vqc.py b/test/algorithms/classifiers/test_vqc.py index dfa5ed88f..5f8c63445 100644 --- a/test/algorithms/classifiers/test_vqc.py +++ b/test/algorithms/classifiers/test_vqc.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2018, 2024. +# (C) Copyright IBM 2018, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -27,8 +27,8 @@ from sklearn.datasets import make_classification from sklearn.preprocessing import MinMaxScaler, OneHotEncoder -from qiskit import QuantumCircuit -from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap, ZFeatureMap +from qiskit.circuit.library import RealAmplitudes, ZFeatureMap +from qiskit.circuit.library import real_amplitudes, zz_feature_map, z_feature_map from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit_ibm_runtime import Session, SamplerV2 @@ -87,8 +87,8 @@ def setUp(self): # We want string keys to ensure DDT-generated tests have meaningful names. self.properties = { "cobyla": COBYLA(maxiter=25), - "real_amplitudes": RealAmplitudes(num_qubits=2, reps=1), - "zz_feature_map": ZZFeatureMap(2), + "real_amplitudes": real_amplitudes(num_qubits=2, reps=1), + "zz_feature_map": zz_feature_map(2), "binary": _create_dataset(6, 2), "multiclass": _create_dataset(10, 3), "no_one_hot": _create_dataset(6, 2, one_hot=False), @@ -327,6 +327,8 @@ def test_categorical(self): def test_circuit_extensions(self): """Test VQC when the number of qubits is different compared to the feature map/ansatz.""" + # Note: This first part is using the deprecated BlueprintCircuit based classes to + # ensure the auto-adjust continues to work as expected until its gone/removed. num_qubits = 2 classifier = VQC( num_qubits=num_qubits, @@ -336,12 +338,11 @@ def test_circuit_extensions(self): self.assertEqual(classifier.feature_map.num_qubits, num_qubits) self.assertEqual(classifier.ansatz.num_qubits, num_qubits) - qc = QuantumCircuit(1) with self.assertRaises(QiskitMachineLearningError): _ = VQC( num_qubits=num_qubits, - feature_map=qc, - ansatz=qc, + feature_map=z_feature_map(1), + ansatz=real_amplitudes(1), ) diff --git a/test/algorithms/regressors/test_fidelity_quantum_kernel_qsvr.py b/test/algorithms/regressors/test_fidelity_quantum_kernel_qsvr.py index 549c5ebaf..548308cb6 100644 --- a/test/algorithms/regressors/test_fidelity_quantum_kernel_qsvr.py +++ b/test/algorithms/regressors/test_fidelity_quantum_kernel_qsvr.py @@ -21,7 +21,7 @@ from sklearn.metrics import mean_squared_error from qiskit.primitives import Sampler -from qiskit.circuit.library import ZZFeatureMap +from qiskit.circuit.library import zz_feature_map from qiskit_machine_learning.utils import algorithm_globals from qiskit_machine_learning.algorithms import QSVR, SerializableModelMixin @@ -38,7 +38,7 @@ def setUp(self): algorithm_globals.random_seed = 10598 self.sampler = Sampler() - self.feature_map = ZZFeatureMap(feature_dimension=2, reps=2) + self.feature_map = zz_feature_map(feature_dimension=2, reps=2) self.sample_train = np.asarray( [ @@ -127,7 +127,7 @@ def test_save_load(self): features = np.array([[0, 0], [0.1, 0.1], [0.4, 0.4], [1, 1]]) labels = np.array([0, 0.1, 0.4, 1]) - quantum_kernel = FidelityQuantumKernel(feature_map=ZZFeatureMap(2)) + quantum_kernel = FidelityQuantumKernel(feature_map=zz_feature_map(2)) regressor = QSVR(quantum_kernel=quantum_kernel) regressor.fit(features, labels) diff --git a/test/algorithms/regressors/test_neural_network_regressor.py b/test/algorithms/regressors/test_neural_network_regressor.py index fb791167b..10c16dc09 100644 --- a/test/algorithms/regressors/test_neural_network_regressor.py +++ b/test/algorithms/regressors/test_neural_network_regressor.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -25,7 +25,7 @@ from scipy.optimize import minimize from qiskit.circuit import Parameter, QuantumCircuit -from qiskit.circuit.library import ZZFeatureMap, RealAmplitudes +from qiskit.circuit.library import zz_feature_map, real_amplitudes from qiskit_machine_learning.optimizers import COBYLA, L_BFGS_B, SPSA from qiskit_machine_learning.utils import algorithm_globals @@ -168,8 +168,8 @@ def test_save_load(self): labels = np.array([0, 0.1, 0.4, 1]) num_inputs = 2 - feature_map = ZZFeatureMap(num_inputs) - ansatz = RealAmplitudes(num_inputs) + feature_map = zz_feature_map(num_inputs) + ansatz = real_amplitudes(num_inputs) qc = QuantumCircuit(num_inputs) qc.compose(feature_map, inplace=True) qc.compose(ansatz, inplace=True) @@ -222,8 +222,8 @@ def test_untrained(self): def test_callback_setter(self): """Test the callback setter.""" num_inputs = 2 - feature_map = ZZFeatureMap(num_inputs) - ansatz = RealAmplitudes(num_inputs) + feature_map = zz_feature_map(num_inputs) + ansatz = real_amplitudes(num_inputs) qc = QuantumCircuit(num_inputs) qc.compose(feature_map, inplace=True) qc.compose(ansatz, inplace=True) diff --git a/test/algorithms/regressors/test_qsvr.py b/test/algorithms/regressors/test_qsvr.py index 7fab0dc75..f4cb2f6ad 100644 --- a/test/algorithms/regressors/test_qsvr.py +++ b/test/algorithms/regressors/test_qsvr.py @@ -20,7 +20,7 @@ import numpy as np from sklearn.metrics import mean_squared_error -from qiskit.circuit.library import ZZFeatureMap +from qiskit.circuit.library import zz_feature_map from qiskit_machine_learning.utils import algorithm_globals from qiskit_machine_learning.algorithms import QSVR, SerializableModelMixin from qiskit_machine_learning.exceptions import QiskitMachineLearningWarning @@ -35,7 +35,7 @@ def setUp(self): algorithm_globals.random_seed = 10598 - self.feature_map = ZZFeatureMap(feature_dimension=2, reps=2) + self.feature_map = zz_feature_map(feature_dimension=2, reps=2) self.sample_train = np.asarray( [ @@ -122,7 +122,7 @@ def test_save_load(self): features = np.array([[0, 0], [0.1, 0.1], [0.4, 0.4], [1, 1]]) labels = np.array([0, 0.1, 0.4, 1]) - quantum_kernel = FidelityQuantumKernel(feature_map=ZZFeatureMap(2)) + quantum_kernel = FidelityQuantumKernel(feature_map=zz_feature_map(2)) regressor = QSVR(quantum_kernel=quantum_kernel) regressor.fit(features, labels) diff --git a/test/algorithms/regressors/test_vqr.py b/test/algorithms/regressors/test_vqr.py index 926ecd940..6c66fba44 100644 --- a/test/algorithms/regressors/test_vqr.py +++ b/test/algorithms/regressors/test_vqr.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -17,7 +17,6 @@ import numpy as np from ddt import data, ddt from qiskit.circuit import Parameter, QuantumCircuit -from qiskit.circuit.library import ZZFeatureMap, RealAmplitudes from qiskit.primitives import Estimator from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager @@ -107,11 +106,11 @@ def test_properties(self): """Test properties of VQR.""" vqr = VQR(num_qubits=2) self.assertIsNotNone(vqr.feature_map) - self.assertIsInstance(vqr.feature_map, ZZFeatureMap) + self.assertIsInstance(vqr.feature_map, QuantumCircuit) self.assertEqual(vqr.feature_map.num_qubits, 2) self.assertIsNotNone(vqr.ansatz) - self.assertIsInstance(vqr.ansatz, RealAmplitudes) + self.assertIsInstance(vqr.ansatz, QuantumCircuit) self.assertEqual(vqr.ansatz.num_qubits, 2) self.assertEqual(vqr.num_qubits, 2) diff --git a/test/circuit/library/test_qnn_circuit.py b/test/circuit/library/test_qnn_circuit.py index 4e1596bd5..2f6b0abab 100644 --- a/test/circuit/library/test_qnn_circuit.py +++ b/test/circuit/library/test_qnn_circuit.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2023. +# (C) Copyright IBM 2023, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -14,11 +14,69 @@ import unittest from test import QiskitMachineLearningTestCase +from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import ZFeatureMap, ZZFeatureMap, RealAmplitudes from qiskit.circuit.library import PauliFeatureMap, EfficientSU2 +from qiskit.circuit.library import zz_feature_map, real_amplitudes +from qiskit.circuit.library import pauli_feature_map from qiskit_machine_learning import QiskitMachineLearningError -from qiskit_machine_learning.circuit.library import QNNCircuit +from qiskit_machine_learning.circuit.library import QNNCircuit, qnn_circuit + + +class TestQNNCircuitFunction(QiskitMachineLearningTestCase): + """Tests for the ``qnn_circuit`` circuit.""" + + def test_construction(self): + """Test construction of ``qnn_circuit``.""" + + circuit, fm_params, anz_params = qnn_circuit(num_qubits=2) + + with self.subTest("check resultant circuit built"): + self.assertEqual(circuit.num_qubits, 2) + self.assertEqual(len(fm_params), 2) + self.assertEqual(len(anz_params), 8) + + def test_construction_fails(self): + """Test the faulty construction""" + + # If no argument is passed a QiskitMachineLearningError is raised + with self.assertRaises(QiskitMachineLearningError): + qnn_circuit(feature_map=zz_feature_map(2), ansatz=real_amplitudes(1)) + + # If no argument is passed a QiskitMachineLearningError is raised + with self.assertRaises(QiskitMachineLearningError): + qnn_circuit() + + def test_num_qubit_construction(self): + """Test building the ``qnn_circuit`` with number of qubits.""" + + circuit, fm_params, anz_params = qnn_circuit(1) + + # If not otherwise specified, the defaults are a ZFeatureMap/ZZFeatureMap and a + # RealAmplitudes ansatz. + with self.subTest("check input configuration after the circuit is build"): + self.assertEqual(circuit.num_qubits, 1) + self.assertEqual(type(circuit), QuantumCircuit) + self.assertEqual(len(fm_params), 1) + self.assertEqual(len(anz_params), 4) + + def test_feature_map_construction(self): + """Test building the ``qnn_circuit`` with a feature map""" + + feature_map = pauli_feature_map(3) + circuit, fm_params, anz_params = qnn_circuit(feature_map=feature_map) + + with self.subTest("check number of qubits"): + self.assertEqual(circuit.num_qubits, 3) + self.assertEqual(len(fm_params), 3) + self.assertEqual(len(anz_params), 12) + + def test_construction_for_input_mismatch(self): + """Test the construction of ``qnn_circuit`` for input that does not match fails.""" + + with self.assertRaises(QiskitMachineLearningError): + qnn_circuit(num_qubits=4, feature_map=zz_feature_map(3), ansatz=real_amplitudes(2)) class TestQNNCircuit(QiskitMachineLearningTestCase): diff --git a/test/circuit/library/test_raw_feature_vector.py b/test/circuit/library/test_raw_feature_vector.py index 5b8ed9363..de312a143 100644 --- a/test/circuit/library/test_raw_feature_vector.py +++ b/test/circuit/library/test_raw_feature_vector.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2020, 2024. +# (C) Copyright IBM 2020, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,14 +19,116 @@ import numpy as np import qiskit from qiskit.circuit import QuantumCircuit -from qiskit.circuit.library import RealAmplitudes +from qiskit.circuit.library import RealAmplitudes, real_amplitudes from qiskit.exceptions import QiskitError from qiskit.quantum_info import Statevector from qiskit_machine_learning.optimizers import COBYLA from qiskit_machine_learning.utils import algorithm_globals from qiskit_machine_learning.algorithms import VQC -from qiskit_machine_learning.circuit.library import RawFeatureVector +from qiskit_machine_learning.circuit.library import RawFeatureVector, raw_feature_vector + + +class TestRawFeatureVectorFunction(QiskitMachineLearningTestCase): + """Test the ``raw_feature_vector`` returned circuit.""" + + def test_construction(self): + """Test creating the circuit works.""" + + circuit = raw_feature_vector(4) + + with self.subTest("check number of qubits"): + self.assertEqual(circuit.num_qubits, 2) + + with self.subTest("check parameters"): + self.assertEqual(len(circuit.parameters), 4) + + with self.subTest("check unrolling fails"): + with self.assertRaises(QiskitError): + _ = qiskit.transpile(circuit, basis_gates=["u", "cx"], optimization_level=0) + + def test_fully_bound(self): + """Test fully binding the circuit works.""" + + circuit = raw_feature_vector(8) + + params = np.random.random(8) + 1j * np.random.random(8) + params /= np.linalg.norm(params) + + bound = circuit.assign_parameters(params) + + ref = QuantumCircuit(3) + ref.initialize(params, ref.qubits) + + self.assertEqual(bound.decompose(), ref) + + # make sure that the bound circuit is a successful copy of the original circuit + self.assertEqual(circuit.num_qubits, bound.num_qubits) + + def test_partially_bound(self): + """Test partially binding the circuit works.""" + + circuit = raw_feature_vector(4) + params = circuit.parameters + + with self.subTest("single numeric value"): + circuit.assign_parameters({params[0]: 0.2}, inplace=True) + self.assertEqual(len(circuit.parameters), 3) + + with self.subTest("bound to another parameter"): + circuit.assign_parameters({params[1]: params[2]}, inplace=True) + self.assertEqual(len(circuit.parameters), 2) + + with self.subTest("test now fully bound circuit"): + bound = circuit.assign_parameters({params[2]: 0.4, params[3]: 0.8}) + ref = QuantumCircuit(2) + ref.initialize([0.2, 0.4, 0.4, 0.8], ref.qubits) + self.assertEqual(bound.decompose(), ref) + + # make sure that the bound circuit is a successful copy of the original circuit + self.assertEqual(circuit.num_qubits, bound.num_qubits) + + def test_usage_in_vqc(self): + """Test the circuit works in VQC.""" + + # specify quantum instance and random seed + algorithm_globals.random_seed = 12345 + + # construct data + num_samples = 10 + num_inputs = 4 + X = algorithm_globals.random.random( # pylint: disable=invalid-name + (num_samples, num_inputs) + ) + y = 1.0 * (np.sum(X, axis=1) <= 2) + while len(np.unique(y, axis=0)) == 1: + y = 1.0 * (np.sum(X, axis=1) <= 2) + y = np.array([y, 1 - y]).transpose() + + feature_map = raw_feature_vector(feature_dimension=num_inputs) + ansatz = real_amplitudes(feature_map.num_qubits, reps=1) + + vqc = VQC( + feature_map=feature_map, + ansatz=ansatz, + optimizer=COBYLA(maxiter=10), + ) + + vqc.fit(X, y) + score = vqc.score(X, y) + self.assertGreater(score, 0.5) + + def test_bind_after_composition(self): + """Test binding the parameters after the circuit was composed onto a larger one.""" + circuit = QuantumCircuit(2) + circuit.h([0, 1]) + + raw = raw_feature_vector(4) + circuit.append(raw, [0, 1]) + + bound = circuit.assign_parameters([1, 0, 0, 0]) + + self.assertTrue(Statevector.from_label("00").equiv(bound)) class TestRawFeatureVector(QiskitMachineLearningTestCase): diff --git a/test/connectors/test_torch_connector.py b/test/connectors/test_torch_connector.py index 68cb77c49..ec0707d6f 100644 --- a/test/connectors/test_torch_connector.py +++ b/test/connectors/test_torch_connector.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,7 +19,7 @@ import numpy as np from ddt import ddt, data, unpack, idata from qiskit import QuantumCircuit -from qiskit.circuit.library import RealAmplitudes, ZFeatureMap +from qiskit.circuit.library import real_amplitudes, z_feature_map from qiskit.quantum_info import SparsePauliOp from qiskit_machine_learning import QiskitMachineLearningError @@ -184,8 +184,8 @@ def test_sampler_qnn(self, num_qubits, sparse_connector, sparse_qnn, interpret): else: output_shape = None - fmap = ZFeatureMap(num_qubits, reps=1) - ansatz = RealAmplitudes(num_qubits, reps=1) + fmap = z_feature_map(num_qubits, reps=1) + ansatz = real_amplitudes(num_qubits, reps=1) qc = QuantumCircuit(num_qubits) qc.compose(fmap, inplace=True) qc.compose(ansatz, inplace=True) @@ -224,8 +224,8 @@ def test_sampler_qnn(self, num_qubits, sparse_connector, sparse_qnn, interpret): @unpack def test_estimator_qnn(self, num_qubits, observables): """Test TorchConnector on EstimatorQNN.""" - fmap = ZFeatureMap(num_qubits, reps=1) - ansatz = RealAmplitudes(num_qubits, reps=1) + fmap = z_feature_map(num_qubits, reps=1) + ansatz = real_amplitudes(num_qubits, reps=1) qc = QuantumCircuit(num_qubits) qc.compose(fmap, inplace=True) qc.compose(ansatz, inplace=True) diff --git a/test/connectors/test_torch_networks.py b/test/connectors/test_torch_networks.py index 52530c830..8913199a2 100644 --- a/test/connectors/test_torch_networks.py +++ b/test/connectors/test_torch_networks.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2023. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,7 +18,7 @@ from ddt import ddt, idata from qiskit import QuantumCircuit -from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap +from qiskit.circuit.library import real_amplitudes, zz_feature_map from qiskit_machine_learning.neural_networks import NeuralNetwork, EstimatorQNN, SamplerQNN from qiskit_machine_learning.connectors import TorchConnector @@ -56,8 +56,8 @@ def forward(self, x): def _create_estimator_qnn(self) -> EstimatorQNN: num_inputs = 2 - feature_map = ZZFeatureMap(num_inputs) - ansatz = RealAmplitudes(num_inputs, entanglement="linear", reps=1) + feature_map = zz_feature_map(num_inputs) + ansatz = real_amplitudes(num_inputs, entanglement="linear", reps=1) qc = QuantumCircuit(num_inputs) qc.append(feature_map, range(num_inputs)) @@ -78,8 +78,8 @@ def _create_sampler_qnn(self) -> SamplerQNN: def interpret(x): return f"{x:b}".count("1") % 2 - feature_map = ZZFeatureMap(num_inputs) - ansatz = RealAmplitudes(num_inputs, entanglement="linear", reps=1) + feature_map = zz_feature_map(num_inputs) + ansatz = real_amplitudes(num_inputs, entanglement="linear", reps=1) qc = QuantumCircuit(num_inputs) qc.append(feature_map, range(num_inputs)) diff --git a/test/gradients/test_estimator_gradient.py b/test/gradients/test_estimator_gradient.py index 9face3738..a36e39de7 100644 --- a/test/gradients/test_estimator_gradient.py +++ b/test/gradients/test_estimator_gradient.py @@ -21,7 +21,7 @@ from qiskit import QuantumCircuit from qiskit.circuit import Parameter -from qiskit.circuit.library import EfficientSU2, RealAmplitudes +from qiskit.circuit.library import efficient_su2, real_amplitudes from qiskit.circuit.library.standard_gates import RXXGate, RYYGate, RZXGate, RZZGate from qiskit.primitives import Estimator from qiskit.quantum_info import SparsePauliOp @@ -130,7 +130,7 @@ def test_gradient_u(self, grad): def test_gradient_efficient_su2(self, grad): """Test the estimator gradient for EfficientSU2""" - qc = EfficientSU2(2, reps=1) + qc = efficient_su2(2, reps=1) op = SparsePauliOp.from_list([("ZI", 1)]) gradient = grad(self.estimator) param_list = [ @@ -183,7 +183,7 @@ def test_gradient_2qubit_gate(self, grad): def test_gradient_parameter_coefficient(self, grad): """Test the estimator gradient for parameter variables with coefficients""" - qc = RealAmplitudes(num_qubits=2, reps=1) + qc = real_amplitudes(num_qubits=2, reps=1) qc.rz(qc.parameters[0].exp() + 2 * qc.parameters[1], 0) qc.rx(3.0 * qc.parameters[0] + qc.parameters[1].sin(), 1) qc.u(qc.parameters[0], qc.parameters[1], qc.parameters[3], 1) @@ -546,7 +546,7 @@ def test_gradient_u(self, grad): def test_gradient_efficient_su2(self, grad): """Test the estimator gradient for EfficientSU2""" - qc = EfficientSU2(2, reps=1) + qc = efficient_su2(2, reps=1) op = SparsePauliOp.from_list([("ZI", 1)]) gradient = grad(estimator=self.estimator, pass_manager=self.pass_manager) param_list = [ @@ -599,7 +599,7 @@ def test_gradient_2qubit_gate(self, grad): def test_gradient_parameter_coefficient(self, grad): """Test the estimator gradient for parameter variables with coefficients""" - qc = RealAmplitudes(num_qubits=2, reps=1) + qc = real_amplitudes(num_qubits=2, reps=1) qc.rz(qc.parameters[0].exp() + 2 * qc.parameters[1], 0) qc.rx(3.0 * qc.parameters[0] + qc.parameters[1].sin(), 1) qc.u(qc.parameters[0], qc.parameters[1], qc.parameters[3], 1) diff --git a/test/gradients/test_sampler_gradient.py b/test/gradients/test_sampler_gradient.py index da2408a94..f5149b0eb 100644 --- a/test/gradients/test_sampler_gradient.py +++ b/test/gradients/test_sampler_gradient.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2019, 2024. +# (C) Copyright IBM 2019, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -21,7 +21,7 @@ from qiskit import QuantumCircuit from qiskit.circuit import Parameter -from qiskit.circuit.library import EfficientSU2, RealAmplitudes +from qiskit.circuit.library import efficient_su2, real_amplitudes from qiskit.circuit.library.standard_gates import RXXGate from qiskit.primitives import Sampler from qiskit.result import QuasiDistribution @@ -126,7 +126,7 @@ def test_gradient_u(self, grad): def test_gradient_efficient_su2(self, grad): """Test the sampler gradient for EfficientSU2""" - qc = EfficientSU2(2, reps=1) + qc = efficient_su2(2, reps=1) qc.measure_all() gradient = grad(self.sampler) param_list = [ @@ -241,7 +241,7 @@ def test_gradient_2qubit_gate(self, grad): def test_gradient_parameter_coefficient(self, grad): """Test the sampler gradient for parameter variables with coefficients""" - qc = RealAmplitudes(num_qubits=2, reps=1) + qc = real_amplitudes(num_qubits=2, reps=1) qc.rz(qc.parameters[0].exp() + 2 * qc.parameters[1], 0) qc.rx(3.0 * qc.parameters[0] + qc.parameters[1].sin(), 1) qc.u(qc.parameters[0], qc.parameters[1], qc.parameters[3], 1) @@ -682,7 +682,7 @@ def test_gradient_u(self, grad): def test_gradient_efficient_su2(self, grad): """Test the sampler gradient for EfficientSU2""" - qc = EfficientSU2(2, reps=1) + qc = efficient_su2(2, reps=1) qc.measure_all() gradient = grad( sampler=self.sampler, @@ -802,7 +802,7 @@ def test_gradient_2qubit_gate(self, grad): def test_gradient_parameter_coefficient(self, grad): """Test the sampler gradient for parameter variables with coefficients""" - qc = RealAmplitudes(num_qubits=2, reps=1) + qc = real_amplitudes(num_qubits=2, reps=1) qc.rz(qc.parameters[0].exp() + 2 * qc.parameters[1], 0) qc.rx(3.0 * qc.parameters[0] + qc.parameters[1].sin(), 1) qc.u(qc.parameters[0], qc.parameters[1], qc.parameters[3], 1) diff --git a/test/kernels/algorithms/test_fidelity_qkernel_trainer.py b/test/kernels/algorithms/test_fidelity_qkernel_trainer.py index d6e08ed93..9243d351d 100644 --- a/test/kernels/algorithms/test_fidelity_qkernel_trainer.py +++ b/test/kernels/algorithms/test_fidelity_qkernel_trainer.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -24,7 +24,7 @@ from qiskit import QuantumCircuit from qiskit.circuit import Parameter, ParameterVector -from qiskit.circuit.library import ZZFeatureMap +from qiskit.circuit.library import zz_feature_map from qiskit_machine_learning.utils import algorithm_globals from qiskit_machine_learning.algorithms.classifiers import QSVC @@ -46,8 +46,8 @@ class TestQuantumKernelTrainer(QiskitMachineLearningTestCase): def setUp(self): super().setUp() algorithm_globals.random_seed = 10598 - data_block = ZZFeatureMap(2) - trainable_block = ZZFeatureMap(2, parameter_prefix="θ") + data_block = zz_feature_map(2) + trainable_block = zz_feature_map(2, parameter_prefix="θ") training_parameters = trainable_block.parameters self.feature_map = data_block.compose(trainable_block).compose(data_block) diff --git a/test/kernels/test_fidelity_qkernel.py b/test/kernels/test_fidelity_qkernel.py index d21923510..d2cb685f1 100644 --- a/test/kernels/test_fidelity_qkernel.py +++ b/test/kernels/test_fidelity_qkernel.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -26,7 +26,7 @@ from qiskit import QuantumCircuit from qiskit.circuit import Parameter -from qiskit.circuit.library import ZFeatureMap +from qiskit.circuit.library import z_feature_map from qiskit.primitives import Sampler from qiskit_machine_learning.algorithm_job import AlgorithmJob @@ -48,7 +48,7 @@ def setUp(self): algorithm_globals.random_seed = 10598 - self.feature_map = ZFeatureMap(feature_dimension=2, reps=2) + self.feature_map = z_feature_map(feature_dimension=2, reps=2) self.sample_train = np.asarray( [ @@ -378,7 +378,7 @@ class TestDuplicates(QiskitMachineLearningTestCase): def setUp(self) -> None: super().setUp() - self.feature_map = ZFeatureMap(feature_dimension=2, reps=1) + self.feature_map = z_feature_map(feature_dimension=2, reps=1) self.properties = { "no_dups": np.array([[1, 2], [2, 3], [3, 4]]), diff --git a/test/kernels/test_fidelity_statevector_kernel.py b/test/kernels/test_fidelity_statevector_kernel.py index cd92b8c23..89b220a6c 100644 --- a/test/kernels/test_fidelity_statevector_kernel.py +++ b/test/kernels/test_fidelity_statevector_kernel.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2023, 2024. +# (C) Copyright IBM 2023, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -27,7 +27,7 @@ from qiskit import QuantumCircuit from qiskit.circuit import Parameter -from qiskit.circuit.library import ZFeatureMap +from qiskit.circuit.library import z_feature_map from qiskit.utils import optionals from qiskit_machine_learning.utils import algorithm_globals @@ -43,7 +43,7 @@ def setUp(self): algorithm_globals.random_seed = 10598 - self.feature_map = ZFeatureMap(feature_dimension=2, reps=2) + self.feature_map = z_feature_map(feature_dimension=2, reps=2) self.sample_train = np.asarray( [ @@ -401,7 +401,7 @@ class TestStatevectorKernelDuplicates(QiskitMachineLearningTestCase): def setUp(self) -> None: super().setUp() - self.feature_map = ZFeatureMap(feature_dimension=2, reps=1) + self.feature_map = z_feature_map(feature_dimension=2, reps=1) self.properties = { "no_dups": np.array([[1, 2], [2, 3], [3, 4]]), diff --git a/test/kernels/test_trainable_fidelity_qkernel.py b/test/kernels/test_trainable_fidelity_qkernel.py index a7eada0c7..516270e02 100644 --- a/test/kernels/test_trainable_fidelity_qkernel.py +++ b/test/kernels/test_trainable_fidelity_qkernel.py @@ -19,7 +19,7 @@ import numpy as np from ddt import ddt, data, idata, unpack from qiskit.circuit import Parameter -from qiskit.circuit.library import ZZFeatureMap +from qiskit.circuit.library import zz_feature_map from qiskit_machine_learning import QiskitMachineLearningError from qiskit_machine_learning.kernels import ( @@ -36,8 +36,8 @@ def setUp(self): super().setUp() # Create an arbitrary 3-qubit feature map circuit - circ1 = ZZFeatureMap(3) - circ2 = ZZFeatureMap(3, parameter_prefix="θ") + circ1 = zz_feature_map(3) + circ2 = zz_feature_map(3, parameter_prefix="θ") self.feature_map = circ1.compose(circ2).compose(circ1) self.num_features = circ1.num_parameters self.training_parameters = circ2.parameters diff --git a/test/neural_networks/test_effective_dimension.py b/test/neural_networks/test_effective_dimension.py index ce3944548..6d61f74d5 100644 --- a/test/neural_networks/test_effective_dimension.py +++ b/test/neural_networks/test_effective_dimension.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,7 +19,7 @@ from ddt import ddt, data, unpack from qiskit.circuit import QuantumCircuit -from qiskit.circuit.library import ZFeatureMap, RealAmplitudes +from qiskit.circuit.library import z_feature_map, real_amplitudes from qiskit_machine_learning.utils import algorithm_globals from qiskit_machine_learning.neural_networks import ( @@ -42,8 +42,8 @@ def setUp(self): # set up quantum neural networks num_qubits = 3 - feature_map = ZFeatureMap(feature_dimension=num_qubits, reps=1) - ansatz = RealAmplitudes(num_qubits, reps=1) + feature_map = z_feature_map(feature_dimension=num_qubits, reps=1) + ansatz = real_amplitudes(num_qubits, reps=1) # SamplerQNNs qc = QuantumCircuit(num_qubits) diff --git a/test/neural_networks/test_estimator_qnn_v1.py b/test/neural_networks/test_estimator_qnn_v1.py index 483eaf0c1..ff6853cde 100644 --- a/test/neural_networks/test_estimator_qnn_v1.py +++ b/test/neural_networks/test_estimator_qnn_v1.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,7 +18,7 @@ import numpy as np from qiskit.circuit import Parameter, QuantumCircuit -from qiskit.circuit.library import ZZFeatureMap, RealAmplitudes, ZFeatureMap +from qiskit.circuit.library import zz_feature_map, real_amplitudes, z_feature_map from qiskit.quantum_info import SparsePauliOp from qiskit_machine_learning.circuit.library import QNNCircuit @@ -412,8 +412,8 @@ def test_setters_getters(self): def test_qnn_qc_circuit_construction(self): """Test Estimator QNN properties and forward/backward pass for QNNCircuit construction""" num_qubits = 2 - feature_map = ZZFeatureMap(feature_dimension=num_qubits) - ansatz = RealAmplitudes(num_qubits=num_qubits, reps=1) + feature_map = zz_feature_map(feature_dimension=num_qubits) + ansatz = real_amplitudes(num_qubits=num_qubits, reps=1) qnn_qc = QNNCircuit(num_qubits=num_qubits, feature_map=feature_map, ansatz=ansatz) qc = QuantumCircuit(num_qubits) @@ -451,7 +451,7 @@ def test_qnn_qc_circuit_construction(self): def test_binding_order(self): """Test parameter binding order gives result as expected""" - qc = ZFeatureMap(feature_dimension=2, reps=1) + qc = z_feature_map(feature_dimension=2, reps=1) input_params = qc.parameters weight = Parameter("weight") for i in range(qc.num_qubits): diff --git a/test/neural_networks/test_estimator_qnn_v2.py b/test/neural_networks/test_estimator_qnn_v2.py index f5c3539aa..646db1ea1 100644 --- a/test/neural_networks/test_estimator_qnn_v2.py +++ b/test/neural_networks/test_estimator_qnn_v2.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,7 +19,7 @@ import numpy as np from qiskit.circuit import Parameter, QuantumCircuit -from qiskit.circuit.library import ZZFeatureMap, RealAmplitudes, ZFeatureMap +from qiskit.circuit.library import zz_feature_map, real_amplitudes, z_feature_map from qiskit.quantum_info import SparsePauliOp from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager @@ -477,8 +477,8 @@ def test_setters_getters(self): def test_qnn_qc_circuit_construction(self): """Test Estimator QNN properties and forward/backward pass for QNNCircuit construction""" num_qubits = 2 - feature_map = ZZFeatureMap(feature_dimension=num_qubits) - ansatz = RealAmplitudes(num_qubits=num_qubits, reps=1) + feature_map = zz_feature_map(feature_dimension=num_qubits) + ansatz = real_amplitudes(num_qubits=num_qubits, reps=1) qc = QuantumCircuit(num_qubits) qc.compose(feature_map, inplace=True) @@ -529,7 +529,7 @@ def test_qnn_qc_circuit_construction(self): def test_binding_order(self): """Test parameter binding order gives result as expected""" - qc = ZFeatureMap(feature_dimension=2, reps=1) + qc = z_feature_map(feature_dimension=2, reps=1) input_params = qc.parameters weight = Parameter("weight") for i in range(qc.num_qubits): diff --git a/test/neural_networks/test_sampler_qnn.py b/test/neural_networks/test_sampler_qnn.py index e2b821cc8..ba3d12203 100644 --- a/test/neural_networks/test_sampler_qnn.py +++ b/test/neural_networks/test_sampler_qnn.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -25,7 +25,7 @@ from qiskit.primitives import Sampler from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager -from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap +from qiskit.circuit.library import real_amplitudes, zz_feature_map from qiskit_ibm_runtime import Session, SamplerV2 @@ -70,8 +70,8 @@ def setUp(self): # define feature map and ansatz num_qubits = 2 - feature_map = ZZFeatureMap(num_qubits, reps=1) - var_form = RealAmplitudes(num_qubits, reps=1) + feature_map = zz_feature_map(num_qubits, reps=1) + var_form = real_amplitudes(num_qubits, reps=1) # construct circuit self.qc = QuantumCircuit(num_qubits) @@ -383,8 +383,8 @@ def test_no_parameters(self): def test_qnn_qc_circuit_construction(self): """Test Sampler QNN properties and forward/backward pass for QNNCircuit construction""" num_qubits = 2 - feature_map = ZZFeatureMap(feature_dimension=num_qubits) - ansatz = RealAmplitudes(num_qubits=num_qubits, reps=1) + feature_map = zz_feature_map(feature_dimension=num_qubits) + ansatz = real_amplitudes(num_qubits=num_qubits, reps=1) def parity(x): return f"{bin(x)}".count("1") % 2 diff --git a/test/optimizers/test_gradient_descent.py b/test/optimizers/test_gradient_descent.py index 4091ad113..3a8a6aa32 100644 --- a/test/optimizers/test_gradient_descent.py +++ b/test/optimizers/test_gradient_descent.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -14,7 +14,7 @@ from test import QiskitAlgorithmsTestCase import numpy as np -from qiskit.circuit.library import PauliTwoDesign +from qiskit.circuit.library import pauli_two_design from qiskit.quantum_info import SparsePauliOp, Statevector from qiskit_machine_learning.optimizers import GradientDescent, GradientDescentState @@ -40,7 +40,7 @@ def grad(self, x): def test_pauli_two_design(self): """Test standard gradient descent on the Pauli two-design example.""" - circuit = PauliTwoDesign(3, reps=3, seed=2) + circuit = pauli_two_design(3, reps=3, seed=2) parameters = list(circuit.parameters) obs = SparsePauliOp("ZZI") # Z^Z^I diff --git a/test/optimizers/test_optimizers.py b/test/optimizers/test_optimizers.py index 719dc76a1..df253cd5d 100644 --- a/test/optimizers/test_optimizers.py +++ b/test/optimizers/test_optimizers.py @@ -20,7 +20,7 @@ import numpy as np from scipy.optimize import rosen, rosen_der -from qiskit.circuit.library import RealAmplitudes +from qiskit.circuit.library import real_amplitudes from qiskit.exceptions import MissingOptionalLibraryError from qiskit.primitives import Sampler @@ -387,7 +387,7 @@ def steps(): def test_qnspsa(self): """Test QN-SPSA optimizer is serializable.""" - ansatz = RealAmplitudes(1) + ansatz = real_amplitudes(1) fidelity = QNSPSA.get_fidelity(ansatz, sampler=Sampler()) options = { "fidelity": fidelity, diff --git a/test/optimizers/test_spsa.py b/test/optimizers/test_spsa.py index ec3af13ee..a201d80ea 100644 --- a/test/optimizers/test_spsa.py +++ b/test/optimizers/test_spsa.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2021, 2024. +# (C) Copyright IBM 2021, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -17,7 +17,7 @@ import numpy as np -from qiskit.circuit.library import PauliTwoDesign +from qiskit.circuit.library import pauli_two_design from qiskit.primitives import Estimator, Sampler from qiskit.quantum_info import SparsePauliOp, Statevector @@ -38,7 +38,7 @@ def setUp(self): @data("spsa", "2spsa", "qnspsa") def test_pauli_two_design(self, method): """Test SPSA on the Pauli two-design example.""" - circuit = PauliTwoDesign(3, reps=1, seed=1) + circuit = pauli_two_design(3, reps=1, seed=1) parameters = list(circuit.parameters) obs = SparsePauliOp("ZZI") # Z^Z^I @@ -200,7 +200,7 @@ def objective(x): def test_qnspsa_fidelity_primitives(self): """Test the primitives can be used in get_fidelity.""" - ansatz = PauliTwoDesign(2, reps=1, seed=2) + ansatz = pauli_two_design(2, reps=1, seed=2) initial_point = np.random.random(ansatz.num_parameters) with self.subTest(msg="pass as kwarg"): @@ -211,7 +211,7 @@ def test_qnspsa_fidelity_primitives(self): def test_qnspsa_max_evals_grouped(self): """Test using max_evals_grouped with QNSPSA.""" - circuit = PauliTwoDesign(3, reps=1, seed=1) + circuit = pauli_two_design(3, reps=1, seed=1) num_parameters = circuit.num_parameters obs = SparsePauliOp("ZZI") # Z^Z^I diff --git a/test/state_fidelities/test_compute_uncompute.py b/test/state_fidelities/test_compute_uncompute.py index b498e29fa..e777b0a92 100644 --- a/test/state_fidelities/test_compute_uncompute.py +++ b/test/state_fidelities/test_compute_uncompute.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,7 +18,7 @@ import numpy as np from qiskit.circuit import QuantumCircuit, ParameterVector -from qiskit.circuit.library import RealAmplitudes +from qiskit.circuit.library import real_amplitudes from qiskit.primitives import Sampler from qiskit_machine_learning.state_fidelities import ComputeUncompute @@ -179,7 +179,7 @@ def test_input_format(self): """test for different input format variations""" fidelity = ComputeUncompute(self._sampler) - circuit = RealAmplitudes(2) + circuit = real_amplitudes(2) values = np.random.random(circuit.num_parameters) shift = np.ones_like(values) * 0.01 diff --git a/test/state_fidelities/test_compute_uncompute_v2.py b/test/state_fidelities/test_compute_uncompute_v2.py index 30d276333..0fc68d43a 100644 --- a/test/state_fidelities/test_compute_uncompute_v2.py +++ b/test/state_fidelities/test_compute_uncompute_v2.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2024. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,7 +18,7 @@ import numpy as np from qiskit.circuit import QuantumCircuit, ParameterVector -from qiskit.circuit.library import RealAmplitudes +from qiskit.circuit.library import real_amplitudes from qiskit.primitives import Sampler from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager @@ -226,7 +226,7 @@ def test_asymmetric_params(self): def test_input_format(self): """test for different input format variations""" - circuit = RealAmplitudes(2) + circuit = real_amplitudes(2) fidelity = ComputeUncompute(self._sampler, pass_manager=self.pass_manager) values = np.random.random(circuit.num_parameters) shift = np.ones_like(values) * 0.01 diff --git a/test/utils/test_adjust_num_qubits.py b/test/utils/test_adjust_num_qubits.py index 3a8418a2f..13920157a 100644 --- a/test/utils/test_adjust_num_qubits.py +++ b/test/utils/test_adjust_num_qubits.py @@ -1,6 +1,6 @@ # This code is part of a Qiskit project. # -# (C) Copyright IBM 2022, 2023. +# (C) Copyright IBM 2022, 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -16,7 +16,7 @@ from ddt import idata, unpack, ddt from qiskit import QuantumCircuit -from qiskit.circuit.library import ZFeatureMap, RealAmplitudes, ZZFeatureMap +from qiskit.circuit.library import ZFeatureMap, RealAmplitudes from qiskit_machine_learning import QiskitMachineLearningError from qiskit_machine_learning.utils import derive_num_qubits_feature_map_ansatz @@ -105,11 +105,11 @@ def _test_feature_map(self, feature_map_der, feature_map_org, num_qubits_expecte self.assertEqual(feature_map_der.num_qubits, num_qubits_expected) if feature_map_org is None and num_qubits_expected == 1: - self.assertIsInstance(feature_map_der, ZFeatureMap) + self.assertIsInstance(feature_map_der, QuantumCircuit) if feature_map_org is None and num_qubits_expected == 2: - self.assertIsInstance(feature_map_der, ZZFeatureMap) + self.assertIsInstance(feature_map_der, QuantumCircuit) def _test_ansatz(self, ansatz_der, num_qubits_expected): self.assertIsNotNone(ansatz_der) self.assertEqual(ansatz_der.num_qubits, num_qubits_expected) - self.assertIsInstance(ansatz_der, RealAmplitudes) + self.assertIsInstance(ansatz_der, QuantumCircuit) From e28046bb97f87996ef77928b88738b1ee5bb79ad Mon Sep 17 00:00:00 2001 From: woodsp-ibm Date: Thu, 5 Jun 2025 16:04:54 -0400 Subject: [PATCH 2/4] =?UTF-8?q?Add=20greek=20letter=20pi=20(=CF=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pylintdict | 1 + 1 file changed, 1 insertion(+) diff --git a/.pylintdict b/.pylintdict index 5942e917c..7e77dafdf 100644 --- a/.pylintdict +++ b/.pylintdict @@ -632,3 +632,4 @@ zz φ_i φ_ij Δ +π From 7a1c41566c448c038f888fb1ebf4c9d7714d3de6 Mon Sep 17 00:00:00 2001 From: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com> Date: Fri, 6 Jun 2025 09:16:09 -0400 Subject: [PATCH 3/4] Update qiskit_machine_learning/circuit/library/raw_feature_vector.py Co-authored-by: Edoardo Altamura <38359901+edoaltamura@users.noreply.github.com> --- qiskit_machine_learning/circuit/library/raw_feature_vector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit_machine_learning/circuit/library/raw_feature_vector.py b/qiskit_machine_learning/circuit/library/raw_feature_vector.py index 6ce3a6bcd..25e4586f0 100644 --- a/qiskit_machine_learning/circuit/library/raw_feature_vector.py +++ b/qiskit_machine_learning/circuit/library/raw_feature_vector.py @@ -153,7 +153,7 @@ def __init__(self, feature_dimension: Optional[int]) -> None: msg="RawFeatureVector, a BlueprintCircuit based class, is deprecated", version="0.9.0", remedy="Use raw_feature_vector instead but note that later " - "adjustment of the feature dimension (i,e updating num qubits) is not " + "adjustment of the feature dimension (i,e updating num_qubits) is not " "possible anymore.", period="4 months", ) From 4348ebef685656167f6e2e9dff3279ce8bb15f93 Mon Sep 17 00:00:00 2001 From: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com> Date: Fri, 6 Jun 2025 09:16:26 -0400 Subject: [PATCH 4/4] Update qiskit_machine_learning/kernels/base_kernel.py Co-authored-by: Edoardo Altamura <38359901+edoaltamura@users.noreply.github.com> --- qiskit_machine_learning/kernels/base_kernel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit_machine_learning/kernels/base_kernel.py b/qiskit_machine_learning/kernels/base_kernel.py index f2dd886a6..e393c5f4b 100644 --- a/qiskit_machine_learning/kernels/base_kernel.py +++ b/qiskit_machine_learning/kernels/base_kernel.py @@ -62,7 +62,7 @@ def __init__(self, *, feature_map: QuantumCircuit = None, enforce_psd: bool = Tr msg="Passing None as a feature_map is deprecated", version="0.9.0", remedy="Pass a feature map with the required number of qubits to match " - "the features. Later any adjustment of the number of qubits will be " + "the features. Adjusting the number of qubits after instantiation will be " "removed from Qiskit as circuits based on BlueprintCircuit, " "like ZZFeatureMap to which this defaults, which could do this, " "have been deprecated.",