3. BBN Generation

BBN generation is available. We support singly- and mulit-connected BBNs.

3.1. Singly-connected BBN

Use generate_singly_bbn() to generate a singly-connected BBN and then use create_reasoning_model() to create a reasoning model.

[1]:
from pybbn.factory import create_reasoning_model
from pybbn.generator import generate_singly_bbn
import numpy as np

g, p = generate_singly_bbn(
    n=10, max_iter=20, max_values=2, max_alpha=10, rng=np.random.default_rng(seed=37)
)

model = create_reasoning_model(g, p)

The singly-connected BBN graph looks like the following.

[2]:
import networkx as nx
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(5, 5))

pos = nx.nx_agraph.graphviz_layout(g, prog="dot")
nx.draw(g, pos=pos, with_labels=True, node_color="#e0e0e0")

fig.tight_layout()
_images/generate_4_0.png

Querying of the posteriors proceeds as usual.

[3]:
import pandas as pd

q1 = model.pquery()

e = {"4": model.create_observation_evidences("4", "s0")}
q2 = model.pquery(evidences=e)

e = {"4": model.create_observation_evidences("4", "s1")}
q3 = model.pquery(evidences=e)

p1 = pd.Series({n: q1[n].iloc[0]["__p__"] for n in model.d.nodes()})
p2 = pd.Series({n: q2[n].iloc[0]["__p__"] for n in model.d.nodes()})
p3 = pd.Series({n: q3[n].iloc[0]["__p__"] for n in model.d.nodes()})

pd.DataFrame([p1, p2, p3]).T.rename(columns={0: "q1", 1: "q2", 2: "q3"})
[3]:
q1 q2 q3
0 0.500393 0.500424 0.500380
1 0.370587 0.370672 0.370552
2 0.500547 0.500535 0.500551
3 0.221217 0.222402 0.220730
4 0.291306 1.000000 0.000000
5 0.672492 0.630880 0.689596
6 0.246865 0.246865 0.246865
7 0.603267 0.597744 0.605537
8 0.304271 0.304277 0.304269
9 0.887248 0.961834 0.856590
[4]:
from pybbn.serde import model_to_dict
import json

with open("../../_support/bbn/singly-connected.json", "w") as fp:
    json.dump(model_to_dict(model), fp, indent=1)

3.2. Multi-connected BBN

Use generate_multi_bbn() to generate a singly-connected BBN and then use create_reasoning_model() to create a reasoning model.

[5]:
from pybbn.generator import generate_multi_bbn

g, p = generate_multi_bbn(
    n=10, max_iter=5, max_values=2, max_alpha=10, rng=np.random.default_rng(seed=37)
)

model = create_reasoning_model(g, p)
[6]:
fig, ax = plt.subplots(figsize=(5, 5))

pos = nx.nx_agraph.graphviz_layout(g, prog="dot")
nx.draw(g, pos=pos, with_labels=True, node_color="#e0e0e0")

fig.tight_layout()
_images/generate_10_0.png
[7]:
import pandas as pd

q1 = model.pquery()

e = {"0": model.create_observation_evidences("0", "s0")}
q2 = model.pquery(evidences=e)

e = {"0": model.create_observation_evidences("0", "s1")}
q3 = model.pquery(evidences=e)

p1 = pd.Series({n: q1[n].iloc[0]["__p__"] for n in model.d.nodes()})
p2 = pd.Series({n: q2[n].iloc[0]["__p__"] for n in model.d.nodes()})
p3 = pd.Series({n: q3[n].iloc[0]["__p__"] for n in model.d.nodes()})

pd.DataFrame([p1, p2, p3]).T.rename(columns={0: "q1", 1: "q2", 2: "q3"})
[7]:
q1 q2 q3
0 0.026385 1.000000 0.000000
1 0.564311 0.210227 0.573907
2 0.486509 0.402171 0.488795
3 0.352396 0.357359 0.352262
4 0.492260 0.477167 0.492669
5 0.446751 0.412918 0.447668
6 0.458902 0.490701 0.458041
7 0.584410 0.767471 0.579449
8 0.634409 0.590927 0.635587
9 0.491198 0.502911 0.490881
[8]:
with open("../../_support/bbn/multi-connected.json", "w") as fp:
    json.dump(model_to_dict(model), fp, indent=1)