示例#1
0
  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"]]
示例#2
0
  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")
示例#3
0
  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)
示例#4
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)
示例#5
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
     })
示例#6
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)
示例#7
0
    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)
示例#8
0
 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)]
示例#9
0
  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)
示例#11
0
    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)
示例#12
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)
示例#13
0
    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)
示例#14
0
    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)
示例#15
0
    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)
示例#16
0
  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)
示例#17
0
    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)})
示例#18
0
    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)
示例#19
0
    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")
示例#20
0
 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")
示例#21
0
    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")))
示例#22
0
    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"))
示例#23
0
  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)
示例#24
0
  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)
示例#25
0
    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)
示例#26
0
    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())
示例#27
0
    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
示例#28
0
    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)
示例#29
0
    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})
示例#30
0
    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"}))