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 aBayesNetas a quantum circuit so that measuring the circuit samples from the network’s joint distribution.qBNRejection— runs quantum rejection sampling on top of aqBNMCcircuit to compute posterior distributions conditioned on evidence.
import pyagrum as gumimport pyagrum.qBNSampling as qBNS
bn = gum.loadBN("asia.bif")
## Build the quantum circuit encodingqbn = qBNS.qBNMC(bn)marginals = qbn.runBN(shots=10000) # dict[str, Tensor]
## Quantum rejection-sampling inferenceie = qBNS.qBNRejection(qbn)ie.setEvidence({"dyspnoea": 1})ie.makeInference()print(ie.posterior("bronchitis"))qBNMC — Circuit encoding
Section titled “qBNMC — Circuit encoding”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.
class pyagrum.qBNSampling.qBNMC(bn)
Section titled “class pyagrum.qBNSampling.qBNMC(bn)”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.
- Type: BayesNet
n_qb_map
Section titled “n_qb_map”Maps each node ID to the list of qubit IDs assigned to it.
- Type: dict[int, list[int]]
aerSimulation(circuit, shots=10000)
Section titled “aerSimulation(circuit, shots=10000)”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).
- circuit (
- Returns: Variable name → probability vector over its domain.
- Return type:
dict[str,list[float]]
buildCircuit(add_measure=True, verbose=0)
Section titled “buildCircuit(add_measure=True, verbose=0)”Build the quantum circuit encoding the Bayesian network.
- Parameters:
- add_measure (
bool) – If True (default), append measurement gates to all qubits. - verbose (
int)
- add_measure (
- Returns: The compiled quantum circuit.
- Return type:
QuantumCircuit
getAllParentSates(node)
Section titled “getAllParentSates(node)”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 (seegetWidth()). - param_dict (
dict[str|int,int]) – Variable name → integer state.
- width_dict (
- 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)
- value (
- Returns: Probability value.
- Return type:
float
getQuantumRegisters()
Section titled “getQuantumRegisters()”Quantum registers for the Bayesian network circuit.
- Returns: Node ID → QuantumRegister sized to hold the variable.
- Return type:
dict[int,QuantumRegister]
getRootNodes()
Section titled “getRootNodes()”IDs of root nodes (no parents) in the DAG.
- Returns: Set of root node IDs.
- Return type:
set[int]
getTotNumQBits()
Section titled “getTotNumQBits()”Total number of qubits required for the full circuit.
- Returns: Sum of widths over all nodes.
- Return type:
int
getWidth(node)
Section titled “getWidth(node)”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)
- binary_list (
- Returns: True where the binary string satisfies all target conditions.
- Return type:
list[bool]
mapNodeToQBit(nodes)
Section titled “mapNodeToQBit(nodes)”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)
- circuit (
- Return type:
None
runBN(shots=10000)
Section titled “runBN(shots=10000)”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]
qBNRejection — Quantum inference
Section titled “qBNRejection — Quantum inference”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
qBNMCcircuit 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.
The underlying quantum Bayesian network.
- Type: qBNMC
q_registers
Section titled “q_registers”Quantum registers used to build rotation gates.
- Type: dict[int, QuantumRegister]
evidence
Section titled “evidence”Current evidence: variable name → state index.
- Type: dict[str or int, int]
max_iter
Section titled “max_iter”Maximum number of rejection-sampling iterations (default 1000).
- Type: int
addA(circuit)
Section titled “addA(circuit)”Compose the sample-preparation operator A onto the circuit.
- Parameters:
circuit (
QuantumCircuit) – Circuit to extend in place. - Return type:
None
addB(circuit, evidence_qbs)
Section titled “addB(circuit, evidence_qbs)”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.
- circuit (
- Return type:
None
addG(circuit, A, evidence_qbs)
Section titled “addG(circuit, A, evidence_qbs)”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.
- circuit (
- Return type:
None
addInverse(circuit, M)
Section titled “addInverse(circuit, M)”Compose the adjoint of M onto the circuit.
- Parameters:
- circuit (
QuantumCircuit) – Circuit to extend in place. - M (
QuantumCircuit) – Circuit whose inverse is appended.
- circuit (
- Return type:
None
addS(circuit, evidence_qbs)
Section titled “addS(circuit, evidence_qbs)”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.
- circuit (
- Return type:
None
addZ(circuit, evidence_qbs)
Section titled “addZ(circuit, evidence_qbs)”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.
- circuit (
- Return type:
None
getEvidenceQuBits(evidence)
Section titled “getEvidenceQuBits(evidence)”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]
getGates()
Section titled “getGates()”Precompute and cache operators A and G for the current evidence.
- Return type:
None
getSample(A, G, evidence, verbose=0)
Section titled “getSample(A, G, evidence, verbose=0)”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)
- A (
- Returns: Node ID → sampled state.
- Return type:
dict[int,int]
makeInference(verbose=0)
Section titled “makeInference(verbose=0)”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]]
maxIter()
Section titled “maxIter()”Current maximum iteration count.
- Return type:
int
posterior(node)
Section titled “posterior(node)”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
setEvidence(evidence)
Section titled “setEvidence(evidence)”Set the evidence for subsequent inference calls.
- Parameters:
evidence (
dict[str|int,int]) – Variable name → observed state index. - Return type:
None
setMaxIter(max_iter=1000)
Section titled “setMaxIter(max_iter=1000)”Set the maximum number of rejection-sampling iterations.
- Parameters:
max_iter (
int) – Iteration cap (default 1000). - Return type:
None
transpileGates()
Section titled “transpileGates()”Transpile cached A and G to optimisation level 3.
- Return type:
None
useFragmentBN(evidence=None, target=None)
Section titled “useFragmentBN(evidence=None, target=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 inevidence). - target (
set[str|int] |None) – Target query nodes.
- evidence (
- Return type:
None