Skip to content

Influence diagram

Creative Commons LicenseaGrUMinteractive online version
import math
import pyagrum as gum
import pyagrum.lib.notebook as gnb
gum.fastID("A->*B->$C<-D<-*E->*G->H->*I<-D")
A A B B A->B D D I I D->I C C D->C H H H->I B->C E E E->D G G E->G G->H
diag = gum.loadID("res/diag.bifxml")
gnb.showInfluenceDiagram(diag)

svg

diag
chanceVar1 chanceVar1 chanceVar2 chanceVar2 chanceVar1->chanceVar2 utilityVar1 utilityVar1 chanceVar1->utilityVar1 decisionVar2 decisionVar2 chanceVar2->decisionVar2 decisionVar3 decisionVar3 chanceVar2->decisionVar3 chanceVar3 chanceVar3 chanceVar5 chanceVar5 chanceVar3->chanceVar5 chanceVar4 chanceVar4 chanceVar4->chanceVar5 utilityVar2 utilityVar2 chanceVar5->utilityVar2 decisionVar1 decisionVar1 decisionVar1->chanceVar1 decisionVar2->chanceVar4 decisionVar2->utilityVar1 decisionVar3->chanceVar3 decisionVar4 decisionVar4 decisionVar4->utilityVar2
F = diag.addChanceNode(gum.LabelizedVariable("F", "F", 2))
diag.addArc(diag.idFromName("decisionVar1"), F)
U = diag.addUtilityNode(gum.LabelizedVariable("U", "U", 1))
diag.addArc(diag.idFromName("decisionVar3"), U)
diag.addArc(diag.idFromName("F"), U)
gnb.showInfluenceDiagram(diag)

svg

diag.cpt(F)[{"decisionVar1": 0}] = [0.9, 0.1]
diag.cpt(F)[{"decisionVar1": 1}] = [0.3, 0.7]
diag.utility(U)[{"F": 0, "decisionVar3": 0}] = 2
diag.utility(U)[{"F": 0, "decisionVar3": 1}] = 4
diag.utility(U)[{"F": 1}] = [[0], [5]]

Optimization in an influence diagram (actually LIMID)

Section titled “Optimization in an influence diagram (actually LIMID)”
oil = gum.loadID("res/OilWildcatter.bifxml")
gnb.flow.row(oil, gnb.getInference(oil))
TestResult TestResult Drilling Drilling TestResult->Drilling OilContents OilContents OilContents->TestResult Reward Reward OilContents->Reward Testing Testing Testing->TestResult Testing->Drilling Cost Cost Testing->Cost Drilling->Reward
structs MEU 22.50 (stdev=87.46) Inference in   0.25ms Testing 2025-10-29T13:56:48.101507 image/svg+xml Matplotlib v3.10.7, Drilling 2025-10-29T13:56:48.117715 image/svg+xml Matplotlib v3.10.7, Testing->Drilling TestResult 2025-10-29T13:56:48.137482 image/svg+xml Matplotlib v3.10.7, Testing->TestResult Cost Cost : -10.00 (0.00) Testing->Cost Reward Reward : 32.50 (87.46) Drilling->Reward TestResult->Drilling OilContents 2025-10-29T13:56:48.158637 image/svg+xml Matplotlib v3.10.7, OilContents->TestResult OilContents->Reward

Inference in the LIMID optimizing the decisions nodes

Section titled “Inference in the LIMID optimizing the decisions nodes”
## a function to show results on decision nodes T and D
def show_decisions(ie):
gnb.flow.row(
ie.optimalDecision("Testing"),
ie.optimalDecision("Drilling"),
f"$${ie.MEU()['mean']:5.3f}\\ (stdev : {math.sqrt(ie.MEU()['variance']):5.3f})$$",
captions=["Strategy for T", "Strategy for D", "MEU and its standard deviation"],
)
gnb.flow.row(
ie.posterior("Testing"),
ie.posteriorUtility("Testing"),
ie.posterior("Drilling"),
ie.posteriorUtility("Drilling"),
captions=[
"Final decision for Testing",
"Final reward for Testing",
"Final decision for Drilling",
"Final reward for Drilling",
],
)
ie = gum.ShaferShenoyLIMIDInference(oil)
ie.makeInference()
show_decisions(ie)
Testing
Yes
No
1.00000.0000

