Skip to main content

Dynex SDK

Dynex provides a qubit-agnostic computing platform designed to unify diverse quantum and quantum-driven compute resources under a single execution and programming environment. The Dynex SDK enables users to access heterogeneous compute modalities through a consistent workflow for optimization, simulation, and probabilistic workloads—without requiring direct exposure to device-specific implementations. It is compatible with PennyLane, IBM Qiskit, OpenQAM, Dimod, PyQUBO, and the Ocean SDK.

Documentation & Examples

Installation

Install with uv (recommended)

uv add dynex

Install with pip

pip install dynex

Install uv

If you don't have uv yet:

curl -LsSf https://astral.sh/uv/install.sh | sh

Or via Homebrew on macOS:

brew install uv

Quick Start

import dynex
import dimod

# Create BQM
bqm = dimod.BinaryQuadraticModel({0: 1.0, 1: -1.0}, {(0, 1): 0.5}, 0.0, 'BINARY')

# Create sampler and sample
model = dynex.BQM(bqm)
sampler = dynex.DynexSampler(model)
sampleset = sampler.sample(num_reads=10)

print(sampleset.first.sample)

Configuration

Environment Variables

Set credentials via environment variables or .env file:

DYNEX_SDK_KEY=your_sdk_key
DYNEX_GRPC_ENDPOINT=quantum-router-engine-grpc.hz.dynex.co:3000

Compute Backends

Dynex SDK supports three compute backends via the ComputeBackend enum:

from dynex import DynexConfig, ComputeBackend

# Using enum (recommended)
config = DynexConfig(compute_backend=ComputeBackend.QPU)

# Using string (also supported)
config = DynexConfig(compute_backend="qpu")

1. CPU Backend (Default)

Efficient quantum emulation on CPU providing up to 1,000,000 algorithmic qubits:

config = DynexConfig(compute_backend=ComputeBackend.CPU)
sampler = dynex.DynexSampler(model, config=config)
sampleset = sampler.sample(num_reads=100)

2. GPU Backend

GPU-accelerated quantum emulation of up to 1,000,000 algorithmic qubits:

config = DynexConfig(compute_backend=ComputeBackend.GPU)
sampler = dynex.DynexSampler(model, config=config)
sampleset = sampler.sample(num_reads=100)

3. QPU Backend

Access to Quantum Processing Units (QPUs), including Dynex's proprietary quantum hardware (Apollo and Zeus series) and integrated third-party QPUs (IBM, IonQ, Rigetti, D-Wave, QuEra and IQM) via Dynex's Qubit-Agnostic Quantum Platform:

from dynex import QPUModel

# Using QPUModel enum (recommended)
config = DynexConfig(
    compute_backend=ComputeBackend.QPU,
    qpu_model=QPUModel.APOLLO_RC1  # or other supported QPUs
)

# Or using string
config = DynexConfig(
    compute_backend=ComputeBackend.QPU,
    qpu_model="apollo_rc1"  # or other supported QPUs
)

sampler = dynex.DynexSampler(model, config=config)
sampleset = sampler.sample(num_reads=10, annealing_time=500)

Advanced Usage

Returning Ranked Solutions

Use rank to return more than the single best Modal solution on CPU or GPU. The value must be between 1 and num_reads:

sampleset = sampler.sample(num_reads=32, rank=5)

The returned dimod.SampleSet contains up to five solver-ranked solutions per atomic, applied to every requested shot. QPU does not support rank and continues to return the reads produced by the QPU agent.

BQM Preprocessing

Scale BQM coefficients for QPU compatibility:

import dynex
from dynex import ComputeBackend

# Scale to QPU range
scaled_bqm, scale_factor = dynex.scale_bqm_to_range(bqm, max_abs_coeff=9.0)
model = dynex.BQM(scaled_bqm)

# Sample on QPU
config = DynexConfig(compute_backend=ComputeBackend.QPU, qpu_model=QPUModel.APOLLO_RC1)
sampler = dynex.DynexSampler(model, config=config)
sampleset = sampler.sample(num_reads=10, qpu_max_coeff=9.0)

# Scale energy back
original_energy = sampleset.first.energy / scale_factor

Custom Configuration

