Workflow: Formulation and Sampling
Every computation on Dynex follows the same pattern: define a model, configure a backend, sample, and analyze results.
Full Example
import dynex
import dimod
from dynex import DynexConfig, ComputeBackend
# Step 1: Build the problem model
bqm = dimod.BinaryQuadraticModel(
{0: -1.0, 1: -1.0},
{(0, 1): 2.0},
0.0,
'BINARY'
)
# Step 2: Configure the compute backend (GPU = Dynex neuromorphic chips)
config = DynexConfig(compute_backend=ComputeBackend.GPU)
# Step 3: Wrap model and create sampler
model = dynex.BQM(bqm)
sampler = dynex.DynexSampler(model, config=config, description="My optimization job")
# Step 4: Sample
sampleset = sampler.sample(
num_reads=1000,
annealing_time=200,
shots=5,
)
# Step 5: Inspect results
best = sampleset.first
print(f"Best sample: {best.sample}")
print(f"Best energy: {best.energy}")
# Iterate over all samples
for sample, energy in sampleset.data(['sample', 'energy']):
print(f" {sample} → energy {energy:.4f}")
Step 1: Choose a Model Type
Select the model class that best fits your problem:
| Model | Class | Use when |
|---|
| Binary Quadratic Model | dynex.BQM | Natural QUBO/Ising formulation |
| Constrained Quadratic Model | dynex.CQM | Constraints are central to the problem |
| Discrete Quadratic Model | dynex.DQM | Variables have more than 2 possible values |
See Defining Models for detailed examples of each type.
Step 2: Choose a Compute Backend
from dynex import DynexConfig, ComputeBackend, QPUModel
# GPU — Dynex neuromorphic chips, primary production backend
config = DynexConfig(compute_backend=ComputeBackend.GPU)
# QPU — specific quantum hardware model
config = DynexConfig(
compute_backend=ComputeBackend.QPU,
qpu_model=QPUModel.APOLLO_RC1
)
# CPU — lightweight network jobs and connectivity testing
config = DynexConfig(compute_backend=ComputeBackend.CPU)
# LOCAL — offline testing, no credentials required
config = DynexConfig(compute_backend=ComputeBackend.LOCAL)
Use GPU for all production workloads — it runs on Dynex’s own neuromorphic chips distributed globally. Use LOCAL for offline development and unit tests.
Step 3: Build Sampler
sampler = dynex.DynexSampler(
model,
config=config,
description="Optional job description",
logging=True
)
Step 4: Run Sampling
sampleset = sampler.sample(
num_reads=1000, # Number of parallel reads
annealing_time=200, # Integration depth (ODE steps)
shots=5, # Minimum solutions from network
preprocess=False, # Enable preprocessing for QPU
)
Parameter guidance:
| Parameter | GPU (small/test) | GPU (production) | QPU |
|---|
num_reads | 100–500 | 1000–10000 | 1–100 |
annealing_time | 50–200 | 200–1000 | 10–1000 |
shots | 1 | 1–5 | 1–5 |
QPU backends have tighter hardware constraints: num_reads must stay within 1–100, annealing_time within 10–1000, and shots up to 5.
Step 5: Analyze Results
The sampler returns a dimod SampleSet:
# Best solution
best = sampleset.first
print(best.sample) # {0: 1, 1: 0, 2: 1, ...}
print(best.energy) # -3.14159
# All samples sorted by energy
for sample in sampleset.samples():
print(sample)
# As pandas DataFrame
df = sampleset.to_pandas_dataframe()
print(df.head())
# Number of occurrences
for sample, energy, num_occ in sampleset.data(['sample', 'energy', 'num_occurrences']):
print(f"Energy {energy:.3f} occurred {num_occ} times")
Step 6: Iterate
Tune your model and parameters:
- Better solutions → increase
num_reads and annealing_time
- Faster results → decrease
annealing_time, use CPU instead of QPU
- Constrained problems → switch from BQM to CQM
- Large-scale → use QPU backend with
preprocess=True
Migrating from legacy SDK
| Legacy | Current |
|---|
sampler.sample(..., mainnet=True) | DynexConfig(compute_backend=ComputeBackend.CPU) |
sampler.sample(..., mainnet=False) | DynexConfig(compute_backend=ComputeBackend.LOCAL) |
sampler.sample(..., v2=True) | Remove v2=True — no longer needed |
| REST-based communication | gRPC-based communication (automatic) |