Source code for scikit_quri.qsvm.qsvc
from typing import List, Optional, TypeGuard
import numpy as np
from numpy.typing import NDArray
from ..circuit import LearningCircuit
from sklearn import svm
from quri_parts.core.state import (
QuantumState,
quantum_state,
ParametricCircuitQuantumState,
GeneralCircuitQuantumState,
)
from quri_parts.circuit import QuantumCircuit
from quri_parts.backend import SamplingBackend
from ..state.overlap_estimator import overlap_estimator
from ..state.overlap_estimator_real_device import overlap_estimator_real_device
# sampling_backendのTypeGuardを定義
[docs]def is_real_device(
sampling_backend: Optional[SamplingBackend], is_sim: bool
) -> TypeGuard[SamplingBackend]:
return not is_sim
[docs]class QSVC:
def __init__(self, circuit: LearningCircuit, sim: bool = True):
self.svc = svm.SVC(kernel="precomputed")
self.circuit = circuit
# for sim
self.data_states: List[QuantumState] = []
# for real devices
self.data_circuits: List[QuantumCircuit] = []
self.n_qubit: int = circuit.n_qubits
self.is_sim = sim
self.estimator = None
[docs] def run_circuit(self, x: NDArray[np.float64]) -> GeneralCircuitQuantumState:
# ここにはparametrizeされたcircuitは入ってこないはず...
circuit = self.circuit.bind_input_and_parameters(x, np.array([]))
state = quantum_state(n_qubits=self.n_qubit, circuit=circuit)
return state
[docs] def fit(
self,
x: NDArray[np.float64],
y: NDArray[np.int_],
sampling_backend: Optional[SamplingBackend] = None,
n_shots: int = 1000,
):
if not self.is_sim and sampling_backend is None:
raise ValueError("sampling_backend is required for real devices")
kar = np.zeros((len(x), len(x)))
for i in range(len(x)):
state = self.run_circuit(x[i])
self.data_states.append(state)
self.data_circuits.append(state.circuit.get_mutable_copy())
if is_real_device(sampling_backend, self.is_sim):
self.estimator = overlap_estimator_real_device(
self.data_circuits.copy(), sampling_backend, n_shots
)
else:
self.estimator = overlap_estimator(self.data_states.copy())
for i in range(len(x)):
for j in range(len(x)):
kar[i][j] = self.estimator.estimate(i, j)
print("\r", f"{i}/{len(x)}", end="")
print("")
self.svc.fit(kar, y)
[docs] def predict(self, xs: NDArray[np.float64]) -> NDArray[np.float64]:
if self.estimator is None:
raise ValueError("run fit() before predict")
kar = np.zeros((len(xs), len(self.data_states)))
new_states = []
new_circuits = []
for i in range(len(xs)):
x_qc = self.run_circuit(xs[i])
new_states.append(x_qc)
new_circuits.append(x_qc.circuit.get_mutable_copy())
if self.is_sim:
self.estimator.add_data(new_states)
else:
self.estimator.add_data(new_circuits)
offset = len(self.data_states)
for i in range(len(xs)):
for j in range(len(self.data_states)):
kar[i][j] = self.estimator.estimate(offset + i, j)
print("\r", f"{i}/{len(xs)}", end="")
print("")
pred: NDArray[np.float64] = self.svc.predict(kar)
return pred