Configure SDK behavior through DynexConfig:

config = DynexConfig(
    sdk_key="your_sdk_key",
    compute_backend="cpu",
    # Environment parameters (set via config only)
    use_notebook_output=True,      # Dynamic table updates in Jupyter (default: True)
    default_timeout=600.0,          # Max wait time for solutions in seconds (default: 300.0)
    # Job parameters (can override in sampler)
    default_description="My Job",   # Default job description
    preserve_solutions=False,       # Keep solution files after processing (default: False)
)

sampler = dynex.DynexSampler(model, config=config)

# Job parameters can be overridden per sampler
sampler = dynex.DynexSampler(
    model,
    config=config,
    description="Custom Job",        # Override default_description
    preserve_solutions=True,          # Override preserve_solutions
)

Configuration Parameters:

Environment Parameters (config only):

  • use_notebook_output - Enable dynamic table updates in Jupyter Notebook (default: True)
    • True: Table updates in-place with clear_output() (Jupyter)
    • False: Each table printed separately (console/scripts)
  • default_timeout - Maximum wait time for solutions in seconds (default: 300.0)

Job Parameters (config + override):

  • default_description - Default job description (default: "Dynex SDK Job")
  • preserve_solutions - Keep solution files after processing (default: False)

Constrained Quadratic Models (CQM)

from dimod import ConstrainedQuadraticModel, Binary

# Create CQM
cqm = ConstrainedQuadraticModel()
x = [Binary(f'x{i}') for i in range(5)]

# Add objective
cqm.set_objective(sum(x[i] * x[i+1] for i in range(4)))

# Add constraint
cqm.add_constraint(sum(x) == 2)

# Sample
model = dynex.CQM(cqm)
sampler = dynex.DynexSampler(model)
sampleset = sampler.sample(num_reads=10)

Discrete Quadratic Models (DQM)

from dimod import DiscreteQuadraticModel

# Create DQM
dqm = DiscreteQuadraticModel()
dqm.add_variable(3)  # variable with 3 states
dqm.add_variable(2)  # variable with 2 states

# Set interactions
dqm.set_linear(0, [1.0, 2.0, 3.0])
dqm.set_quadratic(0, 1, {(0, 0): 1.0, (1, 1): -1.0})

# Sample
model = dynex.DQM(dqm)
sampler = dynex.DynexSampler(model)
sampleset = sampler.sample(num_reads=10)

Logging & Monitoring

Dynex SDK provides comprehensive logging with platform-specific prefixes and detailed timing information.

Enable Logging

import logging

logging.basicConfig(level=logging.INFO)

model = dynex.BQM(bqm, logging=True)
sampler = dynex.DynexSampler(model, config=config)

Log Output Features

Platform Identification:

INFO: [DYNEX-APOLLO-RC1] SAMPLER INITIALISED
INFO: [DYNEX-CPU] SAMPLER INITIALISED
INFO: [DYNEX-GPU] SAMPLER INITIALISED

Problem Settings Summary:

INFO: [DYNEX-APOLLO-RC1] Problem: 400 qubits, 15600 gates
INFO: [DYNEX-APOLLO-RC1] Settings: num_reads=5, shots=3, annealing_time=100

Validation Warnings:

WARNING: [DYNEX-APOLLO-RC1] annealing_time=10 might be short for 400 qubits
WARNING: [DYNEX-APOLLO-RC1] num_reads=100 is very high, consider reducing for faster testing

Shot Progress Tracking:

INFO: [DYNEX-APOLLO-RC1] Shot 1/3 received
INFO: [DYNEX-APOLLO-RC1] Shot 2/3 received
INFO: [DYNEX-APOLLO-RC1] Shot 3/3 received

Timing Breakdown:

INFO: [DYNEX-APOLLO-RC1] Average time per shot: 4.60s (3 shots in 13.80s)
INFO: [DYNEX-APOLLO-RC1] Timing breakdown:
INFO: [DYNEX-APOLLO-RC1]   Job upload:        0.34s
INFO: [DYNEX-APOLLO-RC1]   Time to 1st shot:  7.08s
INFO: [DYNEX-APOLLO-RC1]   Compute (Apollo):  13.80s
INFO: [DYNEX-APOLLO-RC1]   Solution download: 0.15s
INFO: [DYNEX-APOLLO-RC1]   Total elapsed:     14.29s

