def factor_product(*args): """ Returns factor product over `args`. Parameters ---------- args: `BaseFactor` instances. factors to be multiplied Returns ------- BaseFactor: `BaseFactor` representing factor product over all the `BaseFactor` instances in args. Examples -------- >>> from pgmpy.factors.discrete import DiscreteFactor >>> from pgmpy.factors import factor_product >>> phi1 = DiscreteFactor(['x1', 'x2', 'x3'], [2, 3, 2], range(12)) >>> phi2 = DiscreteFactor(['x3', 'x4', 'x1'], [2, 2, 2], range(8)) >>> phi = factor_product(phi1, phi2) >>> phi.variables ['x1', 'x2', 'x3', 'x4'] >>> phi.cardinality array([2, 3, 2, 2]) >>> phi.values array([[[[ 0, 0], [ 4, 6]], [[ 0, 4], [12, 18]], [[ 0, 8], [20, 30]]], [[[ 6, 18], [35, 49]], [[ 8, 24], [45, 63]], [[10, 30], [55, 77]]]]) """ if not all(isinstance(phi, BaseFactor) for phi in args): raise TypeError("Arguments must be factors") # Check if all of the arguments are of the same type elif len(set(map(type, args))) != 1: raise NotImplementedError("All the args are expected to ", "be instances of the same factor class.") for arg in args: for i in range(len(arg.values)): replace_absolute_values(arg.values, i) return reduce(lambda phi1, phi2: phi1 * phi2, args)
def factor_product(*args): """ Returns factor product over `args`. Parameters ---------- args: `BaseFactor` instances. factors to be multiplied Returns ------- BaseFactor: `BaseFactor` representing factor product over all the `BaseFactor` instances in args. Examples -------- >>> from pgmpy.factors.discrete import DiscreteFactor >>> from pgmpy.factors import factor_product >>> phi1 = DiscreteFactor(['x1', 'x2', 'x3'], [2, 3, 2], range(12)) >>> phi2 = DiscreteFactor(['x3', 'x4', 'x1'], [2, 2, 2], range(8)) >>> phi = factor_product(phi1, phi2) >>> phi.variables ['x1', 'x2', 'x3', 'x4'] >>> phi.cardinality array([2, 3, 2, 2]) >>> phi.values array([[[[ 0, 0], [ 4, 6]], [[ 0, 4], [12, 18]], [[ 0, 8], [20, 30]]], [[[ 6, 18], [35, 49]], [[ 8, 24], [45, 63]], [[10, 30], [55, 77]]]]) """ if not all(isinstance(phi, BaseFactor) for phi in args): raise TypeError("Arguments must be factors") # Check if all of the arguments are of the same type elif len(set(map(type, args))) != 1: raise NotImplementedError("All the args are expected to ", "be instances of the same factor class.") return reduce(lambda phi1, phi2: phi1 * phi2, args)
def factor_product(*args): """ Returns factor product over `args`. Parameters ---------- args: `Factor` instances. factors to be multiplied Returns ------- Factor: `Factor` representing factor product over all the `Factor` instances in args. Examples -------- >>> from pgmpy.factors import Factor, factor_product >>> phi1 = Factor(['x1', 'x2', 'x3'], [2, 3, 2], range(12)) >>> phi2 = Factor(['x3', 'x4', 'x1'], [2, 2, 2], range(8)) >>> phi = factor_product(phi1, phi2) >>> phi.variables ['x1', 'x2', 'x3', 'x4'] >>> phi.cardinality array([2, 3, 2, 2]) >>> phi.values array([[[[ 0, 0], [ 4, 6]], [[ 0, 4], [12, 18]], [[ 0, 8], [20, 30]]], [[[ 6, 18], [35, 49]], [[ 8, 24], [45, 63]], [[10, 30], [55, 77]]]]) """ if not all(isinstance(phi, Factor) for phi in args): raise TypeError("Arguments must be factors") return reduce(lambda phi1, phi2: phi1 * phi2, args)
def is_imap(self, JPD): """ Checks whether the bayesian model is Imap of given JointProbabilityDistribution Parameters ---------- JPD : An instance of JointProbabilityDistribution Class, for which you want to check the Imap Returns ------- boolean : True if bayesian model is Imap for given Joint Probability Distribution False otherwise Examples -------- >>> from pgmpy.models import BayesianModel >>> from pgmpy.factors.discrete import TabularCPD >>> from pgmpy.factors.discrete import JointProbabilityDistribution >>> G = BayesianModel([('diff', 'grade'), ('intel', 'grade')]) >>> diff_cpd = TabularCPD('diff', 2, [[0.2], [0.8]]) >>> intel_cpd = TabularCPD('intel', 3, [[0.5], [0.3], [0.2]]) >>> grade_cpd = 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]) >>> G.add_cpds(diff_cpd, intel_cpd, grade_cpd) >>> val = [0.01, 0.01, 0.08, 0.006, 0.006, 0.048, 0.004, 0.004, 0.032, 0.04, 0.04, 0.32, 0.024, 0.024, 0.192, 0.016, 0.016, 0.128] >>> JPD = JointProbabilityDistribution(['diff', 'intel', 'grade'], [2, 3, 3], val) >>> G.is_imap(JPD) True """ if not isinstance(JPD, JointProbabilityDistribution): raise TypeError( "JPD must be an instance of JointProbabilityDistribution") factors = [cpd.to_factor() for cpd in self.get_cpds()] factor_prod = reduce(mul, factors) JPD_fact = DiscreteFactor(JPD.variables, JPD.cardinality, JPD.values) if JPD_fact == factor_prod: return True else: return False
def is_imap(self, JPD): """ Checks whether the bayesian model is Imap of given JointProbabilityDistribution Parameters ----------- JPD : An instance of JointProbabilityDistribution Class, for which you want to check the Imap Returns -------- boolean : True if bayesian model is Imap for given Joint Probability Distribution False otherwise Examples -------- >>> from pgmpy.models import BayesianModel >>> from pgmpy.factors.discrete import TabularCPD >>> from pgmpy.factors.discrete import JointProbabilityDistribution >>> G = BayesianModel([('diff', 'grade'), ('intel', 'grade')]) >>> diff_cpd = TabularCPD('diff', 2, [[0.2], [0.8]]) >>> intel_cpd = TabularCPD('intel', 3, [[0.5], [0.3], [0.2]]) >>> grade_cpd = 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]) >>> G.add_cpds(diff_cpd, intel_cpd, grade_cpd) >>> val = [0.01, 0.01, 0.08, 0.006, 0.006, 0.048, 0.004, 0.004, 0.032, 0.04, 0.04, 0.32, 0.024, 0.024, 0.192, 0.016, 0.016, 0.128] >>> JPD = JointProbabilityDistribution(['diff', 'intel', 'grade'], [2, 3, 3], val) >>> G.is_imap(JPD) True """ if not isinstance(JPD, JointProbabilityDistribution): raise TypeError("JPD must be an instance of JointProbabilityDistribution") factors = [cpd.to_factor() for cpd in self.get_cpds()] factor_prod = reduce(mul, factors) JPD_fact = DiscreteFactor(JPD.variables, JPD.cardinality, JPD.values) if JPD_fact == factor_prod: return True else: return False
def factorset_product(*factorsets_list): r""" Base method used for product of factor sets. Suppose :math:`\vec\phi_1` and :math:`\vec\phi_2` are two factor sets then their product is a another factors set :math:`\vec\phi_3 = \vec\phi_1 \cup \vec\phi_2`. Parameters ---------- factorsets_list: FactorSet1, FactorSet2, ..., FactorSetn All the factor sets to be multiplied Returns ------- Product of factorset in factorsets_list Examples -------- >>> from pgmpy.factors import FactorSet >>> from pgmpy.factors.discrete import DiscreteFactor >>> from pgmpy.factors import factorset_product >>> phi1 = DiscreteFactor(['x1', 'x2', 'x3'], [2, 3, 2], range(12)) >>> phi2 = DiscreteFactor(['x3', 'x4', 'x1'], [2, 2, 2], range(8)) >>> factor_set1 = FactorSet(phi1, phi2) >>> phi3 = DiscreteFactor(['x5', 'x6', 'x7'], [2, 2, 2], range(8)) >>> phi4 = DiscreteFactor(['x5', 'x7', 'x8'], [2, 2, 2], range(8)) >>> factor_set2 = FactorSet(phi3, phi4) >>> factor_set3 = factorset_product(factor_set1, factor_set2) >>> print(factor_set3) set([<DiscreteFactor representing phi(x1:2, x2:3, x3:2) at 0x7fb3a1933e90>, <DiscreteFactor representing phi(x5:2, x7:2, x8:2) at 0x7fb3a1933f10>, <DiscreteFactor representing phi(x5:2, x6:2, x7:2) at 0x7fb3a1933f90>, <DiscreteFactor representing phi(x3:2, x4:2, x1:2) at 0x7fb3a1933e10>]) """ if not all( isinstance(factorset, FactorSet) for factorset in factorsets_list): raise TypeError("Input parameters must be FactorSet instances") return reduce(lambda x, y: x.product(y, inplace=False), factorsets_list)
def factorset_product(*factorsets_list): r""" Base method used for product of factor sets. Suppose :math:`\vec\phi_1` and :math:`\vec\phi_2` are two factor sets then their product is a another factors set :math:`\vec\phi_3 = \vec\phi_1 \cup \vec\phi_2`. Parameters ---------- factorsets_list: FactorSet1, FactorSet2, ..., FactorSetn All the factor sets to be multiplied Returns ------- Product of factorset in factorsets_list Examples -------- >>> from pgmpy.factors import FactorSet >>> from pgmpy.factors.discrete import DiscreteFactor >>> from pgmpy.factors import factorset_product >>> phi1 = DiscreteFactor(['x1', 'x2', 'x3'], [2, 3, 2], range(12)) >>> phi2 = DiscreteFactor(['x3', 'x4', 'x1'], [2, 2, 2], range(8)) >>> factor_set1 = FactorSet(phi1, phi2) >>> phi3 = DiscreteFactor(['x5', 'x6', 'x7'], [2, 2, 2], range(8)) >>> phi4 = DiscreteFactor(['x5', 'x7', 'x8'], [2, 2, 2], range(8)) >>> factor_set2 = FactorSet(phi3, phi4) >>> factor_set3 = factorset_product(factor_set1, factor_set2) >>> print(factor_set3) set([<DiscreteFactor representing phi(x1:2, x2:3, x3:2) at 0x7fb3a1933e90>, <DiscreteFactor representing phi(x5:2, x7:2, x8:2) at 0x7fb3a1933f10>, <DiscreteFactor representing phi(x5:2, x6:2, x7:2) at 0x7fb3a1933f90>, <DiscreteFactor representing phi(x3:2, x4:2, x1:2) at 0x7fb3a1933e10>]) """ if not all(isinstance(factorset, FactorSet) for factorset in factorsets_list): raise TypeError("Input parameters must be FactorSet instances") return reduce(lambda x, y: x.product(y, inplace=False), factorsets_list)
# * KLD solution # A natural choice of objective function will be the Kullback-Leibler (KL) divergence of two probability distribution $p(\mathbf{x})$ and $q(\mathbf{x})$, i.e., $KL(p(\mathbf{x})||q(\mathbf{x}))$. # This should be straightforward using the standard Boltzmann machine training since the # Bayesian network also allows us to evaluate the expected $\phi(\mathbf{x})$ under $p(\mathbf{x})$ tractably. # The only issue left is the negative phase in training Boltzmann machine, which requires evaluation of partition function. # We can circumvent this requirement by using either Monte-Carlo Markov Chain (MCMC) method like contrastive divergence (CD) or persistent CD (PCD), # or quantum hardware to draw samples with quantum mechanics. # We can also find the optimal solution by minimizing the KL-divergence. # Obtain the joint probability distribution (JPD) from conditional probability distributiom. # calculate the true JPD fron CPDs factors = [cpd.to_factor() for cpd in grass_model.get_cpds()] factor_prod = reduce(mul, factors) p_true = factor_prod.values.flatten().astype('float32') print(factor_prod) #------------------------------------ # Method (1) Least-squares solution #------------------------------------ #optimization function def optimize_lsq(p, nodes): # Define phi x1, x2, x3, x4 = symbols('x1, x2, x3, x4') h1, h2, h3, h4, J12, J13, J23, J24, J34, a, b = symbols(