Strategy for T
Drilling
TestResult
Yes
No
closed
1.00000.0000
open
1.00000.0000
diffuse
0.00001.0000

Strategy for D

22.500 (stdev:87.457)22.500\ (stdev : 87.457)

MEU and its standard deviation

Testing
Yes
No
1.00000.0000

Final decision for Testing
Testing
Yes
No
22.500020.0000

Final reward for Testing
Drilling
Yes
No
0.59000.4100

Final decision for Drilling
Drilling
Yes
No
45.0847-10.0000

Final reward for Drilling

Graphical inference with evidence and targets (developped nodes)

Section titled “Graphical inference with evidence and targets (developped nodes)”
gnb.sideBySide(
oil,
gnb.getInference(oil, evs={"TestResult": "closed"}),
gnb.getInference(oil, evs={"TestResult": "open"}),
gnb.getInference(oil, evs={"TestResult": "diffuse"}),
oil,
gnb.getInference(oil, evs={"OilContents": "Dry"}),
gnb.getInference(oil, evs={"OilContents": "Wet"}),
gnb.getInference(oil, evs={"OilContents": "Soaking"}),
ncols=4,
)
TestResult TestResult Drilling Drilling TestResult->Drilling OilContents OilContents OilContents->TestResult Reward Reward OilContents->Reward Testing Testing Testing->TestResult Testing->Drilling Cost Cost Testing->Cost Drilling->Reward
structs MEU 77.50 (stdev=104.73) Inference in   0.18ms Testing 2025-10-29T13:56:48.452629 image/svg+xml Matplotlib v3.10.7, Drilling 2025-10-29T13:56:48.469749 image/svg+xml Matplotlib v3.10.7, Testing->Drilling TestResult 2025-10-29T13:56:48.487072 image/svg+xml Matplotlib v3.10.7, Testing->TestResult Cost Cost : -10.00 (0.00) Testing->Cost Reward Reward : 87.50 (104.73) Drilling->Reward TestResult->Drilling OilContents 2025-10-29T13:56:48.506679 image/svg+xml Matplotlib v3.10.7, OilContents->TestResult OilContents->Reward
structs MEU 22.86 (stdev=104.98) Inference in   0.21ms Testing 2025-10-29T13:56:48.649794 image/svg+xml Matplotlib v3.10.7, Drilling 2025-10-29T13:56:48.666306 image/svg+xml Matplotlib v3.10.7, Testing->Drilling TestResult 2025-10-29T13:56:48.684011 image/svg+xml Matplotlib v3.10.7, Testing->TestResult Cost Cost : -10.00 (0.00) Testing->Cost Reward Reward : 32.86 (104.98) Drilling->Reward TestResult->Drilling OilContents 2025-10-29T13:56:48.702915 image/svg+xml Matplotlib v3.10.7, OilContents->TestResult OilContents->Reward
structs MEU 20.00 (stdev=103.92) Inference in   0.21ms Testing 2025-10-29T13:56:48.876080 image/svg+xml Matplotlib v3.10.7, Drilling 2025-10-29T13:56:48.893182 image/svg+xml Matplotlib v3.10.7, Testing->Drilling TestResult 2025-10-29T13:56:48.909583 image/svg+xml Matplotlib v3.10.7, Testing->TestResult Cost Cost : 0.00 (0.00) Testing->Cost Reward Reward : 20.00 (103.92) Drilling->Reward TestResult->Drilling OilContents 2025-10-29T13:56:48.929622 image/svg+xml Matplotlib v3.10.7, OilContents->TestResult OilContents->Reward
TestResult TestResult Drilling Drilling TestResult->Drilling OilContents OilContents OilContents->TestResult Reward Reward OilContents->Reward Testing Testing Testing->TestResult Testing->Drilling Cost Cost Testing->Cost Drilling->Reward
structs MEU 0.00 (stdev=0.00) Inference in   0.22ms Testing 2025-10-29T13:56:49.070306 image/svg+xml Matplotlib v3.10.7, Drilling 2025-10-29T13:56:49.087972 image/svg+xml Matplotlib v3.10.7, Testing->Drilling TestResult 2025-10-29T13:56:49.105687 image/svg+xml Matplotlib v3.10.7, Testing->TestResult Cost Cost : 0.00 (0.00) Testing->Cost Reward Reward : 0.00 (0.00) Drilling->Reward TestResult->Drilling OilContents 2025-10-29T13:56:49.124116 image/svg+xml Matplotlib v3.10.7, OilContents->TestResult OilContents->Reward
structs MEU 50.00 (stdev=0.00) Inference in   0.20ms Testing 2025-10-29T13:56:49.276152 image/svg+xml Matplotlib v3.10.7, Drilling 2025-10-29T13:56:49.292419 image/svg+xml Matplotlib v3.10.7, Testing->Drilling TestResult 2025-10-29T13:56:49.310183 image/svg+xml Matplotlib v3.10.7, Testing->TestResult Cost Cost : 0.00 (0.00) Testing->Cost Reward Reward : 50.00 (0.00) Drilling->Reward TestResult->Drilling OilContents 2025-10-29T13:56:49.332293 image/svg+xml Matplotlib v3.10.7, OilContents->TestResult OilContents->Reward
structs MEU 200.00 (stdev=0.00) Inference in   0.22ms Testing 2025-10-29T13:56:49.495403 image/svg+xml Matplotlib v3.10.7, Drilling 2025-10-29T13:56:49.511444 image/svg+xml Matplotlib v3.10.7, Testing->Drilling TestResult 2025-10-29T13:56:49.529067 image/svg+xml Matplotlib v3.10.7, Testing->TestResult Cost Cost : 0.00 (0.00) Testing->Cost Reward Reward : 200.00 (0.00) Drilling->Reward TestResult->Drilling OilContents 2025-10-29T13:56:49.549464 image/svg+xml Matplotlib v3.10.7, OilContents->TestResult OilContents->Reward
gnb.showInference(oil, evs={"OilContents": [0.7, 0.5, 0.8]})