BQM Scaling Information:

INFO: [DYNEX-APOLLO-RC1] Auto-scaling BQM for QPU: max_abs_coeff=3109.17 > 9.0
INFO: [DYNEX-APOLLO-RC1] BQM scaled by factor 0.002895 for optimal QPU performance

Result Table

The SDK displays a comprehensive result table showing job details:

╭────────────┬──────────┬─────────┬─────────────┬─────────┬────────────┬───────────┬───────────┬────────────────╮
│   DYNEXJOB │   QUBITS │   GATES │   NUM_READS │   SHOTS │   ANN.TIME │ ELAPSED   │   WORKERS │   GROUND STATE │
├────────────┼──────────┼─────────┼─────────────┼─────────┼────────────┼───────────┼───────────┼────────────────┤
│       3462 │      400 │   15600 │           5 │       3 │        100 │ 14.29s    │         3 │         179.00 │
╰────────────┴──────────┴─────────┴─────────────┴─────────┴────────────┴───────────┴───────────┴────────────────╯

Columns:

  • DYNEXJOB - Job ID on Dynex network
  • QUBITS - Number of problem variables
  • GATES - Number of quantum gates/interactions
  • NUM_READS - Parallel samples per worker
  • SHOTS - Minimum solutions requested from network
  • ANN.TIME - Annealing time per sample
  • ELAPSED - Total elapsed time
  • WORKERS - Number of workers contributed
  • GROUND STATE - Best energy found

Development

Clone the repo and set up the environment with a single command:

git clone https://github.com/Dynex-Development/py-sdk
cd py-sdk
make install

This runs uv sync --group dev — creates .venv and installs all dependencies from the lockfile.

Running tests

make test-unit          # unit tests
make test-integration   # integration tests (needs .env with credentials)
make test               # all tests

Or directly via uv:

uv run pytest tests/unit/ -v

Code quality

make format   # black + isort
make check    # check without changes
make lint     # flake8

Adding dependencies

uv add <package>              # runtime dependency
uv add --group dev <package>  # dev-only dependency
uv lock                       # regenerate lockfile after manual edits to pyproject.toml

Building

make build    # produces dist/dynex-*.whl and dist/dynex-*.tar.gz

License

BSD-3-Clause

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dynex-1.4.7.tar.gz (268.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dynex-1.4.7-py3-none-any.whl (96.3 kB view details)

Uploaded Python 3

File details

Details for the file dynex-1.4.7.tar.gz.

File metadata

  • Download URL: dynex-1.4.7.tar.gz
  • Upload date:
  • Size: 268.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dynex-1.4.7.tar.gz
Algorithm Hash digest
SHA256 a3373bd995fa12353e18f246ee97404ec3172626559d558938791682c439c012
MD5 0c86765145e2d0547c31529a31210d2d
BLAKE2b-256 0d35395ab5fd42a9e901068a8227945c576c52ef34160b8aedf2d0b33c9851b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for dynex-1.4.7.tar.gz:

Publisher: publish.yaml on Dynex-Development/py-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dynex-1.4.7-py3-none-any.whl.

File metadata

  • Download URL: dynex-1.4.7-py3-none-any.whl
  • Upload date:
  • Size: 96.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dynex-1.4.7-py3-none-any.whl
Algorithm Hash digest
SHA256 93983c30c3da6e2baa2e0bf675dde5789e0c8a75880052cdaba4fd3bfcc8f6e2
MD5 f72c1e5a0bb51c4c2f791c8e1f1a964a
BLAKE2b-256 ca4c5a322af9cbd278187afaeee6fd0dcc52a8a65dec0fa462cad67aa2fb5608

See more details on using hashes here.

Provenance

The following attestation bundles were made for dynex-1.4.7-py3-none-any.whl:

Publisher: publish.yaml on Dynex-Development/py-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.4.7 This release

2 files

1.4.6

2 files

1.4.5

2 files

1.4.4

2 files

1.4.3

2 files

1.4.2

2 files

1.4.1

2 files

1.4.0

2 files

1.3.3

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page