Client API¶
The qubitos.client module provides Python clients for communicating with the QubitOS HAL (Hardware Abstraction Layer) server via gRPC.
Overview¶
Two client classes are available:
| Class | Type | Use Case |
|---|---|---|
HALClient |
Async | High-throughput, concurrent operations |
HALClientSync |
Sync | Scripts, REPL, simple use cases |
Quick Start¶
Async Client¶
import asyncio
from qubitos.client import HALClient
async def main():
async with HALClient("localhost:50051") as client:
# Check health
health = await client.health_check()
print(f"Status: {health.status}")
# Execute a pulse
result = await client.execute_pulse(
i_envelope=[0.1, 0.5, 0.9, 0.5, 0.1],
q_envelope=[0.0, 0.0, 0.0, 0.0, 0.0],
duration_ns=20,
target_qubits=[0],
num_shots=1024,
)
print(f"Counts: {result.bitstring_counts}")
asyncio.run(main())
Sync Client¶
from qubitos.client import HALClientSync
with HALClientSync("localhost:50051") as client:
health = client.health_check()
print(f"Status: {health.status}")
Connection Management¶
Using Context Manager (Recommended)¶
# Async
async with HALClient("localhost:50051") as client:
# Connection is managed automatically
result = await client.execute_pulse(...)
# Sync
with HALClientSync("localhost:50051") as client:
result = client.execute_pulse(...)
Manual Connection¶
client = HALClient("localhost:50051")
await client.connect()
try:
result = await client.execute_pulse(...)
finally:
await client.close()
Secure Connections¶
import grpc
# With default TLS
client = HALClient("hal.example.com:50051", secure=True)
# With custom credentials
credentials = grpc.ssl_channel_credentials(
root_certificates=open("ca.pem", "rb").read()
)
client = HALClient("hal.example.com:50051", credentials=credentials)
Executing Pulses¶
The execute_pulse method sends pulse envelopes to a backend for execution:
result = await client.execute_pulse(
# Required parameters
i_envelope=[0.1, 0.5, 0.9, 0.5, 0.1], # In-phase envelope (MHz)
q_envelope=[0.0, 0.0, 0.0, 0.0, 0.0], # Quadrature envelope (MHz)
duration_ns=20, # Pulse duration
target_qubits=[0], # Target qubit indices
# Optional parameters
num_shots=1000, # Measurement shots
backend_name="qutip_simulator", # Backend to use
measurement_basis="z", # Measurement basis
return_state_vector=False, # Return state vector
include_noise=False, # Enable noise simulation
gate_type="X", # Gate type hint
)
With GRAPE-Optimized Pulses¶
from qubitos.pulsegen import generate_pulse
from qubitos.client import HALClientSync
# Generate optimized pulse
pulse = generate_pulse("X", duration_ns=20, target_fidelity=0.999)
# Execute on backend
with HALClientSync("localhost:50051") as client:
result = client.execute_pulse(
i_envelope=pulse.i_envelope.tolist(),
q_envelope=pulse.q_envelope.tolist(),
duration_ns=20,
target_qubits=[0],
num_shots=1024,
)
print(f"Measurement results: {result.bitstring_counts}")
Health Checks¶
Monitor backend status:
# Check all backends
health = await client.health_check()
print(f"Overall: {health.status}")
print(f"Message: {health.message}")
# Check specific backend
health = await client.health_check(backend_name="qutip_simulator")
# Per-backend status
for name, status in health.backends.items():
print(f" {name}: {status}")
Hardware Information¶
Query backend capabilities:
info = await client.get_hardware_info(backend_name="qutip_simulator")
print(f"Name: {info.name}")
print(f"Type: {info.backend_type}")
print(f"Qubits: {info.num_qubits}")
print(f"Available: {info.available_qubits}")
print(f"Gates: {info.supported_gates}")
print(f"State vector: {info.supports_state_vector}")
print(f"Noise model: {info.supports_noise_model}")
Listing Backends¶
Get available backends:
Error Handling¶
from qubitos.client import HALClient, HALClientError
try:
async with HALClient("localhost:50051") as client:
result = await client.execute_pulse(...)
except HALClientError as e:
print(f"Error: {e}")
print(f"Code: {e.code}") # gRPC error code
Common error codes:
| Code | Meaning |
|---|---|
UNAVAILABLE |
Server not reachable |
DEADLINE_EXCEEDED |
Request timed out |
INVALID_ARGUMENT |
Bad request parameters |
NOT_FOUND |
Backend not found |
API Reference¶
qubitos.client.hal.HALClient ¶
HALClient(
address: str = "localhost:50051",
timeout: float = 30.0,
secure: bool = False,
credentials: ChannelCredentials | None = None,
)
Async gRPC client for the HAL server.
The client provides methods for: - Executing pulse sequences - Checking backend health - Getting hardware information
Usage
async with HALClient("localhost:50051") as client: ... result = await client.execute_pulse(...)
Or without context manager
client = HALClient("localhost:50051") await client.connect() try: ... result = await client.execute_pulse(...) ... finally: ... await client.close()
Initialize the HAL client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
address
|
str
|
HAL server address (host:port) |
'localhost:50051'
|
timeout
|
float
|
Default timeout for RPC calls in seconds |
30.0
|
secure
|
bool
|
Whether to use TLS |
False
|
credentials
|
ChannelCredentials | None
|
gRPC credentials for secure connections |
None
|
Source code in src/qubitos/client/hal.py
connect
async
¶
Connect to the HAL server.
Source code in src/qubitos/client/hal.py
close
async
¶
Close the connection to the HAL server.
Source code in src/qubitos/client/hal.py
health_check
async
¶
Check the health of the HAL server and backends.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend_name
|
str | None
|
Specific backend to check (or None for all) |
None
|
Returns:
| Type | Description |
|---|---|
HealthCheckResult
|
HealthCheckResult with status information |
Source code in src/qubitos/client/hal.py
get_hardware_info
async
¶
Get hardware information for a backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend_name
|
str | None
|
Backend name (or None for default) |
None
|
Returns:
| Type | Description |
|---|---|
HardwareInfo
|
HardwareInfo with backend details |
Source code in src/qubitos/client/hal.py
execute_pulse
async
¶
execute_pulse(
i_envelope: Sequence[float],
q_envelope: Sequence[float],
duration_ns: int,
target_qubits: Sequence[int],
num_shots: int = 1000,
pulse_id: str | None = None,
backend_name: str | None = None,
measurement_basis: str = "z",
return_state_vector: bool = False,
include_noise: bool = False,
gate_type: str = "CUSTOM",
) -> MeasurementResult
Execute a pulse sequence on a backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
i_envelope
|
Sequence[float]
|
I (in-phase) pulse envelope (MHz) |
required |
q_envelope
|
Sequence[float]
|
Q (quadrature) pulse envelope (MHz) |
required |
duration_ns
|
int
|
Pulse duration in nanoseconds |
required |
target_qubits
|
Sequence[int]
|
Target qubit indices |
required |
num_shots
|
int
|
Number of measurement shots |
1000
|
pulse_id
|
str | None
|
Optional pulse identifier |
None
|
backend_name
|
str | None
|
Backend to use (or None for default) |
None
|
measurement_basis
|
str
|
Measurement basis ("x", "y", or "z") |
'z'
|
return_state_vector
|
bool
|
Whether to return the state vector |
False
|
include_noise
|
bool
|
Whether to include noise simulation |
False
|
gate_type
|
str
|
Gate type name (e.g., "X", "H", "CZ", "CUSTOM") |
'CUSTOM'
|
Returns:
| Type | Description |
|---|---|
MeasurementResult
|
MeasurementResult with bitstring counts and metadata |
Source code in src/qubitos/client/hal.py
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | |
list_backends
async
¶
List available backends.
Returns:
| Type | Description |
|---|---|
list[str]
|
List of backend names |
Source code in src/qubitos/client/hal.py
qubitos.client.hal.HALClientSync ¶
Data Types¶
qubitos.client.hal.HealthStatus ¶
Bases: Enum
Backend health status.
qubitos.client.hal.BackendType ¶
Bases: Enum
Backend type.
qubitos.client.hal.HardwareInfo
dataclass
¶
HardwareInfo(
name: str,
backend_type: BackendType,
tier: str,
num_qubits: int,
available_qubits: list[int],
supported_gates: list[str],
supports_state_vector: bool,
supports_noise_model: bool,
software_version: str,
)
Information about a quantum backend.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Backend name |
backend_type |
BackendType
|
Type of backend (simulator or hardware) |
tier |
str
|
Backend tier (local, cloud, etc.) |
num_qubits |
int
|
Number of qubits |
available_qubits |
list[int]
|
List of available qubit indices |
supported_gates |
list[str]
|
List of supported gate names |
supports_state_vector |
bool
|
Whether state vector output is supported |
supports_noise_model |
bool
|
Whether noise modeling is supported |
software_version |
str
|
Backend software version |
qubitos.client.hal.MeasurementResult
dataclass
¶
MeasurementResult(
request_id: str,
pulse_id: str,
bitstring_counts: dict[str, int],
total_shots: int,
successful_shots: int,
fidelity_estimate: float | None = None,
state_vector: list[tuple[float, float]] | None = None,
)
Result of a pulse execution.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Unique request identifier |
pulse_id |
str
|
Pulse identifier |
bitstring_counts |
dict[str, int]
|
Dictionary mapping bitstrings to counts |
total_shots |
int
|
Total number of shots requested |
successful_shots |
int
|
Number of successful shots |
fidelity_estimate |
float | None
|
Estimated gate fidelity (if computed) |
state_vector |
list[tuple[float, float]] | None
|
State vector as list of (real, imag) tuples (if requested) |
qubitos.client.hal.HealthCheckResult
dataclass
¶
HealthCheckResult(
status: HealthStatus,
message: str = "",
backends: dict[str, HealthStatus] = dict(),
)
Result of a health check.
Attributes:
| Name | Type | Description |
|---|---|---|
status |
HealthStatus
|
Overall health status |
message |
str
|
Optional status message |
backends |
dict[str, HealthStatus]
|
Per-backend health status |