svg

gnb.showInference(oil, evs={"Drilling": "Yes"})

svg

The default inference for influence diagram actually an inference for LIMIDs. In order to use it for classical (and solvable) influence diagram, do not forget to add the sequence of decision nodes using addNoForgettingAssumption.

infdiag = gum.fastID("Chance->*Decision1->Chance2->$Utility<-Chance3<-*Decision2<-Chance->Utility")
infdiag
Chance Chance Decision1 Decision1 Chance->Decision1 Decision2 Decision2 Chance->Decision2 Utility Utility Chance->Utility Chance2 Chance2 Chance2->Utility Chance3 Chance3 Chance3->Utility Decision1->Chance2 Decision2->Chance3
ie = gum.ShaferShenoyLIMIDInference(infdiag)
try:
ie.makeInference()
except gum.GumException as e:
print(e)
[pyAgrum] Fatal error: This LIMID/Influence Diagram is not solvable.
ie.addNoForgettingAssumption(["Decision1", "Decision2"])
gnb.sideBySide(ie.reducedLIMID(), ie.junctionTree(), gnb.getInference(infdiag, engine=ie))
Chance Chance Decision1 Decision1 Chance->Decision1 Decision2 Decision2 Chance->Decision2 Utility Utility Chance->Utility Chance2 Chance2 Chance2->Utility Chance3 Chance3 Chance3->Utility Decision1->Chance2 Decision1->Decision2 Decision2->Chance3
InfluenceDiagram Chance-Chance2-Decision1-Decision2 (0):Chance,Chance2,Decision1,Decision2 Chance-Chance2-Decision1-Decision2+Chance-Chance2-Chance3-Decision2 Chance,Chance2,Decision2 Chance-Chance2-Decision1-Decision2--Chance-Chance2-Decision1-Decision2+Chance-Chance2-Chance3-Decision2 Chance-Chance2-Chance3-Decision2 (1):Chance,Chance2,Chance3,Decision2 Chance-Chance2-Decision1-Decision2+Chance-Chance2-Chance3-Decision2--Chance-Chance2-Chance3-Decision2
structs MEU 18.41 (stdev=15.40) Inference in   0.28ms Chance 2025-10-29T13:56:50.585994 image/svg+xml Matplotlib v3.10.7, Decision1 2025-10-29T13:56:50.605283 image/svg+xml Matplotlib v3.10.7, Chance->Decision1 Utility Utility : 18.41 (15.40) Chance->Utility Decision2 2025-10-29T13:56:50.666867 image/svg+xml Matplotlib v3.10.7, Chance->Decision2 Chance2 2025-10-29T13:56:50.624976 image/svg+xml Matplotlib v3.10.7, Decision1->Chance2 Chance2->Utility Chance3 2025-10-29T13:56:50.648192 image/svg+xml Matplotlib v3.10.7, Chance3->Utility Decision2->Chance3

