Skip to content

sampler

Compiled samplers for measurements and detectors.

CompiledDetectorSampler

CompiledDetectorSampler(
    circuit: Circuit, *, seed: int | None = None
)

Bases: _CompiledSamplerBase


              flowchart TD
              tsim.sampler.CompiledDetectorSampler[CompiledDetectorSampler]
              tsim.sampler._CompiledSamplerBase[_CompiledSamplerBase]

                              tsim.sampler._CompiledSamplerBase --> tsim.sampler.CompiledDetectorSampler
                


              click tsim.sampler.CompiledDetectorSampler href "" "tsim.sampler.CompiledDetectorSampler"
              click tsim.sampler._CompiledSamplerBase href "" "tsim.sampler._CompiledSamplerBase"
            

Samples detector and observable outcomes from a quantum circuit.

Parameters:

Name Type Description Default
circuit Circuit

The quantum circuit to compile.

required
seed int | None

Random seed for JAX. If None, a random seed is generated.

None
Source code in src/tsim/sampler.py
281
282
283
284
285
286
287
288
289
def __init__(self, circuit: Circuit, *, seed: int | None = None):
    """Create a detector sampler.

    Args:
        circuit: The quantum circuit to compile.
        seed: Random seed for JAX. If None, a random seed is generated.

    """
    super().__init__(circuit, sample_detectors=True, mode="sequential", seed=seed)

sample

sample(
    shots: int,
    *,
    batch_size: int | None = None,
    prepend_observables: bool = False,
    append_observables: bool = False,
    separate_observables: Literal[True],
    bit_packed: bool = False
) -> tuple[np.ndarray, np.ndarray]
sample(
    shots: int,
    *,
    batch_size: int | None = None,
    prepend_observables: bool = False,
    append_observables: bool = False,
    separate_observables: Literal[False] = False,
    bit_packed: bool = False
) -> np.ndarray
sample(
    shots: int,
    *,
    batch_size: int | None = None,
    prepend_observables: bool = False,
    append_observables: bool = False,
    separate_observables: bool = False,
    bit_packed: bool = False
) -> np.ndarray | tuple[np.ndarray, np.ndarray]

Return detector samples from the circuit.

The circuit must define the detectors using DETECTOR instructions. Observables defined by OBSERVABLE_INCLUDE instructions can also be included in the results as honorary detectors.

Parameters:

Name Type Description Default
shots int

The number of times to sample every detector in the circuit.

required
batch_size int | None

The number of samples to process in each batch. When using a GPU, it is recommended to increase this value until VRAM is fully utilized for maximum performance.

None
separate_observables bool

Defaults to False. When set to True, the return value is a (detection_events, observable_flips) tuple instead of a flat detection_events array.

False
prepend_observables bool

Defaults to false. When set, observables are included with the detectors and are placed at the start of the results.

False
append_observables bool

Defaults to false. When set, observables are included with the detectors and are placed at the end of the results.

False
bit_packed bool

Defaults to false. When set, results are bit-packed.

False

Returns:

Type Description
ndarray | tuple[ndarray, ndarray]

A numpy array or tuple of numpy arrays containing the samples.

Source code in src/tsim/sampler.py
315
316
317
318
319
320
321
322
323
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
def sample(
    self,
    shots: int,
    *,
    batch_size: int | None = None,
    prepend_observables: bool = False,
    append_observables: bool = False,
    separate_observables: bool = False,
    bit_packed: bool = False,
) -> np.ndarray | tuple[np.ndarray, np.ndarray]:
    """Return detector samples from the circuit.

    The circuit must define the detectors using DETECTOR instructions. Observables
    defined by OBSERVABLE_INCLUDE instructions can also be included in the results
    as honorary detectors.

    Args:
        shots: The number of times to sample every detector in the circuit.
        batch_size: The number of samples to process in each batch. When using a
            GPU, it is recommended to increase this value until VRAM is fully
            utilized for maximum performance.
        separate_observables: Defaults to False. When set to True, the return value
            is a (detection_events, observable_flips) tuple instead of a flat
            detection_events array.
        prepend_observables: Defaults to false. When set, observables are included
            with the detectors and are placed at the start of the results.
        append_observables: Defaults to false. When set, observables are included
            with the detectors and are placed at the end of the results.
        bit_packed: Defaults to false. When set, results are bit-packed.

    Returns:
        A numpy array or tuple of numpy arrays containing the samples.

    """
    samples = self._sample_batches(shots, batch_size)

    if append_observables:
        return _maybe_bit_pack(samples, bit_packed=bit_packed)

    num_detectors = self._num_detectors
    det_samples = samples[:, :num_detectors]
    obs_samples = samples[:, num_detectors:]

    if prepend_observables:
        combined = np.concatenate([obs_samples, det_samples], axis=1)
        return _maybe_bit_pack(combined, bit_packed=bit_packed)
    if separate_observables:
        return (
            _maybe_bit_pack(det_samples, bit_packed=bit_packed),
            _maybe_bit_pack(obs_samples, bit_packed=bit_packed),
        )

    return _maybe_bit_pack(det_samples, bit_packed=bit_packed)

