Skip to content

Quantum Bayesian Network Sampling

pyagrum.qBNSampling provides a quantum-circuit encoding of Bayesian networks and a quantum rejection-sampling inference engine, built on top of Qiskit and the Aer simulator.

The module contains two classes:

  • qBNMC — encodes a BayesNet as a quantum circuit so that measuring the circuit samples from the network’s joint distribution.
  • qBNRejection — runs quantum rejection sampling on top of a qBNMC circuit to compute posterior distributions conditioned on evidence.
import pyagrum as gum
import pyagrum.qBNSampling as qBNS
bn = gum.loadBN("asia.bif")
## Build the quantum circuit encoding
qbn = qBNS.qBNMC(bn)
marginals = qbn.runBN(shots=10000) # dict[str, Tensor]
## Quantum rejection-sampling inference
ie = qBNS.qBNRejection(qbn)
ie.setEvidence({"dyspnoea": 1})
ie.makeInference()
print(ie.posterior("bronchitis"))

Based on Borujeni et al. [BNN+21].

Each variable in the Bayesian network is mapped to ⌈log₂(domainSize)⌉ qubits (equation 21 of the paper). The CPT of each node is encoded via multi-qubit RY rotations (Section 3.2, Fig. 5):

  • root nodes receive unconditional rotations;
  • non-root nodes receive controlled rotations, one block per parent configuration, with X-gate framing to select the correct control state.

Measuring all qubits of the resulting circuit samples from the joint distribution of the network.

Bases: object

Quantum circuit representation of a Bayesian network.

Encodes a pyAgrum BayesNet into a quantum circuit using multi-qubit RY rotations so that measuring the circuit samples from the joint distribution of the network.

Based on: Quantum circuit representation of Bayesian networks, Sima E. Borujeni.

  • Parameters: bn (BayesNet) – pyAgrum Bayesian network to encode.

The encoded Bayesian network.

Maps each node ID to the list of qubit IDs assigned to it.

  • Type: dict[int, list[int]]

Run a circuit on the Aer simulator and return marginal probabilities.

  • Parameters:
    • circuit (QuantumCircuit) – Circuit to run (must contain measurements).
    • shots (int) – Number of shots (default 10000).
  • Returns: Variable name → probability vector over its domain.
  • Return type: dict[str, list[float]]

Build the quantum circuit encoding the Bayesian network.

  • Parameters:
    • add_measure (bool) – If True (default), append measurement gates to all qubits.
    • verbose (int)
  • Returns: The compiled quantum circuit.
  • Return type: QuantumCircuit

All parent-state combinations for a given node.

  • Parameters: node (str | int) – Variable name or node ID.
  • Returns: One dict per combination mapping parent name → state index.
  • Return type: list[dict[str | int, int]]

getBinarizedParameters(width_dict, param_dict)

Section titled “getBinarizedParameters(width_dict, param_dict)”

Binary-encode variable states.

  • Parameters:
    • width_dict (dict[str | int, int]) – Variable name → qubit width (see getWidth()).
    • param_dict (dict[str | int, int]) – Variable name → integer state.
  • Returns: Node ID → binary string as a list of 0s and 1s.
  • Return type: dict[int, list[int]]

getProbability(value, node, qb_id, param_qbs, param_nodes=None, verbose=0)

Section titled “getProbability(value, node, qb_id, param_qbs, param_nodes=None, verbose=0)”

Conditional probability for one qubit given context (eq18/eq20).

  • Parameters:
    • value (int) – Target qubit state: 0 or 1.
    • node (str | int) – Variable name or node ID owning the qubit.
    • qb_id (int) – Global qubit index in the circuit.
    • param_qbs (dict[int, int]) – Other qubits of the same variable already fixed (global id → value).
    • param_nodes (dict[str | int, int] | None) – Parent variable states (name → state index).
    • verbose (int)
  • Returns: Probability value.
  • Return type: float

Quantum registers for the Bayesian network circuit.

  • Returns: Node ID → QuantumRegister sized to hold the variable.
  • Return type: dict[int, QuantumRegister]

IDs of root nodes (no parents) in the DAG.

  • Returns: Set of root node IDs.
  • Return type: set[int]

Total number of qubits required for the full circuit.

  • Returns: Sum of widths over all nodes.
  • Return type: int

Number of qubits needed to represent a variable.

  • Parameters: node (str | int) – Variable name or node ID.
  • Returns: Ceiling of log2 of the variable’s domain size.
  • Return type: int

indicatorFunction(binary_list, targets, verbose=0)

Section titled “indicatorFunction(binary_list, targets, verbose=0)”

Match binary strings against target conditions (eq17/eq19).

  • Parameters:
    • binary_list (list[list[int]]) – Basis states as lists of 0s and 1s.
    • targets (dict[int, int]) – Relative qubit index → required value.
    • verbose (int)
  • Returns: True where the binary string satisfies all target conditions.
  • Return type: list[bool]

Map node IDs to lists of qubit IDs.

  • Parameters: nodes (set[int]) – Node IDs from the Bayesian network.
  • Returns: Node ID → list of assigned qubit IDs.
  • Return type: dict[int, list[int]]

multiQubitRotation(circuit, node, target_qbs, param_qbs, param_nodes=None, control_qbs=None, verbose=0)

Section titled “multiQubitRotation(circuit, node, target_qbs, param_qbs, param_nodes=None, control_qbs=None, verbose=0)”

Add multi-qubit RY rotations to the circuit (Fig9/eq18).

