Ejemplo n.º 1
0
def test_multiply_dimensions():
    c = FactorOperations.multiply(f['a'], f['b'])
    assert c.variables == [v[1], v[2]]
    assert c.cards == [2, 2]
    
    c = FactorOperations.multiply(f['x'], f['y'])
    assert c.variables == [v[2], v[3], v[4]]
    assert c.cards == [2, 2, 3]
Ejemplo n.º 2
0
def build_joint_cpd():
    a = None
    for k in GN.keys():
        b = FactorOperations.multiply(GN[k]['factor_geno'], GN[k]['factor_pheno'])
        if a==None:
            a = b
        else:
            a = FactorOperations.multiply(a, b)
    return a
Ejemplo n.º 3
0
    def mssg(self, from_v, to_w, isMax=False):
        # collect all mssg arriving at v
        mess = []
        neighbors = self.adj[from_v]
        for n in neighbors:
            if n!=to_w:
                pos = self.adj[n].index(from_v)
                msg = self.delta[n][pos]
                mess.append(msg)

        # take the the initial Psi (and log if needed)
        d = copy.copy(self.factors[from_v])
        if isMax==True:
            d.values = np.log(d.values)

        # multiply/sum by incoming messages
        for ms in mess:
            if isMax==True:
                d = FactorOperations.sum(d, ms, False)
            else:
                d = FactorOperations.multiply(d, ms, True)

        # marginalized to setsep vars
        for n in d.variables:
            if n not in (self.box[from_v] & self.box[to_w]):
                if isMax==True:
                    d = FactorOperations.max_marginalize(d, n)
                else:
                    d = FactorOperations.marginalize(d, n)
        return d
Ejemplo n.º 4
0
def test_complete_2():
    v1 = Rvar.Rvar(1, 2)
    v2 = Rvar.Rvar(2, 2)
    v3 = Rvar.Rvar(3, 2)
    v4 = Rvar.Rvar(4, 3)
    v5 = Rvar.Rvar(5, 2)
        
    d = Factor.Factor([v1])
    d.fill_values([0.6, 0.4])
    i = Factor.Factor([v2])
    i.fill_values([0.7, 0.3]);
    s = Factor.Factor([v3, v2])
    s.fill_values([0.95, 0.05, 0.2, 0.8]);
    g = Factor.Factor([v4, v1, v2])
    g.fill_values([0.3, 0.4, 0.3, 0.05, 0.25, 0.7, 0.9, 0.08, 0.02, 0.5, 0.3, 0.2]);
    l = Factor.Factor([v5, v4])
    l.fill_values([0.1, 0.9, 0.4, 0.6, 0.99, 0.01]);
    
    s = FactorOperations.observe(s, {v3:1}) # we observe high SAT
    
    factors = [i, s, g, l]
    a = d
    for f in factors:
        a = FactorOperations.multiply(a, f)
        print a.variables, a.values.size
    
    rvars = [v1, v3, v4, v5]
    for v in rvars:
        a = FactorOperations.marginalize(a, v)
        print a.variables, a.values.size
    
    assert np.allclose(a.values, [0.12727273, 0.87272727])
Ejemplo n.º 5
0
def test_multiply_values2():
    v_1 = Rvar.Rvar(1, 3)
    v_2 = Rvar.Rvar(2, 2)
    v_3 = Rvar.Rvar(3, 2)
    
    X = Factor.Factor([v_2, v_1])
    X.fill_values([0.5, 0.8, 0.1, 0., 0.3, 0.9])
    Y = Factor.Factor([v_3, v_2])
    Y.fill_values([0.5, 0.7, 0.1, 0.2])

    Z = FactorOperations.multiply(X, Y, False)
    sol = Factor.Factor([v_1, v_2, v_3])
    sol.fill_values([0.25, 0.05, 0.15, 0.08, 0, 0.09, 0.35, 0.07, 0.21, 0.16, 0, 0.18])
    assert np.allclose(Z.values, sol.values, atol=epsilon)
