Influence diagram

Creative Commons License

aGrUM

interactive online version

In [1]:
import os

%matplotlib inline
from pylab import *
import matplotlib.pyplot as plt
from IPython.display import display,HTML

import math
In [2]:
import pyAgrum as gum
import pyAgrum.lib.notebook as gnb

Build a influencediagram

fast build with string

In [3]:
gum.fastID("A->*B->$C<-D<-*E->*G->H->*I<-D")
Out[3]:
G 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

bifxml format file

In [4]:
diag=gum.loadID("res/diag.bifxml")
gnb.showInfluenceDiagram(diag)
../_images/notebooks_21-Models_InfluenceDiagram_7_0.svg
In [5]:
diag
Out[5]:
G 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

the hard way :-)

In [6]:
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)
../_images/notebooks_21-Models_InfluenceDiagram_10_0.svg
In [7]:
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)

In [8]:
oil=gum.loadID("res/OilWildcatter.bifxml")
gnb.flow.row(oil,gnb.getInference(oil))
G 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.00ms Testing 2022-11-11T19:34:41.219713 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Drilling 2022-11-11T19:34:41.281925 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->Drilling TestResult 2022-11-11T19:34:41.329025 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->TestResult Cost Cost : -10.00 (0.00) Testing->Cost Reward Reward : 32.50 (87.46) Drilling->Reward TestResult->Drilling OilContents 2022-11-11T19:34:41.376837 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ OilContents->TestResult OilContents->Reward
In [9]:
# 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)

display(HTML("<h2>Inference in the LIMID optimizing the decisions nodes</h2>"))
ie.makeInference()
show_decisions(ie)

Inference in the LIMID optimizing the decisions nodes

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)$$
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)

In [10]:
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)
G 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   2.00ms Testing 2022-11-11T19:34:42.108240 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Drilling 2022-11-11T19:34:42.154057 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->Drilling TestResult 2022-11-11T19:34:42.203299 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->TestResult Cost Cost : -10.00 (0.00) Testing->Cost Reward Reward : 87.50 (104.73) Drilling->Reward TestResult->Drilling OilContents 2022-11-11T19:34:42.253883 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ OilContents->TestResult OilContents->Reward
structs MEU 22.86 (stdev=104.98) Inference in   1.51ms Testing 2022-11-11T19:34:42.507824 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Drilling 2022-11-11T19:34:42.559496 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->Drilling TestResult 2022-11-11T19:34:42.629976 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->TestResult Cost Cost : -10.00 (0.00) Testing->Cost Reward Reward : 32.86 (104.98) Drilling->Reward TestResult->Drilling OilContents 2022-11-11T19:34:42.678117 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ OilContents->TestResult OilContents->Reward
structs MEU 20.00 (stdev=103.92) Inference in   0.00ms Testing 2022-11-11T19:34:43.137896 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Drilling 2022-11-11T19:34:43.177984 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->Drilling TestResult 2022-11-11T19:34:43.246957 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->TestResult Cost Cost : 0.00 (0.00) Testing->Cost Reward Reward : 20.00 (103.92) Drilling->Reward TestResult->Drilling OilContents 2022-11-11T19:34:43.292518 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ OilContents->TestResult OilContents->Reward
G 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   1.00ms Testing 2022-11-11T19:34:43.511491 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Drilling 2022-11-11T19:34:43.563038 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->Drilling TestResult 2022-11-11T19:34:43.618243 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->TestResult Cost Cost : 0.00 (0.00) Testing->Cost Reward Reward : 0.00 (0.00) Drilling->Reward TestResult->Drilling OilContents 2022-11-11T19:34:43.665066 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ OilContents->TestResult OilContents->Reward
structs MEU 50.00 (stdev=0.00) Inference in   0.94ms Testing 2022-11-11T19:34:43.984809 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Drilling 2022-11-11T19:34:44.034084 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->Drilling TestResult 2022-11-11T19:34:44.103411 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->TestResult Cost Cost : 0.00 (0.00) Testing->Cost Reward Reward : 50.00 (0.00) Drilling->Reward TestResult->Drilling OilContents 2022-11-11T19:34:44.150235 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ OilContents->TestResult OilContents->Reward
structs MEU 200.00 (stdev=0.00) Inference in   1.07ms Testing 2022-11-11T19:34:44.414695 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Drilling 2022-11-11T19:34:44.456908 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->Drilling TestResult 2022-11-11T19:34:44.524628 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Testing->TestResult Cost Cost : 0.00 (0.00) Testing->Cost Reward Reward : 200.00 (0.00) Drilling->Reward TestResult->Drilling OilContents 2022-11-11T19:34:44.592718 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ OilContents->TestResult OilContents->Reward

Soft evidence on chance node

In [11]:
gnb.showInference(oil,evs={'OilContents':[0.7,0.5,0.8]})
../_images/notebooks_21-Models_InfluenceDiagram_18_0.svg

Forced decision

In [12]:
gnb.showInference(oil,evs={'Drilling':'Yes'})
../_images/notebooks_21-Models_InfluenceDiagram_20_0.svg

LIMID versus Influence Diagram

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.

In [13]:
infdiag=gum.fastID("Chance->*Decision1->Chance2->$Utility<-Chance3<-*Decision2<-Chance->Utility")
infdiag
Out[13]:
G 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
In [14]:
ie=gum.ShaferShenoyLIMIDInference(infdiag)
try:
    ie.makeInference()
except gum.GumException as e:
    print(e)
[pyAgrum] Fatal error: This LIMID/Influence Diagram is not solvable.
In [15]:
ie.addNoForgettingAssumption(["Decision1","Decision2"])
gnb.sideBySide(ie.reducedLIMID(),ie.junctionTree(),gnb.getInference(infdiag,engine=ie))
G 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.34 (stdev=12.14) Inference in   0.00ms Chance 2022-11-11T19:34:46.418707 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Decision1 2022-11-11T19:34:46.486165 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Chance->Decision1 Utility Utility : 18.34 (12.14) Chance->Utility Decision2 2022-11-11T19:34:46.626351 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Chance->Decision2 Chance2 2022-11-11T19:34:46.526017 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Decision1->Chance2 Chance2->Utility Chance3 2022-11-11T19:34:46.581110 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Chance3->Utility Decision2->Chance3

Customizing visualization of the results

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

In [16]:
gum.config.reset()
gnb.showInference(infdiag,engine=ie,size="7!")
../_images/notebooks_21-Models_InfluenceDiagram_26_0.svg

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

In [17]:
# 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!")
../_images/notebooks_21-Models_InfluenceDiagram_28_0.svg
In [18]:
# 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!")
../_images/notebooks_21-Models_InfluenceDiagram_29_0.svg
In [19]:
# more visual changes for influence diagram and inference
gum.config.reset()

#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"]))
G 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.34 Inference in   1.00ms Chance Chance Decision1 2022-11-11T19:34:48.778173 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Chance->Decision1 Utility Utility : 18.34 Chance->Utility Decision2 Decision2 Chance->Decision2 Chance2 Chance2 Decision1->Chance2 Chance2->Utility Chance3 2022-11-11T19:34:48.838777 image/svg+xml Matplotlib v3.6.2, https://matplotlib.org/ Chance3->Utility Decision2->Chance3
In [ ]: