class ImportExportTest(unittest.TestCase): def setUp(self): # Create BayesNet self.bn = BayesNet(); # Create Nodes weather0 = DiscreteNode("Weather0", ["Sun", "Rain"]) weather = DiscreteNode("Weather", ["Sun", "Rain"]) ice_cream_eaten = DiscreteNode("Ice Cream Eaten", [True, False]) # Add nodes self.bn.add_node(weather0) self.bn.add_node(weather) self.bn.add_node(ice_cream_eaten) # Add edges self.bn.add_edge(weather, ice_cream_eaten) self.bn.add_edge(weather0, weather); # Set probabilities cpt_weather0 = numpy.array([.6, .4]) weather0.set_probability_table(cpt_weather0, [weather0]) cpt_weather = numpy.array([[.7, .5], [.3, .5]]) weather.set_probability_table(cpt_weather, [weather0, weather]) ice_cream_eaten.set_probability(.9, [(ice_cream_eaten, True), (weather, "Sun")]) ice_cream_eaten.set_probability(.1, [(ice_cream_eaten, False), (weather, "Sun")]) ice_cream_eaten.set_probability(.2, [(ice_cream_eaten, True), (weather, "Rain")]) ice_cream_eaten.set_probability(.8, [(ice_cream_eaten, False), (weather, "Rain")]) def test_import_export(self): # write BN xmlbif = XMLBIF(self.bn, "Test Net") xmlbif.write("test_out.xmlbif") # read BN bn2 = XMLBIF.read("test_out.xmlbif") for node1 in self.bn.get_nodes(): name_found = False cpd_equal = False value_range_equal = False str_equal = False pos_equal = False for node2 in bn2.get_nodes(): # Test node names if node1.name == node2.name: name_found = True cpd_equal = node1.get_cpd == node2.get_cpd value_range_equal = node1.get_value_range() == node2.get_value_range() str_equal = str(node1) == str(node2) pos_equal = node1.pos == node2.pos self.assertTrue(name_found) self.assertTrue(cpd_equal) self.assertTrue(value_range_equal) self.assertTrue(str_equal) self.assertTrue(pos_equal) # remove file os.remove("test_out.xmlbif")
class NodeAddAndRemoveTestCase(unittest.TestCase): def setUp(self): self.bn = BayesNet() def tearDown(self): self.bn = None def test_clear_and_len(self): self.assertFalse(0 == len(self.bn)) self.assertFalse(0 == self.bn.number_of_nodes()) self.bn.clear() self.assertEqual(0, len(self.bn)) self.assertEqual(0, self.bn.number_of_nodes()) def test_add_node(self): self.bn.clear() n = DiscreteNode("Some Node", [True, False]) self.bn.add_node(n) self.assertEqual(n, self.bn.get_node("Some Node")) self.assertTrue(n in self.bn.get_nodes(["Some Node"])) node_with_same_name = DiscreteNode("Some Node", [True, False]) self.assertRaises(Exception, self.bn.add_node, node_with_same_name) def test_remove_node(self): self.bn.clear() n = DiscreteNode("Some Node to remove", [True, False]) self.bn.add_node(n) self.bn.remove_node(n) self.assertFalse(n in self.bn.get_nodes([])) def test_add_edge(self): self.bn.clear() n1 = DiscreteNode("1", [True, False]) n2 = DiscreteNode("2", [True, False]) self.bn.add_node(n1) self.bn.add_node(n2) self.bn.add_edge(n1, n2) self.assertTrue(n1 in self.bn.get_parents(n2)) self.assertTrue(n2 in self.bn.get_children(n1)) def test_remove_edge(self): self.bn.clear() n1 = DiscreteNode("1", [True, False]) n2 = DiscreteNode("2", [True, False]) self.bn.add_node(n1) self.bn.add_node(n2) self.bn.add_edge(n1, n2) self.assertEqual([n1], self.bn.get_parents(n2)) self.bn.remove_edge(n1, n2) self.assertEqual([], self.bn.get_parents(n2)) def test_is_valid(self): self.bn.clear() n1 = DiscreteNode("1", [True, False]) n2 = DiscreteNode("2", [True, False]) self.bn.add_node(n1) self.bn.add_node(n2) self.bn.add_edge(n1, n2) self.assertTrue(self.bn.is_valid()) self.bn.add_edge(n1, n1) self.assertFalse(self.bn.is_valid()) self.bn.remove_edge(n1, n1) self.assertTrue(self.bn.is_valid()) n3 = DiscreteNode("3", [True, False]) n4 = DiscreteNode("4", [True, False]) self.bn.add_node(n3) self.bn.add_node(n4) self.assertTrue(self.bn.is_valid()) self.bn.add_edge(n2, n3) self.assertTrue(self.bn.is_valid()) self.bn.add_edge(n3, n4) self.assertTrue(self.bn.is_valid()) self.bn.add_edge(n4, n1) self.assertFalse(self.bn.is_valid())
class DynamicBayesNet(BayesNet): ''' This is the implementation of a dynamic Bayesian network (also called temporal Bayesian network). Definition: DBN is a pair (B0, TwoTBN), where B0 is a BN over X(0), representing the initial distribution over states, and TwoTBN is a 2-TBN for the process. See Koller, Friedman - "Probabilistic Graphical Models" (p. 204) Properties: Markov property, stationary, directed, discrete, acyclic (within a slice) ''' def __init__(self): super(DynamicBayesNet, self).__init__() self._B0 = BayesNet() self._twoTBN = TwoTBN() @property def B0(self): ''' Get the Bayesian network representing the initial distribution.''' return self._B0 @B0.setter def B0(self, value): ''' Set the Bayesian network representing the initial distribution.''' if isinstance(value, BayesNet): if not value.is_valid(): raise Exception("BayesNet is not valid.") self._B0 = value else: raise Exception("Can only set 'BayesNet' and its subclasses as " + "B0 of a DBN.") @property def twoTBN(self): ''' Get the 2-time-slice Bayesian network.''' return self._twoTBN @twoTBN.setter def twoTBN(self, value): ''' Set the 2-time-slice Bayesian network.''' if isinstance(value, TwoTBN): if not value.is_valid(): raise Exception("BayesNet is not valid.") self._twoTBN = value else: raise Exception("Can only set 'TwoTBN' and its subclasses as " + "twoTBN of a DBN.") def is_valid(self): '''Check if graph structure is valid. And if there is a same-named inital node in towTBN for every node in BO. Returns true if graph is directed and acyclic, false otherwiese''' for node in self._B0.get_nodes(): if not self._twoTBN.has_initial_node_by_name(node.name): print("Node with name " + str(node.name) + " not found in TwoTBN!") return False; return super(DynamicBayesNet, self).is_valid()