Ejemplo n.º 6
0
    def eliminateVar(self, F, C, z):
        # separate factors into two lists, those that use z (F_Cluster) and the rest
        F_Cluster, F_Rest, Cluster_vars = [], [], []
        for f in F.factors:
            if z in f.variables:
                F_Cluster += [f]
                Cluster_vars += f.variables
            else:
                F_Rest += [f]
        
        if F_Cluster!=[]:
            Cluster_vars = tuple(sorted(set(Cluster_vars)))

            # when computing tau of new node, check if it uses other nodes' taus
            rows,cols = C['edges'].shape
            C['edges'] = np.vstack([C['edges'], np.zeros((1,cols))])
            C['edges'] = np.hstack([C['edges'], np.zeros((rows+1,1))])
            pos = np.zeros(cols+1)
            for n,node in enumerate(C['nodes']):
                if node['tau'] in F_Cluster:
                    pos[n]=1
            # create a new array of connecting node edges based on taus in common
            C['edges'][-1,:] = pos
            C['edges'][:,-1] = pos
            
            # multiply the factors in Cluster... (lambda) ...and marginalize by z (tau)
            tau = F_Cluster.pop(0)
            for f in F_Cluster:
                tau = FactorOperations.multiply(tau, f)
            if tau.variables != [z]:
                tau = FactorOperations.marginalize(tau, z)
            
            # add to unused factor list the resulting tau ==> new factor list with var eliminated
            F_Rest += [tau]
            
            # update the edges (connect all vars inside new cluster, & disconnect the eliminated variable)
            for vi in Cluster_vars:
                for vj in Cluster_vars:
                    F.edges[F.allVars.index(vi), F.allVars.index(vj)] = 1
            F.edges[F.allVars.index(z),:] = 0
            F.edges[:, F.allVars.index(z)] = 0
            
            C['nodes'] += [{'vars':Cluster_vars, 'tau':tau}]
            
            F.factors = F_Rest
        return [F, C]
Ejemplo n.º 7
0
 def initializePotentials(self, listOfFactors):
     # create factors initialized to ones
     self.factors = [None]*self.V
     for i in range(self.V):
         fu = Factor.Factor(sorted(list(self.box[i])))
         fu.values = np.ones(fu.cards)
         self.factors[i] = fu
     
     # ... and now brutishly (FIFO) we assign the factors
     for fu in listOfFactors:
         notUsed = True
         for i,n in enumerate(self.box):
             if n.issuperset(set(fu.variables)):
                 self.factors[i] = FactorOperations.multiply(self.factors[i], fu, False)
                 notUsed = False
                 break  # to use only once
         if notUsed:
             raise NameError('factor not used in any clique!', fu.variables)
     pass
Ejemplo n.º 8
0
 def calibrate(self, isMax=False):
     self.beta = [None]*self.V
     # compute messages
     for e in self.computePath():
         from_v, to_w = e
         pos_to = self.adj[from_v].index(to_w)
         self.delta[from_v][pos_to] = self.mssg(from_v, to_w, isMax)
     
     # compute the beliefs
     for v in range(self.V):
         belief = copy.copy(self.factors[v])
         if isMax==True:
             belief.values = np.log(belief.values)
         for w in self.adj[v]:
             pos = self.adj[w].index(v)
             delta = self.delta[w][pos]
             if isMax==True:
                 belief = FactorOperations.sum(belief, delta, False)
             else:
                 belief = FactorOperations.multiply(belief, delta, False)
         self.beta[v] = belief
Ejemplo n.º 9
0
 def eliminateVar(self, F, z):
     # separate factors into two lists, those that use z (F_Cluster) and the rest
     F_Cluster, F_Rest, Cluster_vars = [], [], []
     for f in F.factors:
         if z in f.variables:
             F_Cluster += [f]
             Cluster_vars += f.variables
         else:
             F_Rest += [f]
     
     if F_Cluster!=[]:
         # add a node to clique tree with the variables involved
         position = self.V
         self.V += 1
         self.box.insert(position, set(Cluster_vars))
         self.adj.insert(position, [])
         
         # when computing tau of new node, check if it uses other nodes' taus and connect
         for i in range(position):
             if self.tau[i] in F_Cluster:
                 self.addEdge(i, position)
         
         # multiply the factors in Cluster... (lambda) ...and marginalize by z (tau)
         tau = F_Cluster.pop(0)
         for f in F_Cluster:
             tau = FactorOperations.multiply(tau, f, False)
         if tau.variables != [z]:
             tau = FactorOperations.marginalize(tau, z)
         self.tau.insert(position, tau)
         
         # update the edges of F (connect all vars inside new factor, & disconnect the eliminated variable)
         F.connectAll([F.index_var(v) for v in self.box[position]])
         F.adj[F.index_var(z)] = []
         
         # add to unused factor list the resulting tau ==> new factor list with var eliminated
         F_Rest += [tau]            
         F.factors = F_Rest
     return F