Using pyagrum.config, it is possible to adapt the graphical representations for Influence Diagram (see the notebook 99-Tools_configForPyAgrum.ipynb).

gum.config.reset()
gnb.showInference(infdiag, engine=ie, size="7!")

svg

Many visual options can be changed when displaing an inference (especially for influence diagrams)

## do not show inference time
gum.config["notebook", "show_inference_time"] = False
## more digits for probabilities
gum.config["notebook", "histogram_horizontal_visible_digits"] = 3
gnb.showInference(infdiag, engine=ie, size="7!")

svg

## specificic for influence diagram :
## more digits for utilities
gum.config["influenceDiagram", "utility_visible_digits"] = 5
## disabling stdev for utility and MEU
gum.config["influenceDiagram", "utility_show_stdev"] = False
## showing loss (=-utility) and mEL (minimum Expected Loss) instead of MEU
gum.config["influenceDiagram", "utility_show_loss"] = True
gnb.showInference(infdiag, engine=ie, size="7!")

svg

## visual changes for influence diagram and inference
gum.config.reset()
gum.config.push() # keep the current state
gum.config["notebook", "graph_rankdir"] = "LR"
gnb.sideBySide(infdiag, gnb.getInference(infdiag, engine=ie, targets=["Decision1", "Chance3"]))
Chance Chance Decision1 Decision1 Chance->Decision1 Decision2 Decision2 Chance->Decision2 Utility Utility Chance->Utility Chance2 Chance2 Chance2->Utility Chance3 Chance3 Chance3->Utility Decision1->Chance2 Decision2->Chance3
structs MEU 18.41 (stdev=15.40) Inference in   0.26ms Chance Chance Decision1 2025-10-29T13:56:51.819928 image/svg+xml Matplotlib v3.10.7, Chance->Decision1 Utility Utility : 18.41 (15.40) Chance->Utility Decision2 Decision2 Chance->Decision2 Chance2 Chance2 Decision1->Chance2 Chance2->Utility Chance3 2025-10-29T13:56:51.839579 image/svg+xml Matplotlib v3.10.7, Chance3->Utility Decision2->Chance3
## more visual changes for influence diagram and inference
gum.config.pop() # back to the last state
## shape (https://graphviz.org/doc/info/shapes.html)
gum.config["influenceDiagram", "chance_shape"] = "cylinder"
gum.config["influenceDiagram", "utility_shape"] = "star"
gum.config["influenceDiagram", "decision_shape"] = "box3d"
## colors
gum.config["influenceDiagram", "default_chance_bgcolor"] = "green"
gum.config["influenceDiagram", "default_utility_bgcolor"] = "MediumVioletRed"
gum.config["influenceDiagram", "default_decision_bgcolor"] = "DarkSalmon"
gum.config["influenceDiagram", "utility_show_stdev"] = False
gnb.sideBySide(infdiag, gnb.getInference(infdiag, engine=ie, targets=["Decision1", "Chance3"]))
Chance Chance Decision1 Decision1 Chance->Decision1 Decision2 Decision2 Chance->Decision2 Utility Utility Chance->Utility Chance2 Chance2 Chance2->Utility Chance3 Chance3 Chance3->Utility Decision1->Chance2 Decision2->Chance3
structs MEU 18.41 Inference in   0.25ms Chance Chance Decision1 2025-10-29T13:56:52.138059 image/svg+xml Matplotlib v3.10.7, Chance->Decision1 Utility Utility : 18.41 Chance->Utility Decision2 Decision2 Chance->Decision2 Chance2 Chance2 Decision1->Chance2 Chance2->Utility Chance3 2025-10-29T13:56:52.157683 image/svg+xml Matplotlib v3.10.7, Chance3->Utility Decision2->Chance3