def sprinkler_test_0(self): ''' Simple network from "An introduction to graphical models" by Kevin P. Murphy C -> S C -> R S -> W R -> W ''' C = RandVar("Cloudy", ["F", "T"]) S = RandVar("Sprinkler", ["F", "T"]) R = RandVar("Rain", ["F", "T"]) W = RandVar("WetGrass", ["F", "T"]) Cf = Factor([C], [0.5, 0.5]) Sf = Factor([S, C], [0.5, 0.5, 0.9, 0.1]) Rf = Factor([R, C], [0.8, 0.2, 0.2, 0.5]) Wf = Factor([W, S, R], [1.0, 0.0, 0.1, 0.9, 0.1, 0.9, 0.01, 0.99]) SprinklerNW = bn.BayesianNetwork([(C, Cf, []), (S, Sf, [C]), (R, Rf, [C]), (W, Wf, [S, R])]) cases = [(W, 1, [(S, "T"), (R, "F")], 0.9)] for (qvar, qvalue, evidence, expect) in cases: result = SprinklerNW.eliminationAsk(qvar, evidence) print("qvar: %s\nevidence: %s\nexpect: %s\nresult: %s" % (qvar.name, ",".join( ["%s=%s" % (x[0].name, x[1]) for x in evidence]), expect, result.values[qvalue])) assert_almost_equal(result.values[qvalue], expect, places=3)
def ex1(): """ Example of the Channel Capacity algorithm applied to a binary symmetric channel. Such channels have an explicit way to have their channel capacity computed. Which is: C = 1 - H(p), where p is the probability of error in the channel:: p 0 --- 0 \ / 1-p / / \ 1-p 1 --- 1 p In this example the probability of error is 0.1 """ p = 0.9 Input = RandVar("Input", ["T", "F"]) Output = RandVar("Output", ["T", "F"]) Prior = Factor(Input, [0.5, 0.5]) Channel = Factor([Input, Output], [p, 1 - p, 1 - p, p]) cc = ChannelCapacity(Input, Output, Prior, Channel) explicit = 1 - entropy(Factor(Input, [p, 1 - p])) print("Channel Capacity of a binary symmetric channel") print("Blahut-Arimoto:", cc) print("Explicit: ", explicit)
def factor_test(self): X = RandVar("X", [0, 1]) Y = RandVar("Y", [0, 1]) f1 = Factor(X, [0, 1]) f2 = Factor([X, Y], [0, 1, 2, 3]) assert(f1.__repr__() == "(X, [0, 1])") assert(f2.__repr__() == "([X, Y], [0, 1, 2, 3])")
def ex2(): domain = [str(i) for i in range(2)] Input = RandVar("Input", domain) Output = RandVar("Output", domain) Prior = Factor(Input, [1.0 / 2.0] * 2) channel_dist = [random.random() for i in range(4)] Channel = Factor([Input, Output], channel_dist).normalize(Input) print(ChannelCapacity(Input, Output, Prior, Channel))
def min_test_2(self): """ Minimum with one variable """ for i, domain in enumerate(self.X.domain): fac = Factor(self.X, [1, 2]) fac.values[i] = -10 assert(fac.min() == -10)
def max_test_0(self): """ Maximum with one variable """ for i, domain in enumerate(self.X.domain): fac = Factor(self.X, [1, 2]) fac.values[i] = 10 assert(fac.max() == 10)
def max_test_1(self): """ Maximum with two variables """ for i, domainx in enumerate(self.X.domain): for j, domainy in enumerate(self.Y.domain): fac = Factor([self.X, self.Y], [1, 2, 3, 4]) fac.values[i + j*2] = 10 assert(fac.max() == 10)
def min_test_3(self): """ Minimum with two variables """ for i, domainx in enumerate(self.X.domain): for j, domainy in enumerate(self.Y.domain): fac = Factor([self.X, self.Y], [1, 2, 3, 4]) fac.values[i + j*2] = -10 assert(fac.min() == -10)
def argmin_test_6(self): """ Minimum argument with one variable """ for i, domain in enumerate(self.X.domain): fac = Factor(self.X, [1, 2]) fac.values[i] = -10 event = Event([(self.X, domain)]) assert(fac.argmin() == event)
def argmin_test_7(self): """ Minimum argument with two variables """ for i, domainx in enumerate(self.X.domain): for j, domainy in enumerate(self.Y.domain): fac = Factor([self.X, self.Y], [1, 2, 3, 4]) fac.values[i + j*2] = -10 event = Event([(self.X, domainx), (self.Y, domainy)]) assert(fac.argmin() == event)
def student_test_0(self): ''' Student network from "Probabilistic graphical models principles and techniques" by Koller and Friedman D -> G I -> G I -> S G -> L ''' D = RandVar("Difficulty", ["easy", "hard"]) I = RandVar("Intelligence", ["low", "high"]) G = RandVar("Grade", ["a", "b", "c"]) S = RandVar("SAT", ["low", "high"]) L = RandVar("Letter", ["weak", "good"]) Df = Factor([D], [0.6, 0.4]) If = Factor([I], [0.7, 0.3]) Gf = Factor([G, D, I], [ 0.30, 0.40, 0.30, 0.05, 0.25, 0.70, 0.90, 0.08, 0.02, 0.50, 0.30, 0.20 ]) Sf = Factor([S, I], [0.95, 0.05, 0.2, 0.8]) Lf = Factor([L, G], [0.1, 0.9, 0.4, 0.6, 0.99, 0.01]) StudentNW = bn.BayesianNetwork([(D, Df, []), (I, If, []), (G, Gf, [D, I]), (S, Sf, [I]), (L, Lf, [G])]) cases = [(L, 1, [(I, "low"), (D, "easy")], 0.513), (I, 1, [(L, "weak")], 0.140), (I, 1, [(G, "c"), (S, "high")], 0.578), (L, 1, [(I, "low")], 0.389), (I, 1, [(G, "c")], 0.079)] for (qvar, qvalue, evidence, expect) in cases: result = StudentNW.eliminationAsk(qvar, evidence) print("qvar: %s\nevidence: %s\nexpect: %s\nresult: %s" % (qvar.name, ",".join( ["%s=%s" % (x[0].name, x[1]) for x in evidence]), expect, result.values[qvalue])) assert_almost_equal(result.values[qvalue], expect, places=3)
def kullbackLeiblerDistance(fac1, fac2, base=2): """ Calculates the Kullback-Leibler Distance between fac1 and fac2. The factors should represent probability distributions with the same variables, like P(X) and Q(X), or P(X, Y) and Q(X, Y) :param fac1: First factor in operation :param fac2: Second factor in operation :param base: Base of logarithms in the operations, defaults to 2 :returns: The Kullback-Leibler Distance """ kld = lambda f1, f2: f1 * log(f1 / f2) / log(base) return sum(Factor.factorOp(fac1, fac2, kld).values)
def factor_test(self): X = RandVar("X", [0, 1]) Y = RandVar("Y", [0, 1]) f1 = Factor(X, [0, 1]) f2 = Factor([X, Y], [0, 1, 2, 3]) assert (f1.__repr__() == "(X, [0, 1])") assert (f2.__repr__() == "([X, Y], [0, 1, 2, 3])")
def __init__(self): TestBase.__init__(self) # factors for information theory testing self.fX1 = Factor(self.X, [0.5, 0.5]) self.fX2 = Factor(self.X, [0.0, 1.0]) self.fX3 = Factor(self.X, [1.0, 0.0]) self.fXY1 = Factor([self.X, self.Y], [0.25, 0.25, 0.25, 0.25]) self.fXY2 = Factor([self.X, self.Y], [0.1, 0.2, 0.3, 0.4]) self.fXY3 = Factor([self.X, self.Y], [0.4, 0.3, 0.2, 0.1])
def rejectionSample(self, query_var, observed, samples_num): """ Implementation of the rejection sample algorithm. This algorithms estimates a distribution P(X | e), where X is a query variable and e are observations made in the network. :param query_var: Random variable of type RandVar :param observed: List of observations. Each element of the list should be a tuple, which first element is a RandVar and second element is the observed value for that variable :param samples_num: Number of samples the algorithm is going to take to calculate the estimative """ # List of counts for each value of the domain. Initialized with 0 count = {i: 0 for i in query_var.domain} # The samples_num of samples for i in range(samples_num): # Take a sample sample = self.sample() # Check if it should be rejected rejected = False for j in observed: for k in sample: # If the value of the sampled variable is different from # the value of the observed one, rejected if j[0].name == k[0].name and j[1] != k[1]: rejected = True break # If the sample was already rejected, get out of the cycle if rejected: break # If the sample is not rejected, increment the counts if not rejected: for j in sample: if j[0].name == query_var.name: count[j[1]] += 1 # Make resulting factor values = [count[i] for i in query_var.domain] return Factor([query_var], values).normalize(query_var)
def gibbsAsk(self, query_var, observed, samples_num): # Result is a list of counts for each value in the domain of the query # variable. Initialized with 0 res = {i: 0 for i in query_var.domain} # Assure the observed argument is an Event if type(observed) != Event: observed = Event(observed) # Create non evidence variable list, which are all the variables not # present in the observations non_evidence_vars = [i for i in self.network if not observed.varInEvent(i.node)] # Get markov blankets for each non evidence variable mbs = dict() for i in non_evidence_vars: mbs[i.node.name] = self.markovBlanket(i) # Make an initial sample sample = self.sample(observed) # Execute for samples_num samples for i in range(samples_num): for j in non_evidence_vars: # Get distribution P(j | mb(j)) dist = j.factor for k in mbs[j.node.name]: dist *= k.factor # Instantiate with previous sample, except for current j # variable sample.removeVar(j.node) dist = dist.instVar(sample) # Set new random value of current variable in sample rvalue = self.pickRandomValue(dist.rand_vars[0].domain, dist.values, random.random()) sample.setValue(j.node, rvalue) # Increment count res[rvalue] += 1 # Return the count list normalized values = [res[i] for i in query_var.domain] return Factor(query_var, values).normalize(query_var)
def __init__(self): TestBase.__init__(self) # factors for information theory testing self.fX1 = Factor(self.X, [0.5, 0.5]) self.fX2 = Factor(self.X, [0.0, 1.0]) self.fX3 = Factor(self.X, [1.0, 0.0]) self.fXY1 = Factor([self.X, self.Y], [0.25, 0.25, 0.25, 0.25]) self.fXY2 = Factor([self.X, self.Y], [0.1, 0.2, 0.3, 0.4]) self.fXY3 = Factor([self.X, self.Y], [0.4, 0.3, 0.2, 0.1]) self.P1 = Factor([self.X], [0.5, 0.5]) self.Q1 = Factor([self.X], [0.9, 0.1]) self.P2 = Factor([self.X, self.Y], [0.25, 0.25, 0.25, 0.25]) self.Q2 = Factor([self.X, self.Y], [0.8, 0.05, 0.05, 0.8])
def inf_theory_test_7(self): """ I(X ; Y) """ joint = Factor([self.X, self.Y], [0.8, 0.05, 0.05, 0.8]) fac1 = self.fXY1.marginal(self.X) fac2 = self.fXY1.marginal(self.Y) res = [ mutualInformation(joint, fac1, fac2), mutualInformation(joint, fac1, fac2, 10), mutualInformation(joint, fac1, fac2, math.e) ] assert_almost_equal(res[0], 2.4527, places=4) assert_almost_equal(res[1], 0.73834, places=5) assert_almost_equal(res[2], 1.7001, places=5)
def beliefProp(self): """ Belief propagation algorithm, also known as sum-product algorithm. The result of the algorithm is stored in the *marginal* attribute of every variable node which is part of the network. This implementation only works with tree networks. """ # Select any root node root_node = self.nodes[next(iter(self.nodes))] # Get messages to this node res = self.factorToVar(root_node.neighbors[0], root_node) root_node.messages[0] = res for i, neighbor in enumerate(root_node.neighbors[1:]): msg = self.factorToVar(neighbor, root_node) root_node.messages[i+1] = msg res *= msg for i in root_node.obs_factors: res *= i # Store the calculated marginal root_node.setMarginal(res) # Propagate this message to other nodes for i, neighbor in enumerate(root_node.neighbors): new_msg = Factor(root_node.var, [1, 1]) for j in range(len(root_node.neighbors)): if i != j: new_msg *= root_node.messages[j] for j in root_node.obs_factors: new_msg *= j self.progMsgVarToFactor(neighbor, root_node, new_msg)
sys.path.insert(0, path.join("..", "ProbPy")) # Import ProbPy modules from ProbPy import RandVar, Factor, Event from ProbPy import bn if __name__ == "__main__": # Variables for this example cloudy = RandVar("cloudy", ["True", "False"]) sprinkler = RandVar("sprinkler", ["True", "False"]) rain = RandVar("rain", ["True", "False"]) wet_grass = RandVar("wet_grass", ["True", "False"]) # Factors representing the conditional distributions of this network factor_cloudy = Factor(cloudy, [0.5, 0.5]) factor_sprinkler = Factor([sprinkler, cloudy], [0.1, 0.9, 0.5, 0.5]) factor_rain = Factor([rain, cloudy], [0.8, 0.2, 0.2, 0.8]) factor_wet_grass = Factor([wet_grass, rain, sprinkler], [0.99, 0.01, 0.9, 0.1, 0.9, 0.1, 0.0, 1.0]) # Actual network representation network = [(cloudy, factor_cloudy), (sprinkler, factor_sprinkler), (rain, factor_rain), (wet_grass, factor_wet_grass)] # Create a Bayesian Network BN = bn.BayesianNetwork(network) # Set one observation observed = Event(var=sprinkler, val="True")
def __init__(self): # Scalars self.scalar = 10 self.scalarf = Factor([], [10]) # Binary variables self.X = RandVar("X", ["T", "F"]) self.Y = RandVar("Y", ["T", "F"]) self.Z = RandVar("Z", ["T", "F"]) self.W = RandVar("W", ["T", "F"]) self.K = RandVar("K", ["T", "F"]) self.T = RandVar("T", ["T", "F"]) # Domains self.X_domain = list(range(1, 3)) self.Y_domain = list(range(3, 5)) self.Z_domain = list(range(5, 7)) self.XY_domain = list(range(1, 5)) self.XZ_domain = list(range(5, 9)) self.ZW_domain = list(range(9, 13)) self.XYZ_domain = list(range(1, 9)) self.XYW_domain = list(range(9, 17)) self.XKW_domain = list(range(17, 25)) self.TKW_domain = list(range(25, 33)) # Factors self.X_factor = Factor(self.X, self.X_domain) self.Y_factor = Factor(self.Y, self.Y_domain) self.Z_factor = Factor(self.Z, self.Z_domain) self.XY_factor = Factor([self.X, self.Y], self.XY_domain) self.XZ_factor = Factor([self.X, self.Z], self.XZ_domain) self.ZW_factor = Factor([self.Z, self.W], self.ZW_domain) self.XYZ_factor = Factor([self.X, self.Y, self.Z], self.XYZ_domain) self.XYW_factor = Factor([self.X, self.Y, self.W], self.XYW_domain) self.XKW_factor = Factor([self.X, self.K, self.W], self.XKW_domain) self.TKW_factor = Factor([self.T, self.K, self.W], self.TKW_domain) # Factors for normalization self.X_factor_n = Factor(self.X, [1, 2]) self.XY_factor_n = Factor([self.X, self.Y], [1, 1, 2, 2]) self.XYZ_factor_n = Factor([self.X, self.Y, self.Z], [1, 1, 2, 2, 3, 3, 4, 4]) # Distributions for expected value self.X_dist = Factor(self.X, [0.8, 0.2]) self.Y_dist = Factor(self.Y, [0.1, 0.9]) self.XY_dist = Factor([self.X, self.Y], [0.1, 0.2, 0.3, 0.4]) # Function for expected values f(X) self.x_ev = Factor(self.X, [10, 20]) self.y_ev = Factor(self.Y, [15, 25]) self.xy_ev = Factor([self.X, self.Y], [25, 35, 35, 45])
from ProbPy import RandVar, Factor, Event from ProbPy import bn if __name__ == "__main__": # These are the variables in the network. The first argument is the actual # name of the variable and the second is the domain of it burglary = RandVar("burglary", ["True", "False"]) earthq = RandVar("earthq", ["True", "False"]) alarm = RandVar("alarm", ["True", "False"]) john = RandVar("john", ["True", "False"]) mary = RandVar("mary", ["True", "False"]) # These are the distributions. First argument are the variables, second is # the values in the distribution factor_burglary = Factor([burglary], [0.001, 0.999]) factor_earthq = Factor([earthq], [0.002, 0.998]) factor_alarm = Factor([alarm, earthq, burglary], [ 0.95, 0.05, 0.94, 0.06, 0.29, 0.71, 0.001, 0.999 ]) factor_john = Factor([john, alarm], [0.90, 0.10, 0.05, 0.95]) factor_mary = Factor([mary, alarm], [0.70, 0.30, 0.01, 0.99]) # This array has the nodes of the network. Each element is a tuple. In each # tuple, the first argument is the variable of that node, the second is the # distribution. Note that the nodes were place in the list at random network = [ (earthq, factor_earthq), (alarm, factor_alarm), (john, factor_john), (burglary, factor_burglary),
# Import ProbPy modules from ProbPy import RandVar, Factor if __name__ == "__main__": """ Supposing the following example P(X | Y) P(Y) 1/P(X) = P(Y | X) """ # Random Variables X = RandVar("X", ["T", "F"]) Y = RandVar("Y", ["T", "F"]) # Prior distribution, P(Y) fy = Factor(Y, [0.2, 0.8]) # Conditional distribution, P(X | Y) fx_y = Factor([X, Y], [0.1, 0.9, 0.5, 0.5]) # Bayes theorem to get P(Y | X) fy_x = (fx_y * fy).normalize(Y) print("P(X | Y) P(Y) 1/P(X) = P(Y | X)") print(fy_x.values) # Alternative way of getting P(Y | X) without using the normalize() method fxy = fx_y * fy fx = fxy.marginal(X) fx_y = fxy / fx
class TestInfTheoryValue(TestBase): def __init__(self): TestBase.__init__(self) # factors for information theory testing self.fX1 = Factor(self.X, [0.5, 0.5]) self.fX2 = Factor(self.X, [0.0, 1.0]) self.fX3 = Factor(self.X, [1.0, 0.0]) self.fXY1 = Factor([self.X, self.Y], [0.25, 0.25, 0.25, 0.25]) self.fXY2 = Factor([self.X, self.Y], [0.1, 0.2, 0.3, 0.4]) self.fXY3 = Factor([self.X, self.Y], [0.4, 0.3, 0.2, 0.1]) self.P1 = Factor([self.X], [0.5, 0.5]) self.Q1 = Factor([self.X], [0.9, 0.1]) self.P2 = Factor([self.X, self.Y], [0.25, 0.25, 0.25, 0.25]) self.Q2 = Factor([self.X, self.Y], [0.8, 0.05, 0.05, 0.8]) def inf_theory_test_0(self): """ H(X) """ assert_almost_equal(entropy(self.fX1), 1.0, places=1) assert_almost_equal(entropy(self.fX1, 10), 0.30103, places=5) assert_almost_equal(entropy(self.fX1, math.e), 0.69315, places=5) assert_almost_equal(entropy(self.fX2), 0.0, places=1) assert_almost_equal(entropy(self.fX2, 10), 0.0, places=1) assert_almost_equal(entropy(self.fX2, math.e), 0.0, places=1) assert_almost_equal(entropy(self.fX3), 0.0, places=1) assert_almost_equal(entropy(self.fX3, 10), 0.0, places=1) assert_almost_equal(entropy(self.fX3, math.e), 0.0, places=1) def inf_theory_test_1(self): """ H(X, Y) """ assert_almost_equal(entropy(self.fXY1), 2.0, places=1) assert_almost_equal(entropy(self.fXY1, 10), 0.60206, places=5) assert_almost_equal(entropy(self.fXY1, math.e), 1.3863, places=4) assert_almost_equal(entropy(self.fXY2), 1.8464, places=4) assert_almost_equal(entropy(self.fXY2, 10), 0.55583, places=5) assert_almost_equal(entropy(self.fXY2, math.e), 1.2799, places=4) assert_almost_equal(entropy(self.fXY3), 1.8464, places=4) assert_almost_equal(entropy(self.fXY3, 10), 0.55583, places=5) assert_almost_equal(entropy(self.fXY3, math.e), 1.2799, places=4) def inf_theory_test_2(self): """ KLD(P1 | Q1) """ res = [ kullbackLeiblerDistance(self.P1, self.Q1), kullbackLeiblerDistance(self.P1, self.Q1, 10), kullbackLeiblerDistance(self.P1, self.Q1, math.e) ] assert_almost_equal(res[0], 0.73697, places=4) assert_almost_equal(res[1], 0.22185, places=4) assert_almost_equal(res[2], 0.51083, places=4) def inf_theory_test_3(self): """ KLD(P2 | Q2) """ res = [ kullbackLeiblerDistance(self.P2, self.Q2), kullbackLeiblerDistance(self.P2, self.Q2, 10), kullbackLeiblerDistance(self.P2, self.Q2, math.e) ] assert_almost_equal(res[0], 0.32193, places=4) assert_almost_equal(res[1], 0.09691, places=4) assert_almost_equal(res[2], 0.22314, places=4) def inf_theory_test_4(self): """ KLD(Q1 | P1) """ res = [ kullbackLeiblerDistance(self.Q1, self.P1), kullbackLeiblerDistance(self.Q1, self.P1, 10), kullbackLeiblerDistance(self.Q1, self.P1, math.e) ] assert_almost_equal(res[0], 0.53100, places=5) assert_almost_equal(res[1], 0.15985, places=5) assert_almost_equal(res[2], 0.36806, places=5) def inf_theory_test_5(self): """ KLD(Q2 | P2) """ res = [ kullbackLeiblerDistance(self.Q2, self.P2), kullbackLeiblerDistance(self.Q2, self.P2, 10), kullbackLeiblerDistance(self.Q2, self.P2, math.e) ] assert_almost_equal(res[0], 2.4527, places=4) assert_almost_equal(res[1], 0.73834, places=5) assert_almost_equal(res[2], 1.7001, places=4) def inf_theory_test_6(self): """ I(X ; Y) """ fac1 = self.fXY1.marginal(self.X) fac2 = self.fXY1.marginal(self.Y) res = [ mutualInformation(self.fXY1, fac1, fac2), mutualInformation(self.fXY1, fac1, fac2, 10), mutualInformation(self.fXY1, fac1, fac2, math.e) ] assert_almost_equal(res[0], 0.0, places=1) assert_almost_equal(res[1], 0.0, places=1) assert_almost_equal(res[2], 0.0, places=1) def inf_theory_test_7(self): """ I(X ; Y) """ joint = Factor([self.X, self.Y], [0.8, 0.05, 0.05, 0.8]) fac1 = self.fXY1.marginal(self.X) fac2 = self.fXY1.marginal(self.Y) res = [ mutualInformation(joint, fac1, fac2), mutualInformation(joint, fac1, fac2, 10), mutualInformation(joint, fac1, fac2, math.e) ] assert_almost_equal(res[0], 2.4527, places=4) assert_almost_equal(res[1], 0.73834, places=5) assert_almost_equal(res[2], 1.7001, places=5)
class TestInfTheoryValue(TestBase): def __init__(self): TestBase.__init__(self) # factors for information theory testing self.fX1 = Factor(self.X, [0.5, 0.5]) self.fX2 = Factor(self.X, [0.0, 1.0]) self.fX3 = Factor(self.X, [1.0, 0.0]) self.fXY1 = Factor([self.X, self.Y], [0.25, 0.25, 0.25, 0.25]) self.fXY2 = Factor([self.X, self.Y], [0.1, 0.2, 0.3, 0.4]) self.fXY3 = Factor([self.X, self.Y], [0.4, 0.3, 0.2, 0.1]) self.P1 = Factor([self.X], [0.5, 0.5]) self.Q1 = Factor([self.X], [0.9, 0.1]) self.P2 = Factor([self.X, self.Y], [0.25, 0.25, 0.25, 0.25]) self.Q2 = Factor([self.X, self.Y], [0.8, 0.05, 0.05, 0.8]) def inf_theory_test_0(self): """ H(X) """ assert_almost_equal(entropy(self.fX1), 1.0, places=1) assert_almost_equal(entropy(self.fX1, 10), 0.30103, places=5) assert_almost_equal(entropy(self.fX1, math.e), 0.69315, places=5) assert_almost_equal(entropy(self.fX2), 0.0, places=1) assert_almost_equal(entropy(self.fX2, 10), 0.0, places=1) assert_almost_equal(entropy(self.fX2, math.e), 0.0, places=1) assert_almost_equal(entropy(self.fX3), 0.0, places=1) assert_almost_equal(entropy(self.fX3, 10), 0.0, places=1) assert_almost_equal(entropy(self.fX3, math.e), 0.0, places=1) def inf_theory_test_1(self): """ H(X, Y) """ assert_almost_equal(entropy(self.fXY1), 2.0, places=1) assert_almost_equal(entropy(self.fXY1, 10), 0.60206, places=5) assert_almost_equal(entropy(self.fXY1, math.e), 1.3863, places=4) assert_almost_equal(entropy(self.fXY2), 1.8464, places=4) assert_almost_equal(entropy(self.fXY2, 10), 0.55583, places=5) assert_almost_equal(entropy(self.fXY2, math.e), 1.2799, places=4) assert_almost_equal(entropy(self.fXY3), 1.8464, places=4) assert_almost_equal(entropy(self.fXY3, 10), 0.55583, places=5) assert_almost_equal(entropy(self.fXY3, math.e), 1.2799, places=4) def inf_theory_test_2(self): """ KLD(P1 | Q1) """ res = [kullbackLeiblerDistance(self.P1, self.Q1), kullbackLeiblerDistance(self.P1, self.Q1, 10), kullbackLeiblerDistance(self.P1, self.Q1, math.e)] assert_almost_equal(res[0], 0.73697, places=4) assert_almost_equal(res[1], 0.22185, places=4) assert_almost_equal(res[2], 0.51083, places=4) def inf_theory_test_3(self): """ KLD(P2 | Q2) """ res = [kullbackLeiblerDistance(self.P2, self.Q2), kullbackLeiblerDistance(self.P2, self.Q2, 10), kullbackLeiblerDistance(self.P2, self.Q2, math.e)] assert_almost_equal(res[0], 0.32193, places=4) assert_almost_equal(res[1], 0.09691, places=4) assert_almost_equal(res[2], 0.22314, places=4) def inf_theory_test_4(self): """ KLD(Q1 | P1) """ res = [kullbackLeiblerDistance(self.Q1, self.P1), kullbackLeiblerDistance(self.Q1, self.P1, 10), kullbackLeiblerDistance(self.Q1, self.P1, math.e)] assert_almost_equal(res[0], 0.53100, places=5) assert_almost_equal(res[1], 0.15985, places=5) assert_almost_equal(res[2], 0.36806, places=5) def inf_theory_test_5(self): """ KLD(Q2 | P2) """ res = [kullbackLeiblerDistance(self.Q2, self.P2), kullbackLeiblerDistance(self.Q2, self.P2, 10), kullbackLeiblerDistance(self.Q2, self.P2, math.e)] assert_almost_equal(res[0], 2.4527, places=4) assert_almost_equal(res[1], 0.73834, places=5) assert_almost_equal(res[2], 1.7001, places=4) def inf_theory_test_6(self): """ I(X ; Y) """ fac1 = self.fXY1.marginal(self.X) fac2 = self.fXY1.marginal(self.Y) res = [mutualInformation(self.fXY1, fac1, fac2), mutualInformation(self.fXY1, fac1, fac2, 10), mutualInformation(self.fXY1, fac1, fac2, math.e)] assert_almost_equal(res[0], 0.0, places=1) assert_almost_equal(res[1], 0.0, places=1) assert_almost_equal(res[2], 0.0, places=1) def inf_theory_test_7(self): """ I(X ; Y) """ joint = Factor([self.X, self.Y], [0.8, 0.05, 0.05, 0.8]) fac1 = self.fXY1.marginal(self.X) fac2 = self.fXY1.marginal(self.Y) res = [mutualInformation(joint, fac1, fac2), mutualInformation(joint, fac1, fac2, 10), mutualInformation(joint, fac1, fac2, math.e)] assert_almost_equal(res[0], 2.4527, places=4) assert_almost_equal(res[1], 0.73834, places=5) assert_almost_equal(res[2], 1.7001, places=5)