def setUp(self): self.bn = gum.fastBN("c->s{no|yes}->w{no|yes};c->r->w") self.unsharpen(self.bn) self.c, self.s, self.w, self.r = [self.bn.idFromName(s) for s in "cswr"] self.bn2 = gum.fastBN("r2->s2->w2;r2->w2") self.unsharpen(self.bn2) self.r2, self.s2, self.w2 = [self.bn2.idFromName(s) for s in ["s2", "w2", "r2"]]
def testFromWHY19(self): bn = gum.fastBN("X->Y;U") d = csl.CausalModel(bn, [('Z', ["X", "Y", "U"])], True) _, pot, _ = csl.causalImpact(d, on="Y", doing="X") self.assertIsNone(pot) # HedgeException # Causality, Pearl, 2009, p66 bn = gum.fastBN("Z1->Z2->Z3->Y<-X->Z2;Z2->Y;Z1->X->Z3<-Z1") c = csl.CausalModel(bn, [("Z0", ("X", "Z1", "Z3"))], False) _, pot, explanation = csl.causalImpact(c, "Y", "X") self.assertIsNotNone(pot) self.assertEqual(explanation, "Do-calculus computations")
def testFillWithPotential(self): bn = gum.fastBN("A->B->C") pABC = bn.cpt("A") * bn.cpt("B") * bn.cpt("C") bn2 = gum.fastBN("A->B->C") bn2.cpt("A").fillWith(bn.cpt("A")) bn2.cpt("B").fillWith(pABC.margSumIn(["A", "B"]) / pABC.margSumIn(["A"])) bn2.cpt("C").fillWith(pABC.margSumIn(["B", "C"]) / pABC.margSumIn(["B"])) pABC2 = (bn2.cpt("A") * bn2.cpt("B") * bn2.cpt("C")) self.assertAlmostEqual(np.max(pABC2.reorganize(['A', 'B', 'C']).toarray() - pABC.reorganize(['A', 'B', 'C']).toarray()), 0) self.assertAlmostEqual(np.max(pABC.reorganize(['A', 'B', 'C']).toarray() - pABC2.reorganize(['A', 'B', 'C']).toarray()), 0)
def testMarkovBlanketMultiLevel(self): bn = gum.fastBN("Z<-A->B->C->D->E<-Y;X->G<-F<-C<-I<-H->W") self.assertEqual(gum.MarkovBlanket(bn, "C", 1).size(), 5) self.assertEqual(gum.MarkovBlanket(bn, "C", 2).size(), 11) self.assertEqual(gum.MarkovBlanket(bn, "C", 3).size(), 13) with self.assertRaises(gum.InvalidArgument): err = gum.MarkovBlanket(bn, "C", 0)
def testFromDictAndToDict(self): bn = gum.fastBN("a{chaud|tiede|froid}->b[5]<-c->d->e;c->e") i = bn.completeInstantiation() self.assertEqual(i.todict(withLabels=False), { 'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0 }) self.assertEqual(i.todict(), { 'a': 'chaud', 'b': '0', 'c': '0', 'd': '0', 'e': '0' }) i.fromdict({'a': 'tiede', 'bar': 'foo'}) self.assertEqual(i.todict(withLabels=False), { 'a': 1, 'b': 0, 'c': 0, 'd': 0, 'e': 0 })
def test_simpson(self): m1 = gum.fastBN("Gender->Drug->Patient;Gender->Patient") # Gender = 0 == male # Gender = 1 == female # Drug == 0 - not taking the Drug # Drug == 1 - taking the Drug # Patient = 0 -- not healed # Patient = 1 - healed m1.cpt("Gender")[:] = [0.5, 0.5] m1.cpt("Drug")[:] = [[0.25, 0.75], # Gender=0 [0.75, 0.25]] # Gender=1 m1.cpt("Patient")[{'Drug': 0, 'Gender': 0}] = [ 0.2, 0.8] # No Drug, Male -> healed in 0.8 of cases # No Drug, Female -> healed in 0.4 of cases m1.cpt("Patient")[{'Drug': 0, 'Gender': 1}] = [0.6, 0.4] m1.cpt("Patient")[{'Drug': 1, 'Gender': 0}] = [ 0.3, 0.7] # Drug, Male -> healed 0.7 of cases m1.cpt("Patient")[{'Drug': 1, 'Gender': 1}] = [ 0.8, 0.2] # Drug, Female -> healed in 0.2 of cases d1 = csl.CausalModel(m1) # from formula : \sum_{ Gender }{ P(Patient\mid Drug,Gender) \cdot P(Gender) } margPatient = (m1.cpt("Patient") * m1.cpt("Gender")).margSumOut(["Gender"]) lat, pot, expl = csl.causalImpact( d1, on="Patient", doing={"Drug"}) # when drug=1 self.assertEqual(pot, margPatient)
def testChain(self): bn = gum.fastBN("a->b->c") eg = gum.EssentialGraph(bn) self.assertEqual(eg.size(), 3) self.assertEqual(eg.sizeArcs(), 0) self.assertEqual(eg.sizeEdges(), 2)
def getBackDoors(self, fbn: str, cause: int, effect: int, latent: Set[int] = None): bn = gum.fastBN(fbn) return [[bn.variable(i).name() for i in bd] for bd in csl.backdoor_generator(bn.dag(), bn.idFromName(cause), bn.idFromName(effect), latent)]
def testCounterfactual(self): # experience=10-4*education+Ux # salaire=65+2.5*experience+5*education+Us # # Ux : [-2,10], sans a priori # Us : [0,25], sans a priori # education : 0,1,2 (low, medium, high), a priori [0.4,0.40.2] # experience : [0,20] # salaire : [65,150] edex = gum.fastBN( "Ux[-2,10]->experience[0,20]<-education{low|medium|high}->salary[65,150]<-Us[0,25];experience->salary") edex.cpt("Us").fillWith(1).normalize() edex.cpt("Ux").fillWith(1).normalize() edex.cpt("education")[:] = [0.4, 0.4, 0.2] edex.cpt("experience").fillWithFunction("10-4*education+Ux") edex.cpt("salary").fillWithFunction("round(65+2.5*experience+5*education+Us)") pot = csl.counterfactual(cm=csl.CausalModel(edex), profile={'experience': 8, 'education': 'low', 'salary': '86'}, whatif={"education"}, on={"salary"}, values={"education": "medium"}) self.assertEqual(pot[81 - 65], 1.0)
def testDrawSamples(self): bn = gum.fastBN("A->B[4]->C;A->D->C;D->E[3];") dbgen = gum.BNDatabaseGenerator(bn) nbsample = 100 nbsamples = [nbsample * i for i in [1, 100, 1000]] ns1, ns2, ns3 = nbsamples isOK = False for i in range(self.nbLoopForApproximatedTest): try: ll1, ll2, ll3 = [dbgen.drawSamples(n) for n in nbsamples] self.assertAlmostEqual(ns1 / ns2, ll1 / ll2, delta=0.1) self.assertAlmostEqual(ns3 / ns2, ll3 / ll2, delta=0.1) self.assertAlmostEqual(ns1 / ns3, ll1 / ll3, delta=0.1) isOK = True break except AssertionError: pass self.assertEqual(isOK, True, " Error in loop for Approximated tests") jointe = gum.Potential().fillWith(1) for i in bn.nodes(): jointe *= bn.cpt(i) entropy = jointe.entropy() self.assertAlmostEqual(entropy, -ll1 / ns1, delta=0.5) self.assertAlmostEqual(entropy, -ll2 / ns2, delta=0.2) self.assertAlmostEqual(entropy, -ll3 / ns3, delta=0.1)
def testVstructure(self): bn = gum.fastBN("a->b;c->b") eg = gum.EssentialGraph(bn) self.assertEqual(eg.size(), 3) self.assertEqual(eg.sizeArcs(), 2) self.assertEqual(eg.sizeEdges(), 0)
def testNotebook2(self): bn = gum.fastBN("A->B;C->B;C->D;B->D;A->C") eg = gum.EssentialGraph(bn) self.assertEqual(eg.size(), 4) self.assertEqual(eg.sizeArcs(), 0) self.assertEqual(eg.sizeEdges(), 5)
def testNotebook3(self): bn = gum.fastBN("Z->X->U;Y->X;Y->W") eg = gum.EssentialGraph(bn) self.assertEqual(eg.size(), 5) self.assertEqual(eg.sizeArcs(), 3) self.assertEqual(eg.sizeEdges(), 1)
def testCaseD(self): bn = gum.fastBN("a->b;c1->b;c2->b;a->c1;a->c2") eg = gum.EssentialGraph(bn) self.assertEqual(eg.size(), 4) self.assertEqual(eg.sizeArcs(), 3) self.assertEqual(eg.sizeEdges(), 2)
def testNotebook1(self): bn = gum.fastBN("A->B->C->D;E->B;F->G->D;F->H->I;E->J->K->I->M;K->L") eg = gum.EssentialGraph(bn) self.assertEqual(eg.size(), 13) self.assertEqual(eg.sizeArcs(), 8) self.assertEqual(eg.sizeEdges(), 5)
def test_CRAN1(self): bn = gum.fastBN("w->x->z->y;w->z") bn.cpt("w")[:] = [0.5, 0.5] bn.cpt("x")[:] = [[0.4, 0.6], [0.3, 0.7]] bn.cpt("z")[{'w': 0, 'x': 0}] = [0.2, 0.8] bn.cpt("z")[{'w': 0, 'x': 1}] = [0.1, 0.9] bn.cpt("z")[{'w': 1, 'x': 0}] = [0.4, 0.6] bn.cpt("z")[{'w': 1, 'x': 1}] = [0.5, 0.5] bn.cpt("y")[:] = [[0.1, 0.9], [0.2, 0.8]] d = csl.CausalModel(bn, [("lat1", ["x", "y"])]) # from the formula \sum_{ z ,w }{ P(z\mid w,x) \cdot P(w) \cdot # \sum_{ x' }{ P(y\mid w,x',z) \cdot P(x'\mid w) } # } marg = (bn.cpt("x") * bn.cpt("y")).margSumOut(["x"]) marg = (marg * bn.cpt("w") * bn.cpt("z")).margSumOut(["z", "w"]) _, pot, _ = csl.causalImpact(d, on={"y"}, doing={"x"}) # when x=1 self.assertEqual(pot, marg) _, pot, _ = csl.causalImpact(d, on="y", doing="x") # when x=1 self.assertEqual(pot, marg)
def testMoralizedAncestralGraph(self): bn = gum.fastBN("A->B<-C->D->E<-A->F;G->A;D->H;G<-I->C<-J") g = bn.moralizedAncestralGraph({"I", "J"}) self.assertEqual(g.nodes(), {8, 9}) self.assertEqual(g.edges(), set()) g = bn.moralizedAncestralGraph({"A"}) self.assertEqual(g.nodes(), {0, 6, 8}) self.assertEqual(g.edges(), {(0, 6), (6, 8)}) # V-structure g = bn.moralizedAncestralGraph({"C"}) self.assertEqual(g.nodes(), {2, 8, 9}) self.assertEqual(g.edges(), {(2, 8), (2, 9), (8, 9)}) g = bn.moralizedAncestralGraph({"A", "D", "I", "H"}) self.assertEqual(g.nodes(), {0, 2, 3, 6, 7, 8, 9}) self.assertEqual(g.edges(), {(2, 8), (2, 9), (8, 9), (2, 3), (3, 7), (0, 6), (6, 8)}) g = bn.moralizedAncestralGraph({"F", "B", "E", "H"}) self.assertEqual(g.nodes(), {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) self.assertEqual( g.edges(), {(2, 8), (2, 9), (8, 9), (2, 3), (3, 7), (0, 6), (6, 8), (0, 5), (0, 1), (3, 4), (0, 2), (0, 3), (0, 4), (1, 2)})
def testChainingAdd(self): bn = gum.fastBN("A->B") i = bn.completeInstantiation() m1 = gum.Instantiation().add(bn.variable("A")).add(bn.variable("B")) m2 = gum.Instantiation().add(bn.variable("B")).add(bn.variable("A")) self.assertEqual(i, m1) self.assertEqual(i, m2) m1.inc() self.assertNotEqual(i, m1) i = gum.Instantiation().addVarsFromModel(bn, ["A", "B"]) m1 = gum.Instantiation().add(bn.variable("A")).add(bn.variable("B")) m2 = gum.Instantiation().add(bn.variable("B")).add(bn.variable("A")) self.assertEqual(i, m1) self.assertEqual(i, m2) m1.inc() self.assertNotEqual(i, m1) i = gum.Instantiation().addVarsFromModel(bn, ["B", "A"]) m1 = gum.Instantiation().add(bn.variable("A")).add(bn.variable("B")) m2 = gum.Instantiation().add(bn.variable("B")).add(bn.variable("A")) self.assertEqual(i, m1) self.assertEqual(i, m2) m1.inc() self.assertNotEqual(i, m1)
def setUp(self): m = gum.fastBN("z2->x->z1->y;z2->z1;z2->z3->y") m.cpt("z2")[:] = [0.5, 0.5] m.cpt("x")[:] = [ [0.4, 0.6], # z2=0 [0.4, 0.6] ] # z2=1 m.cpt("z3")[:] = [ [0.3, 0.7], # z2=0 [0.3, 0.7] ] # z2=1 m.cpt("z1")[{"z2": 0, "x": 0}] = [0.2, 0.8] m.cpt("z1")[{"z2": 0, "x": 1}] = [0.25, 0.75] m.cpt("z1")[{"z2": 1, "x": 0}] = [0.1, 0.9] m.cpt("z1")[{"z2": 1, "x": 1}] = [0.15, 0.85] m.cpt("y")[{"z1": 0, "z3": 0}] = [0.5, 0.5] m.cpt("y")[{"z1": 0, "z3": 1}] = [0.45, 0.55] m.cpt("y")[{"z1": 1, "z3": 0}] = [0.4, 0.6] m.cpt("y")[{"z1": 1, "z3": 1}] = [0.35, 0.65] self.d = csl.CausalModel(m, [("X-Z2", ["x", "z2"]), ("X-Z3", ["x", "z3"]), ("X-Y", ["x", "y"]), ("Y-Z2", ["y", "z2"])], True) try: formula, result, msg = csl.causalImpact(self.d, on={"y", "z2", "z1", "z3"}, doing={"x"}) except csl.HedgeException as h: self.fail("Should not raise")
def test_DoCalculusp213(self): fd = gum.fastBN("w->z->x->y") fdModele = csl.CausalModel(fd, [("u1", ["w", "x"]), ("u2", ["w", "y"])], True) formula, impact, explanation = csl.causalImpact(fdModele, on="y", doing="x")
def testCopyToBN(self): bn = gum.fastBN("A->B->C->D;E<-C<-F") self.assertEqual(repr(bn.cpt("B").variable(1)), repr(bn.variable("A"))) frag = gum.BayesNetFragment(bn) frag.installNode("B") self.assertFalse(frag.checkConsistency()) with self.assertRaises(gum.OperationNotAllowed): minibn = frag.toBN() # checking if the nodes are well copied and referenced in frag and then in # minibn checking if the potential are well copied frag.installNode("A") self.assertTrue(frag.checkConsistency()) self.assertEqual(repr(bn.variable("A")), repr(frag.variable("A"))) self.assertEqual(repr(bn.variable("B")), repr(frag.variable("B"))) self.assertEqual(str(bn.cpt("A")), str(frag.cpt("A"))) self.assertEqual(str(bn.cpt("B")), str(frag.cpt("B"))) self.assertEqual(repr(frag.cpt("B").variable(1)), repr(bn.variable("A"))) self.assertEqual(repr(frag.cpt("B").variable(1)), repr(frag.variable("A"))) minibn = frag.toBN() self.assertEqual(minibn.size(), 2) self.assertEqual(minibn.sizeArcs(), 1) self.assertNotEqual(repr(bn.variable("A")), repr(minibn.variable("A"))) self.assertNotEqual(repr(bn.variable("B")), repr(minibn.variable("B"))) self.assertEqual(str(bn.cpt("A")), str(minibn.cpt("A"))) self.assertEqual(str(bn.cpt("B")), str(minibn.cpt("B"))) self.assertEqual(repr(minibn.cpt("B").variable(1)), repr(minibn.variable("A"))) self.assertNotEqual(repr(minibn.cpt("B").variable(1)), repr(frag.variable("A")))
def testExistsArc(self): bn = gum.fastBN("A->B->C<-D->E<-A<-G->F") self.assertTrue(bn.existsArc(0, 1)) self.assertTrue(bn.existsArc("A", "B")) self.assertFalse(bn.existsArc(1, 0)) self.assertFalse(bn.existsArc("B", "A")) self.assertFalse(bn.existsArc(0, 2)) self.assertFalse(bn.existsArc("A", "C"))
def testEvidenceJointImpact(self): bn = gum.fastBN("A->B->C->D;A->E->D;F->B;C->H;") ie = gum.LazyPropagation(bn) res = ie.evidenceJointImpact(["D", "E"], ["A", "B", "C", "F"]) joint = bn.cpt("A") * bn.cpt("B") * bn.cpt("C") * bn.cpt("D") * bn.cpt("E") * bn.cpt("F") * bn.cpt("H") pADCE = joint.margSumIn(["A", "C", "D", "E"]) pAC = pADCE.margSumOut(["D", "E"]) self.assertEqual(res, pADCE / pAC)
def test_CRAN2(self): bn = gum.fastBN("Z1->X->Z2->Y") d = csl.CausalModel(bn, [("L1", ["Z1", "X"]), ("L2", ["Z1", "Z2"]), ("L3", ["Z1", "Y"]), ("L4", ["Y", "X"])], True) _, pot, _ = csl.causalImpact(d, on="Y", doing={"X"}) self.assertIsNone(pot)
def test_dirichlet(self): bn = gum.fastBN("A->B<-C->D->E<-B") gum.generateSample(bn, 2000, self.agrumSrcDir("dirichlet.csv"), with_labels=True) bn2 = gum.fastBN("A->B->C->D->E") gum.generateSample(bn2, 2000, self.agrumSrcDir("database.csv"), with_labels=True) # bn is used to give the variables and their domains learner = gum.BNLearner(self.agrumSrcDir("database.csv"), bn) learner.useDirichletPrior(self.agrumSrcDir("dirichlet.csv"), 10) learner.useScoreAIC( ) # or another score with no included prior such as BDeu bn3 = learner.learnBN() self.assertEqual(bn.size(), 5)
def testAncestors(self): bn = gum.fastBN("A->B<-C->D->E<-A->F;G->A;D->H;G<-I->C<-J") self.assertEqual(bn.descendants(6), {0, 1, 4, 5}) self.assertEqual(bn.descendants("G"), {0, 1, 4, 5}) self.assertEqual(bn.descendants(1), set()) self.assertEqual(bn.descendants("B"), set()) self.assertEqual(bn.ancestors(1), {0, 2, 6, 8, 9}) self.assertEqual(bn.ancestors("B"), {0, 2, 6, 8, 9}) self.assertEqual(bn.ancestors(9), set()) self.assertEqual(bn.ancestors("J"), set())
def testOperatorEqual(self): bn = gum.fastBN("a{chaud|tiede|froid}->b[5]<-c->d->e;c->e") i = bn.completeInstantiation() j = bn.completeInstantiation() self.assertEqual(i, j) while not i.end(): self.assertEqual(i, j) i.inc() self.assertNotEqual(i, j) j.inc() k = gum.Instantiation() self.assertNotEqual(i, k) # not the same size k.inc() self.assertEqual(i, k) # both are in overflow => equals
def testMutilateBN(self): bn = gum.fastBN("P2->N<-P1;A->E2<-N->E1") bn2, _ = gum.mutilateBN(bn, intervention={"N": ["1"]}, observation={}) self.assertEquals(bn2.sizeArcs(), 1) self.assertEquals(bn2.size(), 5) bn2, _ = gum.mutilateBN(bn, intervention={}, observation={"N": [0, 1]}) self.assertEquals(bn2.sizeArcs(), 3) self.assertEquals(bn2.size(), 6) bn2, _ = gum.mutilateBN(bn, intervention={'A': ["1"]}, observation={"N": [0.3, 0.7]}) self.assertEquals(bn2.sizeArcs(), 4) self.assertEquals(bn2.size(), 5)
def test_minimalCondSet(self): bn = gum.fastBN("A->C->E->F->G;B->C;B->D->F;H->E") iA, iB, iC, iD, iE, iF, iG, iH = [bn.idFromName(s) for s in "ABCDEFGH"] tous = {iA, iB, iC, iD, iE, iF, iG, iH} r = bn.minimalCondSet(iA, tous) self.assertEqual(r, {iA}) r = bn.minimalCondSet(iA, tous - {iA}) self.assertEqual(r, {iB, iC}) r = bn.minimalCondSet(iA, {iE, iF, iG}) self.assertEqual(r, {iE, iF}) r = bn.minimalCondSet(iA, {iB, iC, iE, iF, iG}) self.assertEqual(r, {iB, iC}) r = bn.minimalCondSet(iA, {iC, iE, iF, iG}) self.assertEqual(r, {iC, iE, iF}) r = bn.minimalCondSet(iC, tous) self.assertEqual(r, {iC}) r = bn.minimalCondSet(iC, tous - {iC}) self.assertEqual(r, {iA, iB, iH, iE}) r = bn.minimalCondSet(iC, {iE, iF, iG}) self.assertEqual(r, {iE, iF}) r = bn.minimalCondSet(iC, {iB, iE, iF, iG}) self.assertEqual(r, {iE, iB}) r = bn.minimalCondSet(iC, {iC, iE, iF, iG}) self.assertEqual(r, {iC}) # for set of targets tous = {iA, iB, iC, iD, iE, iF, iG, iH} r = bn.minimalCondSet([iE, iD], tous) self.assertEqual(r, {iE, iD}) r = bn.minimalCondSet([iE, iD], tous - {iE}) self.assertEqual(r, {iC, iD, iH, iF}) r = bn.minimalCondSet([iE, iD], tous - {iE, iD}) self.assertEqual(r, {iB, iC, iH, iF})
def testIsIndependent(self): bn = gum.fastBN("A->B<-C->D->E<-A->F;G->A;D->H;G<-I->C<-J") self.assertTrue(bn.isIndependent("I", "J", {})) self.assertFalse(bn.isIndependent("I", "J", {"C"})) self.assertFalse(bn.isIndependent("I", "J", {"H"})) self.assertTrue(bn.isIndependent("I", "J", {"F"})) self.assertFalse(bn.isIndependent("I", "J", {"E"})) self.assertFalse(bn.isIndependent("I", "J", {"E", "G"})) self.assertFalse(bn.isIndependent("I", "J", {"E", "G", "H"})) self.assertFalse(bn.isIndependent("I", "H", {})) self.assertTrue(bn.isIndependent("I", "H", {"C"})) self.assertTrue(bn.isIndependent("I", "H", {"C", "B"})) self.assertFalse(bn.isIndependent("I", "H", {"C", "E"})) self.assertFalse(bn.isIndependent("I", "H", {"C", "E", "B"})) self.assertTrue(bn.isIndependent("I", "H", {"C", "E", "B", "G"}))