Docs/Python SDK

Python SDK

Python 3.9+ · Sync + async · Typed · MIT license

Installation

bash
pip install nerox

# With async support (default, no extra deps needed)
# Or install a specific version:
pip install "nerox==0.9.2"

Authentication

python
import nerox

# From environment variable (recommended)
# export NEROX_API_KEY=nrx_sk_...
client = nerox.Client()

# Or explicitly
client = nerox.Client(api_key="nrx_sk_...")

Synchronous client

The sync client is the simplest way to get started. It blocks until the job completes or until you call .stream().

python
import nerox
import numpy as np

client = nerox.Client()

job = client.optimize.tsp(
    distance_matrix=matrix,
    solver="gpu",
    n_runs=50,
)

# Blocking wait
result = job.wait(timeout=120)    # raises TimeoutError if exceeded
print(result.objective, result.solution)

# Streaming (non-blocking iteration)
for event in job.stream():
    print(event.iteration, event.energy)

Async client

python
import asyncio
import nerox

async def main():
    async with nerox.AsyncClient() as client:
        job = await client.optimize.tsp(
            distance_matrix=matrix,
            solver="gpu",
        )

        # Async streaming
        async for event in job.astream():
            print(event.energy)

        result = await job.result()
        print(result.objective)

asyncio.run(main())

Job object reference

python
job.id              # str — unique job identifier
job.status          # "queued" | "running" | "completed" | "failed"
job.wait()          # blocks until done, returns Result
job.stream()        # iterator of StreamEvent
job.cancel()        # cancel a running job
job.result          # Result object (after completion)

# Result attributes
result.objective    # float — minimized objective value
result.solution     # list — binary vector or tour order
result.runtime_s    # float — wall-clock seconds
result.gpu_seconds  # float — billed GPU time
result.solver       # str — solver name
result.n_iterations # int — total iterations run
result.gap_to_best  # float | None — % above known optimal

Batch submission

python
import nerox

client = nerox.Client()

# Submit multiple jobs in parallel
jobs = client.optimize.batch([
    dict(problem_type="tsp", distance_matrix=m1, solver="gpu"),
    dict(problem_type="tsp", distance_matrix=m2, solver="tabu"),
    dict(problem_type="qubo", Q=Q, solver="qaoa", depth=4),
])

results = [j.wait() for j in jobs]

Error handling

python
from nerox.exceptions import (
    AuthenticationError,   # invalid API key
    RateLimitError,        # quota exceeded
    JobFailedError,        # solver returned error
    TimeoutError,          # job.wait(timeout=...) exceeded
    ValidationError,       # invalid problem input
)

try:
    result = job.wait(timeout=60)
except nerox.JobFailedError as e:
    print(e.reason)        # "matrix_not_square" | "qubo_invalid" | ...
except nerox.RateLimitError:
    print("GPU quota exhausted — check /v1/usage")