Ejemplo n.º 10
0
def test_complete_1():
    v1 = Rvar.Rvar(1, 3)
    v2 = Rvar.Rvar(2, 2)
    v3 = Rvar.Rvar(3, 2)
    v4 = Rvar.Rvar(4, 2)
    v5 = Rvar.Rvar(5, 3)
    v6 = Rvar.Rvar(6, 3)
    v7 = Rvar.Rvar(7, 2)
    v8 = Rvar.Rvar(8, 3)
        
    f1 = Factor.Factor([v1])
    f1.fill_values([1.0/3.0, 1.0/3.0, 1.0/3.0])
    f2 = Factor.Factor([v8, v2])
    f2.fill_values([0.9, 0.1, 0.5, 0.5, 0.1, 0.9])
    f3 = Factor.Factor([v3, v4, v7, v2])
    f3.fill_values([0.9, 0.1, 0.8, 0.2, 0.7, 0.3, 0.6, 0.4, 0.4, 0.6, 0.3, 0.7, 0.2, 0.8, 0.1, 0.9])
    f4 = Factor.Factor([v4])
    f4.fill_values([0.5, 0.5])
    f5 = Factor.Factor([v5, v6])
    f5.fill_values([0.75, 0.2, 0.05, 0.2, 0.6, 0.2, 0.05, 0.2, 0.75])
    f6 = Factor.Factor([v6])
    f6.fill_values([0.3333, 0.3333, 0.3333])
    f7 = Factor.Factor([v7, v5, v6])
    f7.fill_values([0.9, 0.1, 0.8, 0.2, 0.7, 0.3, 0.6, 0.4, 0.5, 0.5, 0.4, 0.6, 0.3, 0.7, 0.2, 0.8, 0.1, 0.9])
    f8 = Factor.Factor([v8, v4, v1])
    f8.fill_values([0.1, 0.3, 0.6, 0.05, 0.2,0.75, 0.2, 0.5, 0.3, 0.1, 0.35, 0.55, 0.8, 0.15, 0.05, 0.2, 0.6, 0.2])

    factors = [f2, f3, f4, f5, f6, f7, f8]
    a = f1
    for f in factors:
        a = FactorOperations.multiply(a, f)
    rvars = [v2,v3,v4,v5,v6,v7,v8]

    for v in rvars:
        a = FactorOperations.marginalize(a, v)
    
    assert np.allclose(a.values, [0.37414966, 0.30272109, 0.32312925])
Ejemplo n.º 11
0
    def __init__ (self, listOfFactors):  
        F = FactorGraph(listOfFactors)
        
        # create nodes iteratively through var elimination
        C = {'nodes':[], 'edges':np.zeros((0,0))}
        considered_cliques = 0
        while considered_cliques < len(F.allVars):
            z = F.firstMinNeighborVar()
            [F,C] = self.eliminateVar(F, C, z)
            considered_cliques += 1
        
        self.nodes = [set(n['vars']) for n in C['nodes']]
        self.edges = C['edges']

        # prune tree
        keepPruning = True
        while keepPruning:
            keepPruning = self.pruneNode()

        # initialize potentials first to all ones
        self.factors = []
        for i in range(len(self.nodes)):
            fu = Factor.Factor(sorted(list(self.nodes[i])))
            #fu.fill_values(np.ones(np.product(fu.cards)))
            fu.values = np.ones(fu.cards)
            self.factors += [fu]
        # ... and now brutishly (FIFO) we assign the factors
        for fu in listOfFactors:
            notUsed = True
            for i,n in enumerate(self.nodes):
                if set(fu.variables) <= n:
                    self.factors[i] = FactorOperations.multiply(self.factors[i], fu, False)
                    notUsed = False
                    break
            if notUsed:
                raise NameError('factor not used in any clique!', fu.variables)
Ejemplo n.º 12
0
def test_multiply_values():
    c = FactorOperations.multiply(f['a'], f['b'])
    sol = Factor.Factor(c.variables)
    sol.fill_values([0.0649, 0.1958, 0.0451, 0.6942])
    assert np.allclose(c.values, sol.values, atol=epsilon)