def setUp(self):
        self.sn2 = {'grade': ['A', 'B', 'F'], 'diff': ['high', 'low'],
                    'intel': ['poor', 'good', 'very good']}
        self.sn1 = {'speed': ['low', 'medium', 'high'],
                    'switch': ['on', 'off'], 'time': ['day', 'night']}

        self.phi1 = Factor(['speed', 'switch', 'time'],
                           [3, 2, 2], np.ones(12))
        self.phi2 = Factor(['speed', 'switch', 'time'],
                           [3, 2, 2], np.ones(12), state_names=self.sn1)

        self.cpd1 = TabularCPD('grade', 3, [[0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
                                            [0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
                                            [0.8, 0.8, 0.8, 0.8, 0.8, 0.8]],
                               evidence=['diff', 'intel'],
                               evidence_card=[2, 3])
        self.cpd2 = TabularCPD('grade', 3, [[0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
                                            [0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
                                            [0.8, 0.8, 0.8, 0.8, 0.8, 0.8]],
                               evidence=['diff', 'intel'],
                               evidence_card=[2, 3],
                               state_names=self.sn2)

        student = BayesianModel([('diff', 'grade'), ('intel', 'grade')])
        diff_cpd = TabularCPD('diff', 2, [[0.2, 0.8]])
        intel_cpd = TabularCPD('intel', 2, [[0.3, 0.7]])
        grade_cpd = TabularCPD('grade', 3, [[0.1, 0.1, 0.1, 0.1],
                                            [0.1, 0.1, 0.1, 0.1],
                                            [0.8, 0.8, 0.8, 0.8]],
                               evidence=['diff', 'intel'],
                               evidence_card=[2, 2])
        student.add_cpds(diff_cpd, intel_cpd, grade_cpd)
        self.model1 = Inference(student)
        self.model2 = Inference(student, state_names=self.sn2)
Exemple #2
0
 def test_markov_inference_init(self):
     infer_markov = Inference(self.markov)
     self.assertEqual(set(infer_markov.variables), {'a', 'b', 'c', 'd'})
     self.assertEqual(infer_markov.cardinality, {
         'a': 2,
         'b': 2,
         'c': 2,
         'd': 2
     })
     self.assertEqual(
         infer_markov.factors, {
             'a': [
                 Factor(['a', 'b'], [2, 2], np.array([100, 1, 1, 100])),
                 Factor(['a', 'c'], [2, 2], np.array([40, 30, 100, 20]))
             ],
             'b': [
                 Factor(['a', 'b'], [2, 2], np.array([100, 1, 1, 100])),
                 Factor(['b', 'd'], [2, 2], np.array([1, 100, 100, 1]))
             ],
             'c': [
                 Factor(['a', 'c'], [2, 2], np.array([40, 30, 100, 20])),
                 Factor(['c', 'd'], [2, 2], np.array([60, 60, 40, 40]))
             ],
             'd': [
                 Factor(['b', 'd'], [2, 2], np.array([1, 100, 100, 1])),
                 Factor(['c', 'd'], [2, 2], np.array([60, 60, 40, 40]))
             ]
         })
Exemple #3
0
 def test_bayesian_inference_init(self):
     infer_bayesian = Inference(self.bayesian)
     self.assertEqual(set(infer_bayesian.variables),
                      {"a", "b", "c", "d", "e"})
     self.assertEqual(infer_bayesian.cardinality, {
         "a": 2,
         "b": 2,
         "c": 2,
         "d": 2,
         "e": 2
     })
     self.assertIsInstance(infer_bayesian.factors, defaultdict)
     self.assertEqual(
         set(infer_bayesian.factors["a"]),
         set([
             self.bayesian.get_cpds("a").to_factor(),
             self.bayesian.get_cpds("b").to_factor(),
         ]),
     )
     self.assertEqual(
         set(infer_bayesian.factors["b"]),
         set([
             self.bayesian.get_cpds("b").to_factor(),
             self.bayesian.get_cpds("c").to_factor(),
         ]),
     )
     self.assertEqual(
         set(infer_bayesian.factors["c"]),
         set([
             self.bayesian.get_cpds("c").to_factor(),
             self.bayesian.get_cpds("d").to_factor(),
         ]),
     )
     self.assertEqual(
         set(infer_bayesian.factors["d"]),
         set([
             self.bayesian.get_cpds("d").to_factor(),
             self.bayesian.get_cpds("e").to_factor(),
         ]),
     )
     self.assertEqual(
         set(infer_bayesian.factors["e"]),
         set([self.bayesian.get_cpds("e").to_factor()]),
     )
 def _absorption(self, marginal_tree, c_i, c_j):
     """
     Send a message from c_j to c_i during propagation.
     """
     # Union of all factors in c_j and its separators' factors
     neighbors = marginal_tree.neighbors(c_j)
     if c_i in neighbors:
         neighbors.remove(c_i)
     R_s = []
     for neighbor in neighbors:
         if (neighbor, c_j) in marginal_tree.separators:
             R_s.extend(marginal_tree.separators[(neighbor, c_j)])
     R_s.extend(marginal_tree.factor_node_assignment[c_j])
     separator = frozenset(c_i).intersection(frozenset(c_j))
     # Variables to marginalize from R_s
     marginalize = list(set(c_j) - set(separator))
     R_s = self._find_relevant_potentials(R_s, separator, marginal_tree)
     R_s = Inference.sum_out(marginalize, R_s)
     # Associate the messages with the separator of c_i and c_j,
     # in the right direction (from c_j to c_i)
     marginal_tree.separators[(c_j, c_i)] = R_s
Exemple #5
0
 def _absorption(self, marginal_tree, c_i, c_j):
     """
     Send a message from c_j to c_i during propagation.
     """
     # Union of all factors in c_j and its separators' factors
     neighbors = marginal_tree.neighbors(c_j)
     if c_i in neighbors:
         neighbors.remove(c_i)
     R_s = []
     for neighbor in neighbors:
         if (neighbor, c_j) in marginal_tree.separators:
             R_s.extend(marginal_tree.separators[(neighbor, c_j)])
     R_s.extend(marginal_tree.factor_node_assignment[c_j])
     separator = frozenset(c_i).intersection(frozenset(c_j))
     # Variables to marginalize from R_s
     marginalize = list(set(c_j) - set(separator))
     R_s = self._find_relevant_potentials(R_s, separator, marginal_tree)
     R_s = Inference.sum_out(marginalize, R_s)
     # Associate the messages with the separator of c_i and c_j,
     # in the right direction (from c_j to c_i)
     marginal_tree.separators[(c_j, c_i)] = R_s
Exemple #6
0
 def test_bayesian_inference_init(self):
     infer_bayesian = Inference(self.bayesian)
     self.assertEqual(set(infer_bayesian.variables),
                      {'a', 'b', 'c', 'd', 'e'})
     self.assertEqual(infer_bayesian.cardinality, {
         'a': 2,
         'b': 2,
         'c': 2,
         'd': 2,
         'e': 2
     })
     self.assertIsInstance(infer_bayesian.factors, defaultdict)
     self.assertEqual(
         set(infer_bayesian.factors['a']),
         set([
             self.bayesian.get_cpds('a').to_factor(),
             self.bayesian.get_cpds('b').to_factor()
         ]))
     self.assertEqual(
         set(infer_bayesian.factors['b']),
         set([
             self.bayesian.get_cpds('b').to_factor(),
             self.bayesian.get_cpds('c').to_factor()
         ]))
     self.assertEqual(
         set(infer_bayesian.factors['c']),
         set([
             self.bayesian.get_cpds('c').to_factor(),
             self.bayesian.get_cpds('d').to_factor()
         ]))
     self.assertEqual(
         set(infer_bayesian.factors['d']),
         set([
             self.bayesian.get_cpds('d').to_factor(),
             self.bayesian.get_cpds('e').to_factor()
         ]))
     self.assertEqual(set(infer_bayesian.factors['e']),
                      set([self.bayesian.get_cpds('e').to_factor()]))
Exemple #7
0
 def test_markov_inference_init(self):
     infer_markov = Inference(self.markov)
     self.assertEqual(set(infer_markov.variables), {"a", "b", "c", "d"})
     self.assertEqual(infer_markov.cardinality, {
         "a": 2,
         "b": 2,
         "c": 2,
         "d": 2
     })
     self.assertEqual(
         infer_markov.factors,
         {
             "a": [
                 DiscreteFactor(["a", "b"], [2, 2],
                                np.array([100, 1, 1, 100])),
                 DiscreteFactor(["a", "c"], [2, 2],
                                np.array([40, 30, 100, 20])),
             ],
             "b": [
                 DiscreteFactor(["a", "b"], [2, 2],
                                np.array([100, 1, 1, 100])),
                 DiscreteFactor(["b", "d"], [2, 2],
                                np.array([1, 100, 100, 1])),
             ],
             "c": [
                 DiscreteFactor(["a", "c"], [2, 2],
                                np.array([40, 30, 100, 20])),
                 DiscreteFactor(["c", "d"], [2, 2],
                                np.array([60, 60, 40, 40])),
             ],
             "d": [
                 DiscreteFactor(["b", "d"], [2, 2],
                                np.array([1, 100, 100, 1])),
                 DiscreteFactor(["c", "d"], [2, 2],
                                np.array([60, 60, 40, 40])),
             ],
         },
     )
 def query(self, query, evidence=None, elimination_order=None):
     if not isinstance(query, list):
         query = [query]
     ### DEBUG
     # print(">>>>>--------------------------------------<<<<<<")
     # print(">>> Query: %s" % query)
     # print(">>> Evidence: %s" % evidence)
     # print(">>> Saved MTs:")
     # for mt in self.marginal_trees:
     #     print("--> Nodes: %s" % mt.nodes())
     #     print(mt.evidence)
     ### --- DEBUG
     # See if it is possible to reuse saved MTs
     marginal_tree = None
     reuse_mts = self.find_reusable(query, evidence)
     ### DEBUG
     # print(">>> Reusable MTs:")
     # for mt in reuse_mts:
     #     print("--> Nodes: %s" % mt.nodes())
     #     print(mt.evidence)
     ### --- DEBUG
     factors = []
     if len(reuse_mts) > 0:
         # TODO: choose MT by the size of it
         # Choose one MT and rebuild it for the new query and evidence
         marginal_tree = reuse_mts[0]
         ### DEBUG
         # print(">>> Nodes before evidence")
         # print(marginal_tree.nodes())
         # print(">>> Messages before evidence")
         # for s in marginal_tree.separators:
         #     print("--> Separator %s" % s.__str__())
         #     for f in marginal_tree.separators[s]:
         #         print(f)
         ### --- DEBUG
         # Reduce new evidences
         new_evidence = {k: evidence[k]
                         for k in evidence
                         if k not in marginal_tree.evidence}
         marginal_tree.set_evidence(new_evidence)
         ### DEBUG
         # print(">>> Nodes after evidence")
         # print(marginal_tree.nodes())
         # print(">>> Messages before evidence")
         # for s in marginal_tree.separators:
         #     print("--> Separator %s" % s.__str__())
         #     for f in marginal_tree.separators[s]:
         #         print(f)
         ### --- DEBUG
         # Rebuild MT to answer new query
         marginal_tree = marginal_tree.rebuild(query, evidence)
         # Perform one way propagation
         self.partial_one_way_propagation(marginal_tree)
     else:
         marginal_tree = self._build(query, evidence, elimination_order)
     ### DEBUG
     # print(">>> Saving marginal tree")
     # print(marginal_tree.nodes())
     # print(marginal_tree.evidence)
     ### --- DEBUG
     # Save the new MT
     self.marginal_trees.append(marginal_tree)
     # Answer the query
     node = marginal_tree.root
     # Define the variables to marginalize
     marginalize = set(node) - set(query)
     # Collect factors for the node
     neighbors = marginal_tree.neighbors(node)
     # Collect incoming messages
     for neighbor in neighbors:
         if (neighbor, node) in marginal_tree.separators:
             factors.extend([f for f in marginal_tree.separators[(neighbor, node)]
                             if len(f.variables) > 0])
     ### DEBUG
     # print(">>> Root: %s" % marginal_tree.root.__str__())
     # print("incoming...")
     # for f in factors:
     #     print(f)
     ### --- DEBUG
     # Collect assigned Factors
     factors.extend([f for f in marginal_tree.factor_node_assignment[node]
                     if len(f.variables) > 0])
     ### DEBUG
     # print("assigned...")
     # for f in marginal_tree.factor_node_assignment[node]:
     #     print(f)
     # print("going to SUM OUT %s" % marginalize.__str__())
     # for f in factors:
     #     print(f)
     ### --- DEBUG
     result = None
     # Sum out variables from factors
     if len(factors) > 0:
         result = Inference.sum_out(marginalize, factors)
     ### DEBUG
     # print(">>> After SUM OUT")
     # for f in result:
     #     print(f)
     ### --- DEBUG
     # Multiply all remaining CPDs
     if len(result) > 0:
         result = factor_product(*result)
         ### DEBUG
         # print(">>> After PRODUCT")
         # print(result)
         ### --- DEBUG
         # Normalize
         result.normalize()
         ### DEBUG
         # print(">>> After Normalize")
         # print(result)
         # marginal_tree.draw()
         ### --- DEBUG
     return result
Exemple #9
0
 def query(self, query, evidence=None, elimination_order=None):
     if not isinstance(query, list):
         query = [query]
     ### DEBUG
     # print(">>>>>--------------------------------------<<<<<<")
     # print(">>> Query: %s" % query)
     # print(">>> Evidence: %s" % evidence)
     # print(">>> Saved MTs:")
     # for mt in self.marginal_trees:
     #     print("--> Nodes: %s" % mt.nodes())
     #     print(mt.evidence)
     ### --- DEBUG
     # See if it is possible to reuse saved MTs
     marginal_tree = None
     reuse_mts = self.find_reusable(query, evidence)
     ### DEBUG
     # print(">>> Reusable MTs:")
     # for mt in reuse_mts:
     #     print("--> Nodes: %s" % mt.nodes())
     #     print(mt.evidence)
     ### --- DEBUG
     factors = []
     if len(reuse_mts) > 0:
         # TODO: choose MT by the size of it
         # Choose one MT and rebuild it for the new query and evidence
         marginal_tree = reuse_mts[0]
         ### DEBUG
         # print(">>> Nodes before evidence")
         # print(marginal_tree.nodes())
         # print(">>> Messages before evidence")
         # for s in marginal_tree.separators:
         #     print("--> Separator %s" % s.__str__())
         #     for f in marginal_tree.separators[s]:
         #         print(f)
         ### --- DEBUG
         # Reduce new evidences
         new_evidence = {
             k: evidence[k]
             for k in evidence if k not in marginal_tree.evidence
         }
         marginal_tree.set_evidence(new_evidence)
         ### DEBUG
         # print(">>> Nodes after evidence")
         # print(marginal_tree.nodes())
         # print(">>> Messages before evidence")
         # for s in marginal_tree.separators:
         #     print("--> Separator %s" % s.__str__())
         #     for f in marginal_tree.separators[s]:
         #         print(f)
         ### --- DEBUG
         # Rebuild MT to answer new query
         marginal_tree = marginal_tree.rebuild(query, evidence)
         # Perform one way propagation
         self.partial_one_way_propagation(marginal_tree)
     else:
         marginal_tree = self._build(query, evidence, elimination_order)
     ### DEBUG
     # print(">>> Saving marginal tree")
     # print(marginal_tree.nodes())
     # print(marginal_tree.evidence)
     ### --- DEBUG
     # Save the new MT
     self.marginal_trees.append(marginal_tree)
     # Answer the query
     node = marginal_tree.root
     # Define the variables to marginalize
     marginalize = set(node) - set(query)
     # Collect factors for the node
     neighbors = marginal_tree.neighbors(node)
     # Collect incoming messages
     for neighbor in neighbors:
         if (neighbor, node) in marginal_tree.separators:
             factors.extend([
                 f for f in marginal_tree.separators[(neighbor, node)]
                 if len(f.variables) > 0
             ])
     ### DEBUG
     # print(">>> Root: %s" % marginal_tree.root.__str__())
     # print("incoming...")
     # for f in factors:
     #     print(f)
     ### --- DEBUG
     # Collect assigned Factors
     factors.extend([
         f for f in marginal_tree.factor_node_assignment[node]
         if len(f.variables) > 0
     ])
     ### DEBUG
     # print("assigned...")
     # for f in marginal_tree.factor_node_assignment[node]:
     #     print(f)
     # print("going to SUM OUT %s" % marginalize.__str__())
     # for f in factors:
     #     print(f)
     ### --- DEBUG
     result = None
     # Sum out variables from factors
     if len(factors) > 0:
         result = Inference.sum_out(marginalize, factors)
     ### DEBUG
     # print(">>> After SUM OUT")
     # for f in result:
     #     print(f)
     ### --- DEBUG
     # Multiply all remaining CPDs
     if len(result) > 0:
         result = factor_product(*result)
         ### DEBUG
         # print(">>> After PRODUCT")
         # print(result)
         ### --- DEBUG
         # Normalize
         result.normalize()
         ### DEBUG
         # print(">>> After Normalize")
         # print(result)
         # marginal_tree.draw()
         ### --- DEBUG
     return result
    def setUp(self):
        self.sn2 = {
            "grade": ["A", "B", "F"],
            "diff": ["high", "low"],
            "intel": ["poor", "good", "very good"],
        }
        self.sn1 = {
            "speed": ["low", "medium", "high"],
            "switch": ["on", "off"],
            "time": ["day", "night"],
        }

        self.sn2_no_names = {
            "grade": [0, 1, 2],
            "diff": [0, 1],
            "intel": [0, 1, 2]
        }
        self.sn1_no_names = {
            "speed": [0, 1, 2],
            "switch": [0, 1],
            "time": [0, 1]
        }

        self.phi1 = DiscreteFactor(["speed", "switch", "time"], [3, 2, 2],
                                   np.ones(12))
        self.phi2 = DiscreteFactor(["speed", "switch", "time"], [3, 2, 2],
                                   np.ones(12),
                                   state_names=self.sn1)

        self.cpd1 = TabularCPD(
            "grade",
            3,
            [
                [0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
                [0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
                [0.8, 0.8, 0.8, 0.8, 0.8, 0.8],
            ],
            evidence=["diff", "intel"],
            evidence_card=[2, 3],
        )
        self.cpd2 = TabularCPD(
            "grade",
            3,
            [
                [0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
                [0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
                [0.8, 0.8, 0.8, 0.8, 0.8, 0.8],
            ],
            evidence=["diff", "intel"],
            evidence_card=[2, 3],
            state_names=self.sn2,
        )

        student = BayesianModel([("diff", "grade"), ("intel", "grade")])
        diff_cpd = TabularCPD("diff", 2, [[0.2, 0.8]])
        intel_cpd = TabularCPD("intel", 2, [[0.3, 0.7]])
        grade_cpd = TabularCPD(
            "grade",
            3,
            [[0.1, 0.1, 0.1, 0.1], [0.1, 0.1, 0.1, 0.1], [0.8, 0.8, 0.8, 0.8]],
            evidence=["diff", "intel"],
            evidence_card=[2, 2],
        )
        student.add_cpds(diff_cpd, intel_cpd, grade_cpd)
        self.model1 = Inference(student)
        self.model2 = Inference(student)