Source code for qlauncher.routines.qiskit.algorithms.qml

  1from collections.abc import Callable
  2from typing import Any, Sequence
  3
  4from qiskit.circuit import QuantumCircuit, Parameter
  5from qiskit.primitives import BaseSampler, BaseSamplerV1, BaseSamplerV2
  6from qiskit.transpiler.passmanager import PassManager
  7from qiskit.providers import Options
  8import numpy as np
  9
 10from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer
 11from qiskit_machine_learning.kernels import TrainableFidelityQuantumKernel, FidelityQuantumKernel
 12from qiskit_machine_learning.state_fidelities import ComputeUncompute, BaseStateFidelity
 13
 14from qlauncher.base.base import Backend, Problem, Algorithm, Result
 15from qlauncher.routines.qiskit.backends.qiskit_backend import QiskitBackend
 16from qlauncher.routines.cirq import CirqBackend
 17
 18
[docs] 19class ComputeUncomputeCustom(ComputeUncompute): 20 """ 21 This is just :class:`qiskit_machine_learning.state_fidelities.ComputeUncompute` that checks 22 if a sampler is an instance of BaseSamplerV1 instead of BaseSampler. 23 The reason was that classes basing BaseSampler were getting isinstance(cls(),BaseSampler) == False 24 probably because of some qiskit shenanigans. 25 """ 26 27 def __init__( 28 self, 29 sampler: BaseSampler | BaseSamplerV2, 30 *, 31 options: Options | None = None, 32 local: bool = False, 33 pass_manager: PassManager | None = None, 34 ) -> None: 35 36 if (not isinstance(sampler, BaseSamplerV1)) and (not isinstance(sampler, BaseSamplerV2)): 37 raise ValueError( 38 f"The sampler should be an instance of BaseSampler or BaseSamplerV2, " 39 f"but got {type(sampler)}" 40 ) 41 self._sampler: BaseSamplerV1 | BaseSamplerV2 = sampler 42 self._pass_manager = pass_manager 43 self._local = local 44 self._default_options = Options() 45 if options is not None: 46 self._default_options.update_options(**options) 47 BaseStateFidelity.__init__(self) # pylint: disable=non-parent-init-called
48 49
[docs] 50class TrainQSVCKernel(Algorithm): 51 """ 52 Train a quantum kernel with additional parameters to be optimized. 53 The kernel will be optimized to provide maximum accuracy with a support vector classifier on the provided dataset. 54 If no trainable parameters are provided, the algorithm will return 55 a :class:`qiskit_machine_learning.kernels.FidelityQuantumKernel` kernel with a sampler assigned to the provided backend. 56 Otherwise an instance of :class:`qiskit_machine_learning.kernels.TrainableFidelityQuantumKernel` with optimal 57 parameters and a sampler assigned to the provided backend will be returned. 58 59 Args: 60 kernel_circuit(QuantumCircuit): A parametrizable quantum circuit. The measurements will be used to produce kernel output. 61 trainable_params(Sequence[Parameter] | None, optional): 62 The parameters to be optimized during training. If None no optimization will be done. Defaults to None. 63 """ 64 65 _algorithm_format = 'tabular_ml' 66 67 def __init__( 68 self, 69 kernel_circuit: QuantumCircuit, 70 trainable_params: Sequence[Parameter] | None = None, 71 **alg_kwargs 72 ) -> None: 73 super().__init__(**alg_kwargs) 74 self.kernel = kernel_circuit 75 self.trainable = trainable_params if trainable_params is not None else [] 76
[docs] 77 def run(self, problem: Problem, backend: Backend, formatter: Callable[..., Any]) -> Result: 78 X, y = formatter(problem) 79 80 if not isinstance(X, np.ndarray): 81 raise ValueError(f"X is not of type np.ndarray: received {type(X)}") 82 83 if not isinstance(y, np.ndarray): 84 raise ValueError(f"y is not of type np.ndarray: received {type(y)}") 85 86 if isinstance(backend, QiskitBackend) or isinstance(backend, CirqBackend): 87 sampler = backend.samplerV1 88 else: 89 raise ValueError(f"The accepted backends are QiskitBackend and CirqBackend, got {type(backend)}") 90 91 if len(self.trainable) == 0: 92 return Result( 93 best_bitstring='', 94 best_energy=1, 95 most_common_bitstring='', 96 most_common_bitstring_energy=0, 97 distribution={}, 98 energies={}, 99 num_of_samples=0, 100 average_energy=0, 101 energy_std=0, 102 result=FidelityQuantumKernel(feature_map=self.kernel, fidelity=ComputeUncomputeCustom(sampler=sampler)) 103 ) 104 trainable_kernel = TrainableFidelityQuantumKernel( 105 feature_map=self.kernel, 106 fidelity=ComputeUncomputeCustom(sampler=sampler), 107 training_parameters=self.trainable 108 ) 109 kernel_trainer = QuantumKernelTrainer(trainable_kernel) 110 kernel_trainer.fit(X, y) 111 112 return Result( 113 best_bitstring='', 114 best_energy=1, 115 most_common_bitstring='', 116 most_common_bitstring_energy=0, 117 distribution={}, 118 energies={}, 119 num_of_samples=0, 120 average_energy=0, 121 energy_std=0, 122 result=kernel_trainer.quantum_kernel 123 )