Source code for kosmos.ml.models.vqc.encoding.qiskit_encoding
from collections.abc import Sequence
import numpy as np
from qiskit import QuantumCircuit
from torch import Tensor
from kosmos.circuit_runner.typing import QuantumCircuitFramework
from kosmos.ml.models.vqc.encoding.encoding import AmplitudeEmbedding, AngleEmbedding
[docs]
class QiskitAngleEmbedding(AngleEmbedding):
"""Angle embedding for the VQC using Qiskit."""
@property
def framework(self) -> QuantumCircuitFramework:
"""The framework used for the quantum circuit."""
return "qiskit"
[docs]
def apply_operation(
self, features: Tensor, wires: Sequence[int], qc: QuantumCircuit | None = None
) -> None:
"""Apply the Qiskit angle embedding operation for encoding.
Args:
features (Tensor): Input features.
wires (Sequence[int]): Target wires.
qc (QuantumCircuit | None): The quantum circuit to use for the encoding
(only for 'qiskit' framework).
"""
super().apply_operation(features, wires, qc)
if len(features) > len(wires):
m = f"Got {len(features)} features for {len(wires)} wires."
raise ValueError(m)
for i, f in enumerate(features):
w = wires[i]
angle = f.item() if isinstance(f, Tensor) else f
wire = int(w)
if self.rotation == "X":
qc.rx(angle, wire)
elif self.rotation == "Y":
qc.ry(angle, wire)
elif self.rotation == "Z":
qc.rz(angle, wire)
else:
msg = f"Unknown rotation axis: {self.rotation}"
raise ValueError(msg) from None
[docs]
class QiskitAmplitudeEmbedding(AmplitudeEmbedding):
"""Amplitude embedding for the VQC using Qiskit."""
@property
def framework(self) -> QuantumCircuitFramework:
"""The framework used for the quantum circuit."""
return "qiskit"
[docs]
def apply_operation(
self, features: Tensor, wires: Sequence[int], qc: QuantumCircuit | None = None
) -> None:
"""Apply the Qiskit amplitude embedding operation for encoding.
Args:
features (Tensor): Input features.
wires (Sequence[int]): Target wires.
qc (QuantumCircuit | None): The quantum circuit to use for the encoding
(only for 'qiskit' framework).
"""
super().apply_operation(features, wires, qc)
def preprocessing(x: Tensor) -> np.ndarray:
x = np.pad(x, (0, 2**self.num_qubits - len(x))).astype(np.float64)
norm = np.linalg.norm(x)
if norm == 0:
msg = "Cannot normalize zero vector."
raise ValueError(msg)
return x / norm
qc.initialize(preprocessing(features), wires)