API Reference
This section contains the complete API documentation for PropFlow.
Core Modules
Engines
- class propflow.bp.engine_base.BPEngine(factor_graph, computator=<propflow.bp.computators.MinSumComputator object>, init_normalization=<function dummy_func>, name='BPEngine', convergence_config=None, monitor_performance=None, normalize_messages=None, anytime=None, snapshot_manager=None)[source]
Bases:
objectThe core engine for running belief propagation simulations.
This class orchestrates the belief propagation process on a factor graph. It manages the simulation loop, message passing schedule, history tracking, convergence checking, and performance monitoring. It is designed to be extended by other engine classes that implement specific BP variants or policies.
- computator
The computator instance for message calculation.
- Type:
- graph
The factor graph on which the simulation runs.
- Type:
- history
An object for tracking the simulation’s history.
- Type:
History
- convergence_monitor
The monitor for checking convergence.
- Type:
- performance_monitor
An optional monitor for performance.
- Type:
PerformanceMonitor
- step(i=0)[source]
Runs one full step of the synchronous belief propagation algorithm.
A step consists of two main phases: 1. Variable nodes compute and send messages to factor nodes. 2. Factor nodes compute and send messages to variable nodes.
- Parameters:
i (
int) – The current step number.- Return type:
Step- Returns:
A Step object containing information about the messages exchanged.
- run(max_iter=None, save_json=False, save_csv=False, filename=None, config_name=None)[source]
Runs the simulation until convergence or max iterations is reached.
- Parameters:
max_iter (
int|None) – The maximum number of iterations to run.save_json (
bool) – Whether to save the full history as a JSON file.save_csv (
bool) – Whether to save the cost history as a CSV file.filename (
str) – The base name for the output files.config_name (
str|None) – The name of the configuration to use for saving.
- Return type:
- Returns:
An optional string, typically for results or status.
- calculate_global_cost()[source]
Calculates the global cost using the original, unmodified factor cost tables.
- Return type:
- pre_factor_compute(factor, iteration=0)[source]
Hook for logic before a factor computes its messages.
- Parameters:
factor (
FactorAgent) – The factor agent about to compute messages.iteration (
int) – The current simulation iteration.
- Return type:
- post_factor_compute(factor, iteration)[source]
Hook for logic after a factor computes its messages.
- Parameters:
factor (
FactorAgent) – The factor agent that just computed messages.iteration (
int) – The current simulation iteration.
- Return type:
- pre_var_compute(var)[source]
Hook for logic before a variable computes its messages.
- Parameters:
var (
VariableAgent) – The variable agent about to compute messages.- Return type:
- post_var_compute(var)[source]
Hook for logic after a variable computes its messages.
- Parameters:
var (
VariableAgent) – The variable agent that just computed messages.- Return type:
- update_global_cost()[source]
Calculates and records the global cost for the current step.
If in “anytime” mode, it ensures the cost recorded does not increase.
- Return type:
- property snapshots: List[EngineSnapshot]
- property snapshot_map: Dict[int, EngineSnapshot]
- class propflow.bp.engines.Engine(factor_graph, computator=<propflow.bp.computators.MinSumComputator object>, init_normalization=<function dummy_func>, name='BPEngine', convergence_config=None, monitor_performance=None, normalize_messages=None, anytime=None, snapshot_manager=None)[source]
Bases:
BPEngineA basic belief propagation engine.
This is a direct alias for BPEngine and provides the standard, unmodified belief propagation behavior.
- class propflow.bp.engines.SplitEngine(*args, split_factor=0.5, **kwargs)[source]
Bases:
BPEngineA BP engine that applies the factor splitting policy.
This engine modifies the factor graph by splitting each factor into two, distributing the original cost between them. This can sometimes help with convergence.
- class propflow.bp.engines.MidRunSplitEngine(*args, split_at_iter, split_factor=0.5, split_targets=None, split_fraction=None, split_seed=None, transfer_mode='reset', **kwargs)[source]
Bases:
BPEngineA BP engine that applies factor splitting at a chosen iteration.
The engine runs standard BP until
split_at_iter. Immediately before that step is computed, it splits the requested factors and either resets messages to zero or transfers current factor-to-variable messages into the split graph.The
transfermode is an empirical heuristic, not a canonical mid-run split. It preserves the aggregate factor-to-variable contribution at the variable inbox boundary (and therefore the variable belief, and the Q messages to unaffected neighbors). It does not preserve the Q messages going into the split clones themselves: each clone’s Q picks up the sibling clone’s transferred share, so each clone’s first outgoing R is not a canonical continuation of the un-split dynamics. Treat the split iteration as a heuristic injection.- step(i=0)[source]
Runs one full step of the synchronous belief propagation algorithm.
A step consists of two main phases: 1. Variable nodes compute and send messages to factor nodes. 2. Factor nodes compute and send messages to variable nodes.
- Parameters:
i (
int) – The current step number.- Returns:
A Step object containing information about the messages exchanged.
- class propflow.bp.engines.CostReductionOnceEngine(*args, reduction_factor=0.5, **kwargs)[source]
Bases:
BPEngineA BP engine that applies a one-time cost reduction policy.
This engine reduces the costs in the factor tables at the beginning of the simulation and then applies a discount to outgoing messages from factors.
- class propflow.bp.engines.DampingEngine(*args, damping_factor=0.9, **kwargs)[source]
Bases:
BPEngineA BP engine that applies message damping.
Damping averages the message from the previous iteration with the newly computed message. This can help prevent oscillations and improve convergence.
- class propflow.bp.engines.QRDampingEngine(*args, q_damping_factor=0.0, r_damping_factor=0.0, **kwargs)[source]
Bases:
BPEngineA BP engine that applies message damping to both Q and R messages.
Q damping applies to variable → factor messages. R damping applies to factor → variable messages.
- post_init()[source]
Prime factor history with zero messages so R-damping applies from iter 0.
- Return type:
- post_var_compute(var)[source]
Hook for logic after a variable computes its messages.
- Parameters:
var (
VariableAgent) – The variable agent that just computed messages.- Return type:
- post_factor_compute(factor, iteration)[source]
Hook for logic after a factor computes its messages.
- Parameters:
factor (
FactorAgent) – The factor agent that just computed messages.iteration (
int) – The current simulation iteration.
- Return type:
- class propflow.bp.engines.RDampingEngine(*args, damping_factor=0.9, **kwargs)[source]
Bases:
BPEngineA BP engine that applies message damping to R messages.
Damping averages the R message from the previous iteration with the newly computed message. This can help prevent oscillations and improve convergence. Unlike DampingEngine which damps Q messages (Variable -> Factor), this engine damps R messages (Factor -> Variable).
- class propflow.bp.engines.DiffusionEngine(*args, alpha=0.3, **kwargs)[source]
Bases:
BPEngineA BP engine that applies spatial message diffusion.
Unlike damping which blends messages across time (current vs previous), diffusion blends messages across space (local vs neighbors) at each iteration. This can help smooth the optimization landscape and improve convergence on densely connected graphs.
- class propflow.bp.engines.DampingSCFGEngine(*args, **kwargs)[source]
Bases:
DampingEngine,SplitEngineA BP engine that combines message damping and factor splitting.
- class propflow.bp.engines.DampingCROnceEngine(*args, **kwargs)[source]
Bases:
DampingEngine,CostReductionOnceEngineA BP engine that combines message damping and one-time cost reduction.
- class propflow.bp.engines.TRWEngine(*args, factor_rhos=None, tree_sample_count=250, tree_sampler_seed=None, min_rho=1e-06, **kwargs)[source]
Bases:
BPEngineTree-Reweighted Belief Propagation engine (Min-Sum variant).
The engine keeps the standard Min-Sum computator but automatically:
Samples spanning trees over the variable-only (primal) graph to estimate per-factor appearance probabilities
rho_f.Scales each factor’s energy table by
1 / rho_fbefore message computation so local costs match the TRW objective.Re-weights outgoing R-messages from factors by
rho_fso that variable updates/beliefs operate on appropriately weighted costs.
Rho sampling and scaling can be overridden by providing explicit
factor_rhos(all > 0). Otherwise the engine performs end-to-end TRW reweighting using the current factor graph structure.- DEFAULT_MIN_RHO = 1e-06
- class propflow.bp.engines.DampingTRWEngine(*args, **kwargs)[source]
Bases:
DampingEngine,TRWEngineA BP engine that combines TRW reweighting with message damping.
Factor Graphs
- class propflow.bp.factor_graph.FactorGraph(variable_li, factor_li, edges)[source]
Bases:
objectRepresents a bipartite factor graph for belief propagation.
This class encapsulates the structure of a factor graph, which consists of variable nodes and factor nodes. It enforces a bipartite structure where variables are only connected to factors and vice versa. It uses a networkx.Graph to manage the underlying connections.
- variables
A list of all variable agents in the graph.
- Type:
List[VariableAgent]
- factors
A list of all factor agents in the graph.
- Type:
List[FactorAgent]
- G
The underlying networkx graph structure.
- Type:
nx.Graph
- compute_cost(factors=None)[source]
Compute total cost over the given factors using current variable assignments.
- Parameters:
factors (
Optional[List[FactorAgent]]) – which factors to sum over. Defaults toself.factors(current, possibly modified factors). Passself.original_factorsto get the cost against the original, unmodified cost tables.- Return type:
- property curr_assignment: Dict[VariableAgent, int]
The current assignment for all variables in the graph.
- Type:
- property edges: Dict[FactorAgent, List[VariableAgent]]
Reconstructs the edge dictionary mapping factors to variables.
- Type:
- set_computator(computator, **kwargs)[source]
Assigns a computator to all nodes in the graph.
- Parameters:
computator (
BPComputator) – The computator instance to assign.**kwargs – Additional arguments (not currently used).
- Return type:
- normalize_messages()[source]
Normalizes all incoming messages for all variable nodes.
This is a common technique to prevent numerical instability in belief propagation algorithms by shifting message values.
- Return type:
- visualize(layout='bipartite', layout_kwargs=None, plot=True, *, pretty=False)[source]
Visualizes the factor graph using matplotlib.
Variable nodes are drawn as circles, and factor nodes are drawn as squares. If plot is True the figure is shown and the function returns None. If plot is False the Figure object is returned (and not shown), allowing further programmatic use.
- Parameters:
layout (
str) – Layout algorithm to use. Supported values are"bipartite"(default),"spring","circular", and"kamada_kawai". Ignored whenpretty=True.layout_kwargs (
Optional[Dict[str,Any]]) – Optional keyword arguments forwarded to the selected NetworkX layout function.plot (
bool) – If True, call plt.show() and return None. If False, return the matplotlib.figure.Figure instance without showing it.pretty (
bool) – When True, render a fixed spring-layout visualization with styled nodes/legend useful for presentations.
- Return type:
Figure|None
- property diameter: int
The diameter of the factor graph.
If the graph is not connected, it returns the diameter of the largest connected component.
- Type:
- property original_factors: List[FactorAgent]
A deep copy of the original factor agents.
- Type:
Computators
- class propflow.bp.computators.BPComputator(reduce_func=<function min>, combine_func=<ufunc 'add'>)[source]
Bases:
ComputatorA vectorized, cache-friendly Belief Propagation computator.
This class provides a highly optimized implementation for the core computations in belief propagation algorithms. It uses function dispatch tables for common operations ( min, max, sum, add, multiply) to minimize overhead and leverages vectorized numpy operations for performance.
The behavior of the computator (Min-Sum, Max-Product) is determined by the reduce_func and combine_func arguments passed during initialization.
- reduce_func
The function used for message reduction (np.min).
- Type:
Callable
- combine_func
The function used for message combination (np.add).
- Type:
Callable
- compute_Q(messages)[source]
Computes outgoing messages from a variable node to factor nodes (Q messages).
This is an optimized, vectorized implementation.
- compute_R(cost_table, incoming_messages)[source]
Computes outgoing messages from a factor node to variable nodes (R messages).
This is an optimized, vectorized implementation that involves three main steps: 1. Broadcast each incoming Q message to the dimensionality of the cost table. 2. Combine the cost table with all broadcasted Q messages once. 3. For each recipient, efficiently “remove” its Q message from the aggregate
and reduce to produce the outgoing R message.
- get_assignment(belief)[source]
Gets the optimal assignment from a belief vector.
Uses the pre-selected _argreduce_func (e.g., argmin, argmax) for zero-overhead execution.
- propflow.bp.computators.Computator
alias of
BPComputator
- class propflow.bp.computators.MinSumComputator[source]
Bases:
BPComputatorA computator for the Min-Sum belief propagation algorithm.
This is equivalent to finding the Most Probable Explanation (MPE) in a graphical model represented in the log-domain. It combines messages using addition and reduces them using the min operator.
- class propflow.bp.computators.MaxSumComputator[source]
Bases:
BPComputatorA computator for the Max-Sum belief propagation algorithm.
This is used for problems where the goal is to maximize a sum of utilities. It combines messages using addition and reduces them using the max operator.
- class propflow.bp.computators.MaxProductComputator[source]
Bases:
BPComputatorA computator for the Max-Product belief propagation algorithm.
This is equivalent to finding the Most Probable Explanation (MPE) in a graphical model. It combines messages using multiplication and reduces them using the max operator.
- class propflow.bp.computators.SumProductComputator[source]
Bases:
BPComputatorA computator for the Sum-Product belief propagation algorithm.
This is used to compute marginal probabilities in a graphical model. It combines messages using multiplication and reduces them (marginalizes) using summation.
Agents
- class propflow.core.agents.FGAgent(name, node_type, domain)[source]
Bases:
Agent,ABCAbstract base class for belief propagation (BP) nodes.
Extends the Agent class with methods relevant to message passing, updating local belief, and retrieving that belief. It serves as a foundation for both VariableAgent and FactorAgent classes.
- mailer
Handles incoming and outgoing messages.
- Type:
- abstractmethod compute_messages()[source]
Abstract method to compute outgoing messages.
This method must be implemented by subclasses to define how messages are calculated based on the agent’s current state and incoming messages.
- class propflow.core.agents.VariableAgent(name, domain)[source]
Bases:
FGAgentRepresents a variable node in a factor graph.
This agent is responsible for aggregating messages from neighboring factor nodes to compute its belief over its domain.
- computator
An object that handles the computation of messages and beliefs.
- compute_messages()[source]
Computes outgoing messages to factor nodes.
Uses the assigned computator to calculate messages based on the contents of the inbox.
- Return type:
- class propflow.core.agents.FactorAgent(name, domain, ct_creation_func, param=None, cost_table=None)[source]
Bases:
FGAgentRepresents a factor node in a factor graph.
This agent stores a cost function (or utility function) that defines the relationship between a set of connected variable nodes.
- cost_table
The table of costs for each combination of assignments.
- Type:
CostTable
- ct_creation_func
A function to create the cost table.
- Type:
Callable
- classmethod create_from_cost_table(name, cost_table)[source]
Creates a FactorAgent from an existing cost table.
- Parameters:
- Return type:
- Returns:
A new FactorAgent instance.
- compute_messages()[source]
Computes messages to be sent to variable nodes.
Uses the assigned computator to calculate messages based on the cost table and incoming messages from variable nodes.
- Return type:
- initiate_cost_table()[source]
Creates the cost table using the provided creation function.
- Raises:
ValueError – If the cost table already exists or if no connections are set.
- Return type:
- set_dim_for_variable(variable, dim)[source]
Maps a variable to a dimension in the cost table.
- Parameters:
variable (
VariableAgent) – The variable agent to map.dim (
int) – The dimension index in the cost table.
- Return type:
- set_name_for_factor()[source]
Sets the factor’s name based on its connected variables.
- Raises:
ValueError – If no connections are set.
- Return type:
Components
- class propflow.core.components.Message(data, sender, recipient)[source]
Bases:
objectRepresents a message passed between agents in the belief propagation algorithm.
- data
The content of the message, typically a numpy array representing costs or beliefs.
- Type:
np.ndarray
- sender
The agent sending the message.
- Type:
Agent
- recipient
The agent receiving the message.
- Type:
Agent
- class propflow.core.components.MailHandler(_domain_size)[source]
Bases:
objectHandles message passing with deduplication and synchronization.
This class manages an agent’s incoming and outgoing messages, ensuring that only the latest message from each sender is stored.
- pruning_policy
An optional policy for selectively discarding messages.
- set_pruning_policy(policy)[source]
Sets a message pruning policy.
- Parameters:
policy – An object with a should_accept_message method.
- Return type:
- set_first_message(owner, neighbor)[source]
Initializes the inbox with a zero-message from a neighbor.
This is used to ensure that an agent has a message from each neighbor before computation begins.
- receive_messages(messages)[source]
Receives and handles one or more messages.
Applies a pruning policy if one is set and stores the message, overwriting any previous message from the same sender.
Policies
Policies used by belief propagation bp.
- class propflow.policies.ConvergenceConfig(belief_threshold=1e-06, assignment_threshold=0, min_iterations=0, patience=5, use_relative_change=True)[source]
Bases:
objectConfiguration settings for the convergence detection logic.
- belief_threshold
The maximum change in the norm of a belief vector for it to be considered stable.
- assignment_threshold
The maximum number of assignment changes allowed for the assignments to be considered stable.
- min_iterations
The minimum number of iterations to run before checking for convergence.
- patience
The number of consecutive iterations for which the beliefs and assignments must remain stable before declaring convergence.
- use_relative_change
If True, uses the relative change in belief norm for the threshold check; otherwise, uses the absolute change.
- class propflow.policies.ConvergenceMonitor(config=None)[source]
Bases:
objectMonitors and detects convergence in a belief propagation simulation.
This class tracks the history of beliefs and assignments to determine if the algorithm has reached a stable state according to the provided configuration.
- check_convergence(beliefs, assignments)[source]
Checks if the algorithm has converged.
This method compares the current beliefs and assignments with the previous state to determine if they have stabilized.
- Parameters:
- Return type:
- Returns:
True if the algorithm is considered to have converged, False otherwise.
- class propflow.policies.MessagePruningPolicy(prune_threshold=None, min_iterations=5, adaptive_threshold=True)[source]
Bases:
objectA policy that prunes messages that have not changed significantly.
This policy helps to optimize belief propagation by avoiding the processing of messages that are redundant. It compares the norm of the difference between a new message and the previous message from the same sender.
- policy_type
The type of the policy (PolicyType.MESSAGE).
- prune_threshold
The threshold for pruning.
- min_iterations
The number of initial iterations during which no pruning will occur.
- adaptive_threshold
If True, the threshold is scaled by the magnitude of the message.
- iteration_count
The current iteration number.
- pruned_count
The total number of pruned messages.
- total_count
The total number of messages considered for pruning.
- should_accept_message(agent, new_message)[source]
Determines whether to accept or prune an incoming message.
- step_completed()[source]
Signals that a simulation step has completed, incrementing the iteration count.
- Return type:
- propflow.policies.TD(variables, x=None, diameter=None)[source]
Applies temporal damping to the outgoing messages of a list of variables.
This function applies damping using messages from a previous cycle, determined by the diameter. The new message is a weighted average of the message from diameter iterations ago and the current message.
The update rule is: new_message = x * previous_cycle_message + (1 - x) * current_message
- Parameters:
variables (
List[VariableAgent]) – A list of VariableAgent objects to apply damping to.x (
float) – The damping factor, representing the weight of the previous message. If None, the default from POLICY_DEFAULTS is used.diameter (
int) – The number of iterations in a cycle, used to retrieve the message from the previous cycle. If None, the default from POLICY_DEFAULTS is used.
- Return type:
- propflow.policies.cost_reduction_all_factors_once(fg, x)[source]
Applies a one-time cost reduction to all factors in the graph.
This function iterates through all factor agents in the provided factor graph and multiplies their cost tables by a given factor. It also saves the original cost table before modification.
- Parameters:
fg (
FactorGraph) – The FactorGraph to modify.x (
float) – The multiplicative factor to apply to the cost tables.
- Return type:
- propflow.policies.damp(agent, x=None)[source]
Applies damping to outgoing messages of a variable or factor agent.
Blends each outgoing message with the corresponding message from the previous iteration:
new = x * prev + (1 - x) * current.
- propflow.policies.damp_factor(agent, x=None)
Applies damping to outgoing messages of a variable or factor agent.
Blends each outgoing message with the corresponding message from the previous iteration:
new = x * prev + (1 - x) * current.
- propflow.policies.discount(fac_a, x)[source]
Applies a discount factor to the cost tables of specified factor agents.
- Parameters:
fac_a (
Iterable[FactorAgent]) – An iterable of FactorAgent objects whose cost tables will be discounted.x (
float) – The multiplicative discount factor to apply.
- Return type:
- propflow.policies.discount_attentive(fg)[source]
Applies an attentive discount to incoming messages for all variable nodes.
The discount factor for each variable’s messages is inversely proportional to the variable’s degree in the factor graph. This means variables with more connections (higher degree) will have their incoming messages discounted more heavily.
- Parameters:
fg (
FactorGraph) – The FactorGraph containing the variables to be updated.- Return type:
- propflow.policies.init_normalization(li)[source]
Performs an initial normalization of cost tables for a list of factors.
This function divides each factor’s cost table by the total number of factors in the list.
- Parameters:
li (
List[FactorAgent]) – A list of FactorAgent objects to be normalized.- Return type:
- propflow.policies.normalize_cost_table_sum(cost_table)[source]
Normalizes a cost table so that the sum across all dimensions is equal.
Note
The implementation of this function appears to be incorrect for its stated purpose and may not produce the intended normalization.
- propflow.policies.normalize_inbox(variables)[source]
Normalizes all messages in the inboxes of a list of variable agents.
This function iterates through each variable’s inbox and last iteration’s messages, normalizing them by subtracting the minimum value. This centers the message values around zero without changing their relative differences.
- Parameters:
variables (
List[VariableAgent]) – A list of VariableAgent objects whose messages will be normalized.- Return type:
- propflow.policies.normalize_soft_max(cost_table)[source]
Normalizes a cost table using the softmax function.
This ensures all values are positive and sum to 1, effectively converting costs into a probability distribution. A stability trick (subtracting the max value) is used to prevent overflow with large cost values.
- propflow.policies.reduce_R(fac_a, x)[source]
Reduces the outgoing R-messages from a factor agent by a factor x.
This function iterates through all staged outgoing messages (R-messages) of a given factor agent and multiplies their data by a reduction factor.
- Parameters:
fac_a (
FactorAgent) – The FactorAgent whose outgoing messages will be reduced.x (
float) – The factor by which to reduce the message data.
- Return type:
- propflow.policies.split_all_factors(fg, p=None)[source]
Performs an in-place replacement of every factor with two cloned factors.
Each factor f with cost table C is replaced by two new factors, f’ and f’’, with cost tables p*C and (1-p)*C, respectively. The new factors inherit all the connections of the original factor.
This function directly modifies the provided FactorGraph object, including its underlying networkx.Graph and its list of factors.
- Parameters:
fg (
FactorGraph) – The FactorGraph to modify.p (
float) – The splitting proportion, which must be between 0 and 1. This determines how the original cost is distributed between the two new factors. If None, the default from POLICY_DEFAULTS is used.
- Raises:
AssertionError – If p is not in the range (0, 1).
- Return type:
Dict[str,List[FactorAgent]]
- propflow.policies.split_factors(fg, p=None, *, factor_names=None, split_fraction=None, seed=None)[source]
Split selected factors in-place and return original-to-clone mapping.
- Parameters:
fg (
FactorGraph) – The factor graph to modify.p (
float|None) – Split proportion allocated to the first clone.factor_names (
Optional[Sequence[str]]) – Optional factor names to restrict the split target set. When omitted, all factors are candidates.split_fraction (
float|None) – Optional fraction of the candidate factors to split. Selection is deterministic for a given seed.seed (
int|None) – Seed used whensplit_fractionis provided.
- Return type:
Dict[str,List[FactorAgent]]- Returns:
A mapping from original factor name to the two replacement clone factors.
- propflow.policies.split_specific_factors(fg, factors, p=None)[source]
Split specific factors in the factor graph.
- Parameters:
fg (
FactorGraph) – The factor graph to modify.factors (
List[FactorAgent]) – The factors to split.p (
float|None) – The splitting proportion. Defaults to None.
- Return type:
Dict[str,List[FactorAgent]]
Utilities
- propflow.utils.dummy_func(*args, **kwargs)[source]
A dummy function that does nothing and returns nothing.
This function serves as a placeholder for callbacks or functions that are optional or not yet implemented, allowing the main logic to proceed without raising errors.
- class propflow.utils.FGBuilder[source]
Bases:
objectA builder class providing static methods to construct factor graphs.
- static build_from_edges(variables, factors, edges)[source]
Builds a factor graph from the provided variables, factors, and edges.
- Parameters:
variables (
List[VariableAgent]) – The variable nodes in the graph.factors (
List[FactorAgent]) – The factor nodes in the graph.edges (
Dict[FactorAgent,List[VariableAgent]]) – The edges connecting factors to variables.
- Returns:
The constructed factor graph.
- Return type:
- static build_random_graph(num_vars, domain_size, ct_factory, ct_params, density, *, seed=None)[source]
Builds a factor graph with random binary constraints.
- Parameters:
num_vars (
int) – The number of variables in the graph.domain_size (
int) – The size of the domain for each variable.ct_factory (
Union[Callable,str]) – The factory for creating cost tables.ct_params (
Dict[str,Any]) – Parameters for the cost table factory.density (
float) – The density of the graph (probability of an edge).seed (
int|None) – Optional seed controlling the random topology. When omitted, randomness is derived from the globally-configured numpy andrandomRNGs so user-level seeding still produces deterministic graphs.
- Return type:
- Returns:
A FactorGraph instance with a random topology.
- static build_cycle_graph(num_vars, domain_size, ct_factory, ct_params, **kwargs)[source]
Builds a factor graph with a simple cycle topology.
The graph structure is x1 – f12 – x2 – … – xn – fn1 – x1.
- Parameters:
num_vars (
int) – The number of variables in the cycle.domain_size (
int) – The size of the domain for each variable.ct_factory (
Union[Callable,str]) – The factory for creating cost tables.ct_params (
Dict[str,Any]) – Parameters for the cost table factory.**kwargs – Catches unused arguments like density for API consistency.
- Return type:
- Returns:
A FactorGraph instance with a cycle topology.
- static build_lemniscate_graph(num_vars, domain_size, ct_factory, ct_params, **kwargs)[source]
Builds a factor graph with a lemniscate (∞) topology.
The structure consists of two cycles that share a single central variable, producing a figure-eight shape. Each loop is guaranteed to contain at least two distinct variables in addition to the central node.
- Parameters:
num_vars (
int) – Total number of variables in the graph. Must be >= 5.domain_size (
int) – The size of the domain for each variable.ct_factory (
Union[Callable,str]) – Factory used to create cost tables for the factors.ct_params (
Dict[str,Any]) – Parameters forwarded to the cost table factory.**kwargs – Captures unused parameters (e.g., density) for API parity.
- Return type:
- Returns:
A FactorGraph instance shaped like a lemniscate.
- Raises:
ValueError – If fewer than five variables are provided.
- static create_lemniscate_graph(num_vars, domain_size, ct_factory, ct_params, **kwargs)
Builds a factor graph with a lemniscate (∞) topology.
The structure consists of two cycles that share a single central variable, producing a figure-eight shape. Each loop is guaranteed to contain at least two distinct variables in addition to the central node.
- Parameters:
num_vars (
int) – Total number of variables in the graph. Must be >= 5.domain_size (
int) – The size of the domain for each variable.ct_factory (
Union[Callable,str]) – Factory used to create cost tables for the factors.ct_params (
Dict[str,Any]) – Parameters forwarded to the cost table factory.**kwargs – Captures unused parameters (e.g., density) for API parity.
- Return type:
- Returns:
A FactorGraph instance shaped like a lemniscate.
- Raises:
ValueError – If fewer than five variables are provided.
- static create_leminscate_graph(num_vars, domain_size, ct_factory, ct_params, **kwargs)
Builds a factor graph with a lemniscate (∞) topology.
The structure consists of two cycles that share a single central variable, producing a figure-eight shape. Each loop is guaranteed to contain at least two distinct variables in addition to the central node.
- Parameters:
num_vars (
int) – Total number of variables in the graph. Must be >= 5.domain_size (
int) – The size of the domain for each variable.ct_factory (
Union[Callable,str]) – Factory used to create cost tables for the factors.ct_params (
Dict[str,Any]) – Parameters forwarded to the cost table factory.**kwargs – Captures unused parameters (e.g., density) for API parity.
- Return type:
- Returns:
A FactorGraph instance shaped like a lemniscate.
- Raises:
ValueError – If fewer than five variables are provided.
- static build_with_unary_costs(base_graph, unary_costs)[source]
Extends a factor graph with unary constraints (per-variable cost biases).
Unary factors are single-variable factors that act as priors or biases for individual variables. They’re useful for adding soft constraints or preferences on variable assignments.
- Parameters:
base_graph (
FactorGraph) – An existing factor graph to extend.unary_costs (
Dict[str,ndarray]) – A dictionary mapping variable names to 1D numpy arrays of costs. The array length must match the variable’s domain size.
- Return type:
- Returns:
A new FactorGraph with the unary factors added.
Example
>>> fg = FGBuilder.build_cycle_graph(3, 2, create_random_int_table, {"low": 0, "high": 10}) >>> unary = {"x1": np.array([0, 5]), "x2": np.array([3, 0])} >>> fg_with_unary = FGBuilder.build_with_unary_costs(fg, unary)
- propflow.utils.find_project_root()[source]
Finds the project root directory by searching for common markers.
This function starts from the current working directory and traverses up the directory tree, looking for files or directories like .git, pyproject.toml, or setup.py that typically indicate the root of a project.
- Return type:
- Returns:
A Path object representing the project root directory, or the current working directory if no project root markers are found (e.g., when installed as a package).
- class propflow.utils.CTFactories[source]
Bases:
objectCost table factory namespace. Use: CTFactories.RANDOM_INT
- UNIFORM(domain, low=0.0, high=1.0)
Generate cost table with uniform float values.
When using FGBuilder, pass low and high via ct_params.
- RANDOM_INT(domain, low=0, high=10)
Generate cost table with random integer values.
When using FGBuilder, pass low and high via ct_params.
- POISSON(domain, rate=1.0, strength=None)
Generate cost table with Poisson-distributed values.
When using FGBuilder, pass rate or strength via ct_params.
Configuration
Configuration helpers for the belief propagation simulator.
- class propflow.configs.Logger(name, level=None, file=None)[source]
Bases:
LoggerA custom logger that provides standardized console and file logging.
This class extends the standard logging.Logger to automatically configure a colored console handler and an optional file handler based on the global logging configuration.
- file_handler
The handler for logging to a file, which is only created if file logging is enabled.
- Type:
- console
The handler for logging to the console with colored output.
- Type:
colorlog.StreamHandler
- class propflow.configs.CTFactories[source]
Bases:
objectCost table factory namespace. Use: CTFactories.RANDOM_INT
- UNIFORM(domain, low=0.0, high=1.0)
Generate cost table with uniform float values.
When using FGBuilder, pass low and high via ct_params.
- RANDOM_INT(domain, low=0, high=10)
Generate cost table with random integer values.
When using FGBuilder, pass low and high via ct_params.
- POISSON(domain, rate=1.0, strength=None)
Generate cost table with Poisson-distributed values.
When using FGBuilder, pass rate or strength via ct_params.
- propflow.configs.get_ct_factory(factory)[source]
Resolve factory identifier to callable.
Accepts CTFactories.RANDOM_INT, “random_int”, or raw function.
- Return type:
- propflow.configs.create_poisson_table(n, domain, rate=1.0, strength=None)[source]
Generate cost table with Poisson-distributed values.
When using FGBuilder, pass rate or strength via ct_params.
- propflow.configs.create_random_int_table(n, domain, low=0, high=10)[source]
Generate cost table with random integer values.
When using FGBuilder, pass low and high via ct_params.
- propflow.configs.create_uniform_float_table(n, domain, low=0.0, high=1.0)[source]
Generate cost table with uniform float values.
When using FGBuilder, pass low and high via ct_params.
- class propflow.configs.EngineDefaults(max_iterations=2000, normalize_messages=True, monitor_performance=False, anytime=False, timeout=600)[source]
Bases:
objectDefault parameters for the belief propagation engine.
- class propflow.configs.LoggingDefaults(default_level=20, verbose_logging=False, file_logging=True, log_dir='configs/logs', log_format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', console_format='%(log_color)s%(asctime)s - %(name)s - %(message)s', file_format='%(asctime)s - %(name)s - %(message)s', console_colors=<factory>)[source]
Bases:
objectDefault configuration for the logging system.
- class propflow.configs.PolicyDefaults(damping_factor=0.9, damping_diameter=1, split_factor=0.5, pruning_threshold=0.1, pruning_magnitude_factor=0.1, cost_reduction_enabled=True, tree_reweight_factor=0.5)[source]
Bases:
objectDefault parameters for various belief propagation policies.
- class propflow.configs.ConvergenceDefaults(belief_threshold=1e-06, assignment_threshold=0, min_iterations=0, patience=5, use_relative_change=True, timeout=600)[source]
Bases:
objectDefault parameters for the convergence monitor.
- class propflow.configs.SimulatorDefaults(default_max_iter=5000, default_log_level='INFORMATIVE', timeout=3600, cpu_count_multiplier=1.0)[source]
Bases:
objectDefault parameters for the multi-simulation runner.
- propflow.configs.validate_engine_config(config)[source]
Validate engine configuration. Raises ValueError if invalid.
- Return type:
- propflow.configs.validate_policy_config(config)[source]
Validate policy configuration. Raises ValueError if invalid.
- Return type:
- propflow.configs.validate_convergence_config(config)[source]
Validates convergence configuration parameters.
- Parameters:
config (
Dict[str,Any]) – A dictionary containing convergence configuration.- Return type:
- Returns:
True if the configuration is valid.
- Raises:
ValueError – If a value is invalid or outside its expected range.
- propflow.configs.get_validated_config(config_type, user_config=None)[source]
Merges a user configuration with defaults and validates it.
- Parameters:
- Return type:
- Returns:
A dictionary containing the final, validated configuration.
- Raises:
ValueError – If the config_type is unknown or validation fails.
Simulator
A parallelized simulator for running and comparing multiple engine configurations.
This module provides a Simulator class that can run multiple belief propagation engine configurations across a set of factor graphs in parallel. It uses Python’s multiprocessing module to distribute the simulation runs, collects the results, and provides a simple plotting utility to visualize and compare the performance of different engines.
- class propflow.simulator.Simulator(engine_configs, log_level=None, *, seed=None)[source]
Bases:
objectOrchestrates parallel execution of multiple simulation configurations.
This class takes a set of engine configurations and a list of factor graphs, runs each engine on each graph in parallel, collects the cost history from each run, and provides methods to visualize the aggregated results.
- run_simulations(graphs, max_iter=None)[source]
Runs all engine configurations on all provided graphs in parallel.
- Parameters:
- Return type:
- Returns:
A dictionary containing the collected results, where keys are engine names and values are lists of cost histories for each run.
Snapshots
Per-step snapshot capture and analysis for BP engines.
This module provides a small, modular API to record a lightweight snapshot of the engine state at each step (when enabled), and to compute Jacobian blocks and cycle metrics for focused, iteration-level analysis.
Top-level exports: - EngineSnapshot: container of snapshot data + Jacobians + metrics - SnapshotManager: attaches to engine and records per-step snapshots - SnapshotAnalyzer: derive Jacobian matrices and convergence metrics from snapshots - AnalysisReport: generate analysis reports and export results - SnapshotVisualizer: plot belief argmin trajectories from snapshots
- class propflow.snapshots.EngineSnapshot(step, lambda_, dom, N_var, N_fac, Q, R, unary=<factory>, beliefs=<factory>, assignments=<factory>, global_cost=None, metadata=<factory>, cost_tables=<factory>, cost_labels=<factory>, jacobians=None, cycles=None, winners=None, min_idx=None, bct_metadata=<factory>, captured_at=<factory>)[source]
Bases:
objectSelf-contained snapshot captured at a single BP step.
- step
Current iteration step. (int)
- lambda_
Damping factor used in this step. (float)
- dom
Variable domains.
- N_var
Neighbouring factors for each variable.
- N_fac
Neighbouring variables for each factor. (2 for binary factors)
- Q
Outgoing Q messages.
- R
Outgoing R messages.
- unary
Unary beliefs for each variable.
- beliefs
Marginal beliefs for each variable.
- assignments
Current MAP assignments for each variable.
- global_cost
Current global cost (if computed).
- metadata
Additional metadata captured at this step.
- cost_tables
Cost tables for each factor.
- cost_labels
Labels for cost tables.
- jacobians
Jacobian matrices and metadata (if computed).
- cycles
Cycle metrics (if computed).
- winners
Winning assignments per factor (if applicable).
- min_idx
Indices of minimum costs per message (if applicable).
- bct_metadata
Additional BCT-related metadata.
- captured_at
Timestamp when the snapshot was captured.
- cycles: CycleMetrics | None = None
- class propflow.snapshots.Jacobians(idxQ, idxR, A, P, B, block_norms=None)[source]
Bases:
objectHolds Jacobian-related matrices and associated metadata.
- A: csr_matrix
- P: csr_matrix
- B: csr_matrix
- class propflow.snapshots.CycleMetrics(num_cycles, aligned_hops_total, has_certified_contraction, details=None)[source]
Bases:
objectCompact summary of cycle analysis for a given step.
- class propflow.snapshots.SnapshotManager[source]
Bases:
objectLightweight helper that captures a snapshot for a single engine step.
- class propflow.snapshots.SnapshotAnalyzer(snapshots, *, domain=None, max_cycle_len=12)[source]
Bases:
objectAnalyze convergence dynamics from propflow snapshots.
This class provides methods to derive Jacobian matrices, dependency graphs, cycle metrics, and other structural properties from snapshot sequences.
- difference_coordinates(step_idx)[source]
Compute ΔQ and ΔR (difference coordinates) for a snapshot.
- jacobian(step_idx)[source]
Construct the Jacobian matrix in difference coordinates.
- Return type:
ndarray|spmatrix
- dependency_digraph(step_idx)[source]
Construct the dependency digraph induced by the Jacobian.
- Return type:
- class propflow.snapshots.AnalysisReport(analyzer)[source]
Bases:
objectGenerate analysis reports from snapshots.
- class propflow.snapshots.SnapshotVisualizer(snapshots)[source]
Bases:
objectVisualize belief propagation snapshot trajectories.
- global_cost_series(*, include_missing=False, fill_value=nan)[source]
Return the global cost trajectory extracted from the snapshots.
- Parameters:
- Return type:
- Returns:
A tuple
(steps, costs)with matching lengths.- Raises:
ValueError – If no snapshots contain global cost information.
- factor_cost_matrix(factor, step)[source]
Return a copy of a factor’s cost table at a given step.
- Return type:
- static plot_agent_cost_table(agent, *, connections=None, fmt='{:.3g}', plot=True, show=True, savepath=None, cmap='viridis', annotate=True)[source]
Static method to show a cost table for a FactorAgent without snapshots.
- Parameters:
agent (
FactorAgent) – The FactorAgent to visualize.connections (
Optional[Dict[FactorAgent,Tuple[str,str]]]) – Optional dictionary mapping FactorAgent objects to (row_var, col_var) tuples. Used to provide variable names for agents without explicit connections.fmt (
str) – Numeric format string for printing tables and annotations.plot (
bool) – If True, generate a heatmap using matplotlib. If False, print a text table.show (
bool) – Whether to display the plot (if plot=True).savepath (
str|None) – Optional path to save the figure (if plot=True).cmap (
str) – Colormap for the heatmap (if plot=True).annotate (
bool) – Whether to annotate cells with values (if plot=True).
- Return type:
Figure|str- Returns:
The formatted table string (if plot=False) or a matplotlib Figure (if plot=True).
- plot_cost_tables(factor=None, step=None, *, show=True, savepath=None, cmap='viridis', annotate=True, fmt='{:.3g}', connections=None)[source]
Pretty-print or plot factor cost tables from a snapshot.
When
factoris provided, prints a labeled table for that factor and returns the formatted string.When
factorisNone, plots all cost tables in a grid with axis labels derived from the factor’s variable ordering. Titles include the factor name.
- Parameters:
factor (
str|FactorAgent|None) – Optional factor name/agent. If provided, only that factor is shown.step (
int|None) – Snapshot step to use. Defaults to the last recorded step.show (
bool) – Whether to display the plot (when plotting all factors).savepath (
str|None) – Optional path to save the plotted figure (when plotting all factors).cmap (
str) – Matplotlib colormap name for heatmaps.annotate (
bool) – Whether to overlay numeric values on heatmaps.fmt (
str) – Numeric format string for printing tables and annotations.connections (
Optional[Dict[FactorAgent,Tuple[str,str]]]) – Optional dictionary mapping FactorAgent objects to (row_var, col_var) tuples. Used to provide variable names for agents without explicit connections.
- Return type:
Figure|str- Returns:
A matplotlib Figure when plotting all factors, or the formatted table string when printing a single factor.
- plot_factor_costs(from_variable, to_factor=None, step=None, *, mode='auto', cmap='viridis', annotate=True, show=True, savepath=None, return_data=False, highlight_color='tab:red', text_color='black', fmt='{:.3g}')[source]
Visualise factor cost tables induced by factor→variable messages.
- plot_global_cost(*, show=True, savepath=None, include_missing=False, fill_value=nan, rolling_window=None, return_data=False)[source]
Plot the evolution of the global cost captured in the snapshots.
- Parameters:
show (
bool) – Whether to display the plot window.savepath (
str|None) – Optional file path to save the figure.include_missing (
bool) – If True, include steps without a recorded cost usingfill_value.fill_value (
float) – Value used wheninclude_missingis True and a step lacks a cost.rolling_window (
int|None) – Size of a trailing window to compute and overlay a rolling mean.return_data (
bool) – If True, return the underlying data alongside the figure.
- Return type:
- Returns:
The created matplotlib figure, optionally accompanied by the plotted data.
- plot_message_norms(*, message_type='Q', pairs=None, norm='l2', show=True, savepath=None, return_data=False)[source]
Plot the per-step norms of Q or R messages.
- Parameters:
message_type (
Literal['Q','R']) – Select"Q"(variable→factor) or"R"(factor→variable``) messages.pairs (
Optional[Sequence[tuple[str,str]]]) – Optional explicit list of message pairs to include. Each tuple is(sender, recipient).norm (
Literal['l2','l1','linf']) – Vector norm used to summarise each message. Supported values are"l2","l1","linf".show (
bool) – Whether to display the plot.return_data (
bool) – If True, include the computed series in the return value.
- Return type:
- Returns:
The created figure, optionally with the underlying message norm series.
- plot_assignment_heatmap(vars_filter=None, *, show=True, savepath=None, cmap='viridis', missing_value=nan, annotate=True, value_labels=None, return_data=False)[source]
Plot variable assignments over time as a heatmap.
- Parameters:
vars_filter (
Optional[List[str]]) – Optional subset of variables to include.show (
bool) – Whether to display the figure window.savepath (
str|None) – Optional path to save the generated figure.cmap (
str) – Matplotlib colormap name to use for the heatmap.missing_value (
float) – Value inserted when an assignment is missing for a step. Defaults toNaNso gaps appear as empty cells.annotate (
bool) – Whether to write assignment values inside each cell.value_labels (
Union[Mapping[int,str],Sequence[str],None]) – Optional mapping or ordered list that converts assignment indices to display labels (e.g.,{0: "A", 1: "B"}or["A", "B", "C"]).return_data (
bool) – If True, return the data used for plotting alongside the figure.
- Return type:
- Returns:
The heatmap figure, optionally with the underlying matrix.
- plot_argmin_per_variable(vars_filter=None, *, figsize=None, show=True, savepath=None, combined_savepath=None, layout='separate')[source]
Plot argmin trajectories for selected variables.
- Parameters:
vars_filter (
Optional[List[str]]) – Optional list of variable names to plot.figsize (
tuple[float,float] |None) – Figure size tuple (width, height).show (
bool) – Whether to display the plot.savepath (
str|None) – Optional path to save individual variable plots (separate layout).combined_savepath (
str|None) – Optional path to save a combined plot.layout (
Literal['separate','combined']) – Choose “separate” for per-variable panels or “combined” for a single figure.
- Return type:
- plot_bct(variable_name, iteration=None, *, value_index=None, steps_back=None, show=True, savepath=None, verbose=False)[source]
Plot a Backtrack Cost Tree (BCT) for a variable from snapshots.
Reconstructs BCT data from snapshot Q and R messages, then visualizes how costs and beliefs from earlier iterations contribute to the final belief of the specified variable.
- Parameters:
variable_name (
str) – The name of the variable to visualize the BCT for.iteration (
int|None) – The iteration index to trace back from. Defaults to None (last step). If None, uses -1 (the last captured iteration).steps_back (
int|None) – Optional number of steps from the end to anchor the tree. For example,steps_back=10traces the state 10 steps before the last recorded snapshot. When provided, overridesiteration.show (
bool) – Whether to display the plot.savepath (
str|None) – Optional path to save the generated figure.verbose (
bool) – If True, annotate edges with message costs that generated each contribution in addition to assignments and table costs.
- Return type:
BCTCreator- Returns:
The BCTCreator object for further analysis (e.g., convergence analysis, variable comparisons). Can be used to call methods like analyze_convergence(), compare_variables(), export_analysis(), etc.
- Raises:
ValueError – If the variable_name is not found in the snapshots.
- class propflow.snapshots.StepByStepFormatter(snapshots, normalize_messages=True, route_filter='both', route_order=None, ignore_pairs=None)[source]
Bases:
objectFormats BP simulation steps in Excel-like tabular format.
This class takes a sequence of EngineSnapshots and provides methods to format them as readable step-by-step output showing: - Cost tables for all factors - Q messages (variable -> factor) per iteration - R messages (factor -> variable) per iteration - Variable assignments and beliefs per iteration - Solution cost per iteration
Example
>>> from propflow.snapshots import StepByStepFormatter >>> formatter = StepByStepFormatter(engine.snapshot_manager.snapshots) >>> print(formatter.format_all_steps())
- format_iteration(step, use_letters=True, show='text')[source]
Format Q/R messages, assignments, and cost for one iteration.
- Parameters:
- Return type:
- Returns:
Formatted string for the iteration.