Recursively encodes the CPT probabilities of node into controlled RY rotations on target_qbs.

  • Parameters:
    • circuit (QuantumCircuit) – Circuit to modify in place.
    • node (str | int) – Variable name or node ID being encoded.
    • target_qbs (list[int]) – Global qubit IDs representing the variable.
    • param_qbs (dict[int, int]) – Same-variable qubits already set in the recursion (global id → value).
    • param_nodes (dict[str | int, int] | None) – Parent variable conditioning states.
    • control_qbs (list[int] | None) – Qubit IDs of parent registers used as controls.
    • verbose (int)
  • Return type: None

Build and run the circuit; return marginals as Tensors.

  • Parameters: shots (int) – Number of shots (default 10000).
  • Returns: Variable name → pyAgrum Tensor with marginal probabilities.
  • Return type: dict[str, Tensor]

Based on Low et al. [LYC14].

Inference is performed via quantum rejection sampling with Grover-based amplitude amplification (Algorithm 1 of the paper). The key operators are:

  • A — the sample-preparation circuit (the qBNMC circuit without measurement).
  • G = S_e A⁻¹ S₀ A — the Grover iterate, where S_e is a phase flip on the evidence qubits and S₀ is a phase flip on the all-zero state.

Each call to getSample() runs Algorithm 1: it applies G^{⌈2^k⌉} for increasing k until a measurement consistent with the evidence is obtained.

class pyagrum.qBNSampling.qBNRejection(qbn)

Section titled “class pyagrum.qBNSampling.qBNRejection(qbn)”

Bases: object

Quantum rejection-sampling inference on a Bayesian network.

Implements the quantum rejection-sampling algorithm to compute posterior distributions conditioned on evidence, using a quantum circuit encoding of the Bayesian network (Grover-based amplitude amplification).

Based on: Quantum Inference on Bayesian Networks, Guang Hao Low.

  • Parameters: qbn (qBNMC) – Quantum Bayesian network object built from qBNMC.

The underlying quantum Bayesian network.

Quantum registers used to build rotation gates.

  • Type: dict[int, QuantumRegister]

Current evidence: variable name → state index.

  • Type: dict[str or int, int]

Maximum number of rejection-sampling iterations (default 1000).

  • Type: int

Compose the sample-preparation operator A onto the circuit.

  • Parameters: circuit (QuantumCircuit) – Circuit to extend in place.
  • Return type: None

Apply X gates to evidence qubits with state 0 (eq7 phase flip helper).

  • Parameters:
    • circuit (QuantumCircuit) – Circuit to extend in place.
    • evidence_qbs (dict[int, int]) – Qubit ID → required quantum state.
  • Return type: None

Compose one Grover iterate G = S_e A^{-1} S_0 A onto the circuit.

  • Parameters:
    • circuit (QuantumCircuit) – Circuit to extend in place.
    • A (QuantumCircuit) – Sample-preparation circuit.
    • evidence_qbs (dict[int, int]) – Qubit ID → required quantum state for the evidence flip S_e.
  • Return type: None

Compose the adjoint of M onto the circuit.

  • Parameters:
    • circuit (QuantumCircuit) – Circuit to extend in place.
    • M (QuantumCircuit) – Circuit whose inverse is appended.
  • Return type: None

Apply the phase-flip operator S = B Z B† (eq7).

  • Parameters:
    • circuit (QuantumCircuit) – Circuit to extend in place.
    • evidence_qbs (dict[int, int]) – Qubit ID → required quantum state.
  • Return type: None

Apply a (multi-controlled) Z gate over evidence qubits (eq7).

  • Parameters:
    • circuit (QuantumCircuit) – Circuit to extend in place.
    • evidence_qbs (dict[int, int]) – Qubit ID → required quantum state.
  • Return type: None

Convert node-level evidence to qubit-level evidence.

  • Parameters: evidence (dict[int, int]) – Node ID → state index.
  • Returns: Qubit ID → qubit state (0 or 1).
  • Return type: dict[int, int]

Precompute and cache operators A and G for the current evidence.

  • Return type: None

Draw one sample consistent with evidence using Algorithm 1.

  • Parameters:
    • A (QuantumCircuit) – Sample-preparation circuit.
    • G (QuantumCircuit) – Grover iterate circuit.
    • evidence (dict[str | int, int]) – Variable name → required state.
    • verbose (int)
  • Returns: Node ID → sampled state.
  • Return type: dict[int, int]

Run rejection sampling and accumulate marginal probabilities.

Uses precomputed gates if available, otherwise calls getGates().

  • Parameters: verbose (int) – 0 = silent, 1 = per-iteration stats, 2 = full debug.
  • Returns: Variable name → probability vector over its domain.
  • Return type: dict[str, list[float]]

Current maximum iteration count.

  • Return type: int

Return the posterior distribution of a variable as a Tensor.

Calls makeInference() if results are not yet available.

  • Parameters: node (str | int) – Variable name or node ID.
  • Returns: pyAgrum Tensor with the posterior probability vector.
  • Return type: Tensor

Set the evidence for subsequent inference calls.

  • Parameters: evidence (dict[str | int, int]) – Variable name → observed state index.
  • Return type: None

Set the maximum number of rejection-sampling iterations.

  • Parameters: max_iter (int) – Iteration cap (default 1000).
  • Return type: None

Transpile cached A and G to optimisation level 3.

  • Return type: None

Restrict the network to the ancestors of target and evidence nodes.

Replaces the internal qBNMC with one built from the minimal BayesNetFragment covering all relevant nodes.

  • Parameters:
    • evidence (set[str | int] | None) – Additional evidence nodes (beyond those in evidence).
    • target (set[str | int] | None) – Target query nodes.
  • Return type: None