CompiledMeasurementSampler

CompiledMeasurementSampler(
    circuit: Circuit, *, seed: int | None = None
)

Bases: _CompiledSamplerBase


              flowchart TD
              tsim.sampler.CompiledMeasurementSampler[CompiledMeasurementSampler]
              tsim.sampler._CompiledSamplerBase[_CompiledSamplerBase]

                              tsim.sampler._CompiledSamplerBase --> tsim.sampler.CompiledMeasurementSampler
                


              click tsim.sampler.CompiledMeasurementSampler href "" "tsim.sampler.CompiledMeasurementSampler"
              click tsim.sampler._CompiledSamplerBase href "" "tsim.sampler._CompiledSamplerBase"
            

Samples measurement outcomes from a quantum circuit.

Uses sequential decomposition [0, 1, 2, ..., n] where: - compiled_scalar_graphs[0]: normalization (0 outputs plugged) - compiled_scalar_graphs[i]: cumulative probability up to bit i

Parameters:

Name Type Description Default
circuit Circuit

The quantum circuit to compile.

required
seed int | None

Random seed for JAX. If None, a random seed is generated.

None
Source code in src/tsim/sampler.py
245
246
247
248
249
250
251
252
253
def __init__(self, circuit: Circuit, *, seed: int | None = None):
    """Create a measurement sampler.

    Args:
        circuit: The quantum circuit to compile.
        seed: Random seed for JAX. If None, a random seed is generated.

    """
    super().__init__(circuit, sample_detectors=False, mode="sequential", seed=seed)

sample

sample(shots: int, *, batch_size: int = 1024) -> np.ndarray

Sample measurement outcomes from the circuit.

Parameters:

Name Type Description Default
shots int

The number of times to sample every measurement in the circuit.

required
batch_size int

The number of samples to process in each batch. When using a GPU, it is recommended to increase this value until VRAM is fully utilized for maximum performance.

1024

Returns:

Type Description
ndarray

A numpy array containing the measurement samples.

Source code in src/tsim/sampler.py
255
256
257
258
259
260
261
262
263
264
265
266
267
268
def sample(self, shots: int, *, batch_size: int = 1024) -> np.ndarray:
    """Sample measurement outcomes from the circuit.

    Args:
        shots: The number of times to sample every measurement in the circuit.
        batch_size: The number of samples to process in each batch. When using a
            GPU, it is recommended to increase this value until VRAM is fully
            utilized for maximum performance.

    Returns:
        A numpy array containing the measurement samples.

    """
    return self._sample_batches(shots, batch_size)

CompiledStateProbs

CompiledStateProbs(
    circuit: Circuit,
    *,
    sample_detectors: bool = False,
    seed: int | None = None
)

Bases: _CompiledSamplerBase


              flowchart TD
              tsim.sampler.CompiledStateProbs[CompiledStateProbs]
              tsim.sampler._CompiledSamplerBase[_CompiledSamplerBase]

                              tsim.sampler._CompiledSamplerBase --> tsim.sampler.CompiledStateProbs
                


              click tsim.sampler.CompiledStateProbs href "" "tsim.sampler.CompiledStateProbs"
              click tsim.sampler._CompiledSamplerBase href "" "tsim.sampler._CompiledSamplerBase"
            

Computes measurement probabilities for a given state.

Uses joint decomposition [0, n] where: - compiled_scalar_graphs[0]: normalization (0 outputs plugged) - compiled_scalar_graphs[1]: full joint probability (all outputs plugged)

Parameters:

Name Type Description Default
circuit Circuit

The quantum circuit to compile.

required
sample_detectors bool

If True, compute detector/observable probabilities.

False
seed int | None

Random seed for JAX. If None, a random seed is generated.

None
Source code in src/tsim/sampler.py
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
def __init__(
    self,
    circuit: Circuit,
    *,
    sample_detectors: bool = False,
    seed: int | None = None,
):
    """Create a probability estimator.

    Args:
        circuit: The quantum circuit to compile.
        sample_detectors: If True, compute detector/observable probabilities.
        seed: Random seed for JAX. If None, a random seed is generated.

    """
    super().__init__(
        circuit, sample_detectors=sample_detectors, mode="joint", seed=seed
    )

probability_of

probability_of(
    state: ndarray, *, batch_size: int
) -> np.ndarray

Compute probabilities for a batch of error samples given a measurement state.

Parameters:

Name Type Description Default
state ndarray

The measurement outcome state to compute probability for.

required
batch_size int

Number of error samples to use for estimation.

required

Returns:

Type Description
ndarray

Array of probabilities P(state | error_sample) for each error sample.

Source code in src/tsim/sampler.py
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
428
429
def probability_of(self, state: np.ndarray, *, batch_size: int) -> np.ndarray:
    """Compute probabilities for a batch of error samples given a measurement state.

    Args:
        state: The measurement outcome state to compute probability for.
        batch_size: Number of error samples to use for estimation.

    Returns:
        Array of probabilities P(state | error_sample) for each error sample.

    """
    f_samples = jnp.asarray(self._channel_sampler.sample(batch_size))
    p_norm = jnp.ones(batch_size)
    p_joint = jnp.ones(batch_size)

    for component in self._program.components:
        assert len(component.compiled_scalar_graphs) == 2

        f_selected = f_samples[:, component.f_selection]

        norm_circuit, joint_circuit = component.compiled_scalar_graphs

        # Normalization: only f-params
        p_norm = p_norm * jnp.abs(evaluate(norm_circuit, f_selected))

        # Joint probability: f-params + state
        component_state = state[list(component.output_indices)]
        tiled_state = jnp.tile(component_state, (batch_size, 1))
        joint_params = jnp.hstack([f_selected, tiled_state])
        p_joint = p_joint * jnp.abs(evaluate(joint_circuit, joint_params))

    return np.asarray(p_joint / p_norm)

sample_component

sample_component(
    component: CompiledComponent,
    f_params: Array,
    key: Array,
) -> tuple[jax.Array, PRNGKey]

Sample outputs from a single component using autoregressive sampling.

Parameters:

Name Type Description Default
component CompiledComponent

The compiled component to sample from.

required
f_params Array

Error parameters, shape (batch_size, num_f_params).

required
key Array

JAX random key.

required

Returns:

Type Description
Array

Tuple of (samples, next_key) where samples has shape

Array

(batch_size, num_outputs_for_component).

Source code in src/tsim/sampler.py
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
def sample_component(
    component: CompiledComponent,
    f_params: jax.Array,
    key: PRNGKey,
) -> tuple[jax.Array, PRNGKey]:
    """Sample outputs from a single component using autoregressive sampling.

    Args:
        component: The compiled component to sample from.
        f_params: Error parameters, shape (batch_size, num_f_params).
        key: JAX random key.

    Returns:
        Tuple of (samples, next_key) where samples has shape
        (batch_size, num_outputs_for_component).

    """
    # Skip JIT for small components (overhead not worth it)
    if len(component.output_indices) <= 1:
        return _sample_component(component, f_params, key)
    return _sample_component_jit(component, f_params, key)

sample_program

sample_program(
    program: CompiledProgram, f_params: Array, key: Array
) -> jax.Array

Sample all outputs from a compiled program.

Parameters:

Name Type Description Default
program CompiledProgram

The compiled program to sample from.

required
f_params Array

Error parameters, shape (batch_size, num_f_params).

required
key Array

JAX random key.

required

Returns:

Type Description
Array

Samples array of shape (batch_size, num_outputs), reordered to

Array

match the original output indices.

Source code in src/tsim/sampler.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def sample_program(
    program: CompiledProgram,
    f_params: jax.Array,
    key: PRNGKey,
) -> jax.Array:
    """Sample all outputs from a compiled program.

    Args:
        program: The compiled program to sample from.
        f_params: Error parameters, shape (batch_size, num_f_params).
        key: JAX random key.

    Returns:
        Samples array of shape (batch_size, num_outputs), reordered to
        match the original output indices.

    """
    results: list[jax.Array] = []

    for component in program.components:
        samples, key = sample_component(component, f_params, key)
        results.append(samples)

    combined = jnp.concatenate(results, axis=1)
    return combined[:, jnp.argsort(program.output_order)]