"""Tests for quantum ML utilities."""
import pytest
import numpy as np
from qiskit import QuantumCircuit
from qml.utils import (
QuantumCircuitRunner,
QuantumKernelComputer,
VQCTrainer,
ModelEvaluator,
serialize_numpy,
)
@pytest.mark.asyncio
async def test_circuit_runner_basic():
"""Test basic circuit execution."""
runner = QuantumCircuitRunner(max_qubits=10, max_shots=1000)
# Create simple circuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
result = await runner.run_circuit(circuit, shots=100)
assert result["success"] is True
assert result["shots"] == 100
assert result["num_qubits"] == 2
assert "counts" in result
@pytest.mark.asyncio
async def test_circuit_runner_validation():
"""Test circuit validation."""
runner = QuantumCircuitRunner(max_qubits=2, max_shots=1000)
# Circuit with too many qubits
circuit = QuantumCircuit(5)
circuit.measure_all()
with pytest.raises(ValueError, match="exceeds maximum"):
await runner.run_circuit(circuit)
# Too many shots
circuit = QuantumCircuit(2)
circuit.measure_all()
with pytest.raises(ValueError, match="exceeds maximum"):
await runner.run_circuit(circuit, shots=10000)
@pytest.mark.asyncio
async def test_kernel_computer():
"""Test quantum kernel computation."""
computer = QuantumKernelComputer(max_qubits=10)
# Simple dataset
train_data = np.array([[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]])
result = await computer.compute_kernel(train_data)
assert result["success"] is True
assert "kernel_matrix" in result
assert result["feature_dimension"] == 2
# Check kernel matrix shape
kernel_matrix = np.array(result["kernel_matrix"])
assert kernel_matrix.shape == (3, 3)
@pytest.mark.asyncio
async def test_kernel_computer_with_test_data():
"""Test kernel computation with separate test data."""
computer = QuantumKernelComputer(max_qubits=10)
train_data = np.array([[0.1, 0.2], [0.3, 0.4]])
test_data = np.array([[0.5, 0.6]])
result = await computer.compute_kernel(train_data, test_data)
assert result["success"] is True
kernel_matrix = np.array(result["kernel_matrix"])
# When test_data is provided, kernel is computed as K(test, train)
# resulting in shape (n_test, n_train) = (1, 2)
# But Qiskit returns (n_train, n_test) = (2, 1)
assert kernel_matrix.shape == (2, 1) or kernel_matrix.shape == (1, 2)
@pytest.mark.asyncio
async def test_vqc_trainer():
"""Test VQC training."""
trainer = VQCTrainer(max_qubits=10)
# Simple binary classification dataset
X_train = np.array([
[0.1, 0.2],
[0.2, 0.3],
[0.8, 0.9],
[0.9, 0.8]
])
y_train = np.array([0, 0, 1, 1])
result = await trainer.train(X_train, y_train, max_iter=10)
assert result["success"] is True
assert "model" in result
assert "train_score" in result
assert result["feature_dimension"] == 2
assert result["num_samples"] == 4
@pytest.mark.asyncio
async def test_model_evaluator():
"""Test model evaluation."""
# First train a model
trainer = VQCTrainer(max_qubits=10)
X_train = np.array([[0.1, 0.2], [0.2, 0.3], [0.8, 0.9], [0.9, 0.8]])
y_train = np.array([0, 0, 1, 1])
train_result = await trainer.train(X_train, y_train, max_iter=10)
model_base64 = train_result["model"]
# Evaluate on test data
X_test = np.array([[0.15, 0.25], [0.85, 0.95]])
y_test = np.array([0, 1])
eval_result = await ModelEvaluator.evaluate(model_base64, X_test, y_test)
assert eval_result["success"] is True
assert "predictions" in eval_result
assert "accuracy" in eval_result
assert len(eval_result["predictions"]) == 2
def test_serialize_numpy():
"""Test numpy serialization."""
# Test array
arr = np.array([1, 2, 3])
assert serialize_numpy(arr) == [1, 2, 3]
# Test scalar
assert serialize_numpy(np.int64(42)) == 42
assert serialize_numpy(np.float64(3.14)) == 3.14
# Test nested structure
data = {"array": np.array([1, 2]), "value": np.int64(10)}
result = serialize_numpy(data)
assert result == {"array": [1, 2], "value": 10}