def testBugInferenceWithEvidenceWithSemiFastSyntax(self): tst_id = gum.InfluenceDiagram() tst_id.addVariables(["c1","c","$u","*d"]) tst_id.addArcs([("c","c1"), ("c","u"), ("d","u")]) tst_id.cpt("c").fillWith([0.5, 0.5]) tst_id.cpt("c1")[{'c': 0}] = [1, 0] tst_id.cpt("c1")[{'c': 1}] = [0, 1] tst_id.utility("u")[{'c': 0, 'd': 0}] = [10] tst_id.utility("u")[{'c': 0, 'd': 1}] = [21] tst_id.utility("u")[{'c': 1, 'd': 0}] = [100] tst_id.utility("u")[{'c': 1, 'd': 1}] = [200] ie = gum.ShaferShenoyLIMIDInference(tst_id) ie.setEvidence({'c': 0}) ie.makeInference() self.assertEqual(ie.optimalDecision("d"), gum.Potential().add(tst_id.variableFromName("d")).fillWith([0, 1])) self.assertEqual(ie.MEU()['mean'], 21) ie = gum.ShaferShenoyLIMIDInference(tst_id) ie.setEvidence({'c': 1}) ie.makeInference() self.assertEqual(ie.optimalDecision("d"), gum.Potential().add(tst_id.variableFromName("d")).fillWith([0, 1])) self.assertEqual(ie.MEU()['mean'], 200)
def testBugInferenceWithEvidence(self): tst_id = gum.fastID("c1<-c->$u<-*d") tst_id.cpt("c").fillWith([0.5, 0.5]) tst_id.cpt("c1")[{'c': 0}] = [1, 0] tst_id.cpt("c1")[{'c': 1}] = [0, 1] tst_id.utility("u")[{'c': 0, 'd': 0}] = [10] tst_id.utility("u")[{'c': 0, 'd': 1}] = [21] tst_id.utility("u")[{'c': 1, 'd': 0}] = [100] tst_id.utility("u")[{'c': 1, 'd': 1}] = [200] ie = gum.ShaferShenoyLIMIDInference(tst_id) ie.setEvidence({'c': 0}) ie.makeInference() self.assertEqual(ie.optimalDecision("d"), gum.Potential().add(tst_id.variableFromName("d")).fillWith([0, 1])) self.assertEqual(ie.MEU()['mean'], 21) ie = gum.ShaferShenoyLIMIDInference(tst_id) ie.setEvidence({'c': 1}) ie.makeInference() self.assertEqual(ie.optimalDecision("d"), gum.Potential().add(tst_id.variableFromName("d")).fillWith([0, 1])) self.assertEqual(ie.MEU()['mean'], 200)
def LIMIDinference2dot(diag, size, engine, evs, targets): """ create a pydot representation of an inference in a influence diagram Parameters ---------- diag: pyAgrum.InfluenceDiagram the model size: float|str the size of the rendered graph engine: pyAgrum.InfluenceDiagramInference the inference algorithm used. If None, ShaferShenoyLIMIDInference will be used evs: Dict[str,str|int|List[float]] the evidence targets: Set[str] set of targetted variable. If targets={} then each node is a target Returns ------- pydot.Dot the representation of the inference """ startTime = time.time() if engine is None: ie = gum.ShaferShenoyLIMIDInference(diag) else: ie = engine ie.setEvidence(evs) ie.makeInference() stopTime = time.time() meu = ie.MEU() temp_dir = mkdtemp("", "tmp", None) # with TemporaryDirectory() as temp_dir: dotstr = "digraph structs {\n fontcolor=\"" + \ gumcols.getBlackInTheme() + "\";bgcolor=\"transparent\";" fmt = '.' + gum.config["influenceDiagram", "utility_visible_digits"] + 'f' if gum.config["influenceDiagram", "utility_show_loss"] == "True": titut = f'mEL {-meu["mean"]:{fmt}}' else: titut = f'MEU {meu["mean"]:{fmt}}' if gum.config["influenceDiagram", "utility_show_stdev"] == "True": titut += f' (stdev={math.sqrt(meu["variance"]):{fmt}})' slabel = f'label="{titut}' if gum.config["notebook", "show_inference_time"] == "True": slabel += f"\nInference in {1000 * (stopTime - startTime):6.2f}ms" dotstr += slabel + "\";\n" for nid in diag.nodes(): name = diag.variable(nid).name() # defaults if diag.isChanceNode(nid): bgcolor = gum.config["influenceDiagram", "default_chance_bgcolor"] fgcolor = gum.config["influenceDiagram", "default_chance_fgcolor"] shape = gum.config["influenceDiagram", "chance_shape"] elif diag.isDecisionNode(nid): bgcolor = gum.config["influenceDiagram", "default_decision_bgcolor"] fgcolor = gum.config["influenceDiagram", "default_decision_fgcolor"] shape = gum.config["influenceDiagram", "decision_shape"] else: # diag.isUtilityNode(nid): bgcolor = gum.config["influenceDiagram", "default_utility_bgcolor"] fgcolor = gum.config["influenceDiagram", "default_utility_fgcolor"] shape = gum.config["influenceDiagram", "utility_shape"] # 'hard' colour for evidence (?) if name in evs or nid in evs: bgcolor = gum.config["notebook", "evidence_bgcolor"] fgcolor = gum.config["notebook", "evidence_fgcolor"] styleattribute = 'style=filled, height=0,margin=0.1' colorattribute = f'fillcolor="{bgcolor}", fontcolor="{fgcolor}", color="#000000"' if not diag.isUtilityNode(nid): if len(targets) == 0 or name in targets or nid in targets: # shape="rectangle" filename = temp_dir + \ hashlib.md5(name.encode()).hexdigest() + "." + \ gum.config["notebook", "graph_format"] saveFigProba(ie.posterior(name), filename, bgcolor=bgcolor, util=ie.posteriorUtility(nid), txtcolor=fgcolor) dotstr += f' "{name}" [shape=rectangle,image="{filename}",label="", {colorattribute}];\n' else: dotstr += f' "{name}" [{colorattribute},shape={shape},{styleattribute}]' else: # utility node mv = ie.meanVar(name) if gum.config["influenceDiagram", "utility_show_loss"] == "True": coef = -1 else: coef = 1 fmt = "." + gum.config["influenceDiagram", "utility_visible_digits"] + "f" labut = f'{name} : {coef * mv["mean"]:{fmt}}' if gum.config["influenceDiagram", "utility_show_stdev"] == "True": labut += f' ({math.sqrt(mv["variance"]):{fmt}})' dotstr += f' "{name}" [label="{labut}",{colorattribute},{styleattribute},shape={shape}]' # arcs dotstr += "\n" for node in diag.nodes(): for chi in diag.children(node): dotstr += ' "' + diag.variable(node).name() + '"->"' + \ diag.variable(chi).name() + '"' if diag.isDecisionNode(chi): dotstr += f' [style="{gum.config["influenceDiagram", "decision_arc_style"]}"]' elif diag.isUtilityNode(chi): dotstr += f' [style="{gum.config["influenceDiagram", "utility_arc_style"]}"]' dotstr += ";\n" dotstr += "}" g = dot.graph_from_dot_data(dotstr)[0] # workaround for some badly parsed graph (pyparsing>=3.03) g.del_node('"\\n"') if size is None: size = gum.config["influenceDiagram", "default_id_inference_size"] g.set_size(size) g.temp_dir = temp_dir return g
def prepareShowInference(model, engine=None, evs=None, targets=None, size=None, nodeColor=None, factorColor=None, arcWidth=None, arcColor=None, cmap=None, cmapArc=None, graph=None, view=None): """ Transform an inference for a model in a dot representation Parameters ---------- model: pyAgrum:GraphicalModel the model in which to infer (pyAgrum.BayesNet, pyAgrum.MarkovNet or pyAgrum.InfluenceDiagram) filename: str the name of the resulting file (suffix in ['pdf', 'png', 'ps']). If filename is None, the result is a np.array ready to be used with imshow(). engine: pyAgrum.Inference inference algorithm used. If None, gum.LazyPropagation will be used for BayesNet,gum.ShaferShenoy for gum.MarkovNet and gum.ShaferShenoyLIMIDInference for gum.InfluenceDiagram. evs: Dict[str,str|int] map of evidence targets: Set[str|int] set of targets size: str size of the rendered graph nodeColor: Dict[int,float] a nodeMap of values (between 0 and 1) to be shown as color of nodes (with special colors for 0 and 1) factorColor: Dict[int,float] a nodeMap of values (between 0 and 1) to be shown as color of factors (in MarkovNet representation) arcWidth: Dict[(int,int),float] a arcMap of values to be shown as width of arcs arcColor: Dict[(int,int),float] a arcMap of values (between 0 and 1) to be shown as color of arcs cmap: matplotlib.colors.ColorMap color map to show the color of nodes and arcs cmapArc: matplotlib.colors.ColorMap color map to show the vals of Arcs. graph: pyAgrum.Graph only shows nodes that have their id in the graph (and not in the whole BN) view: str graph | factorgraph | None (default) for Markov network Raises ------ pyAgrum.InvalidArgument: if the arg is invalid Returns ------- str the obtained graph as a string """ if size is None: size = gum.config["notebook", "default_graph_inference_size"] if evs is None: evs = {} if targets is None: targets = {} if isinstance(model, gum.BayesNet): if engine is None: engine = gum.LazyPropagation(model) return BNinference2dot(model, size=size, engine=engine, evs=evs, targets=targets, nodeColor=nodeColor, arcWidth=arcWidth, arcColor=arcColor, cmapNode=cmap, cmapArc=cmapArc) if isinstance(model, gum.MarkovNet): if view is None: view = gum.config["notebook", "default_markovnetwork_view"] if engine is None: engine = gum.ShaferShenoyMNInference(model) if view == "graph": return MNinference2UGdot(model, size=size, engine=engine, evs=evs, targets=targets, nodeColor=nodeColor, factorColor=factorColor, arcWidth=arcWidth, arcColor=arcColor, cmapNode=cmap, cmapArc=cmapArc) # view=factor graph return MNinference2FactorGraphdot(model, size=size, engine=engine, evs=evs, targets=targets, nodeColor=nodeColor, factorColor=factorColor, cmapNode=cmap) if isinstance(model, gum.InfluenceDiagram): if engine is None: engine = gum.ShaferShenoyLIMIDInference(model) return LIMIDinference2dot(model, size=size, engine=engine, evs=evs, targets=targets) if isinstance(model, gum.CredalNet): if engine is None: engine = gum.CNMonteCarloSampling(model) return CNinference2dot(model, size=size, engine=engine, evs=evs, targets=targets, nodeColor=nodeColor, arcWidth=arcWidth, arcColor=arcColor, cmapNode=cmap) raise gum.InvalidArgument( "Argument model should be a PGM (BayesNet, MarkovNet or Influence Diagram)" )