def create_difficult_pattern(size):
    '''The eq ids go from 0..size-1, the column ids from size..2*size-1.
    A pathological pattern, resulting in many ties:
    | x x         | 
    |     x x     |
    |         x x |
    | x x x x     |
    |     x x x x |
    | x x     x x |  '''
    assert size % 2 == 0, size
    rows, cols = list(irange(size)), list(irange(size, 2 * size))
    g = Graph()
    half_size = size // 2
    # build upper half
    for i in irange(half_size):
        g.add_edges_from(((i, size + 2 * i), (i, size + 2 * i + 1)))
    # build lower half
    for i in irange(half_size, size):
        k = 2 * (i - half_size)
        vrs = [size + v % size for v in irange(k, k + 4)]
        g.add_edges_from(izip(repeat(i), vrs))
    assert is_bipartite_node_set(g, rows)
    assert is_bipartite_node_set(g, cols)
    #to_pdf(g, rows, cols, '', str(size))
    #plot_dm_decomp(g, size)
    return g
Exemple #2
0
    def check_model(self):
        """
        Check the model for various errors. This method checks for the following
        errors. In the same time it also updates the cardinalities of all the
        random variables.

        * Check whether bipartite property of factor graph is still maintained
        or not.
        * Check whether factors are associated for all the random variables or not.
        * Check if factors are defined for each factor node or not.
        * Check if cardinality of random variable remains same across all the
        factors.
        """
        variable_nodes = set([x for factor in self.factors for x in factor.scope()])
        factor_nodes = set(self.nodes()) - variable_nodes

        if not all(isinstance(factor_node, Factor) for factor_node in factor_nodes):
            raise ValueError('Factors not associated for all the random variables')

        if (not (bipartite.is_bipartite(self)) or 
            not (bipartite.is_bipartite_node_set(self, variable_nodes) or
                 bipartite.is_bipartite_node_set(self, variable_nodes))):
            raise ValueError('Edges can only be between variables and factors')

        if len(factor_nodes) != len(self.factors):
            raise ValueError('Factors not associated with all the factor nodes.')

        cardinalities = self.get_cardinality()
        for factor in self.factors:
            for variable, cardinality in zip(factor.scope(), factor.cardinality):
                if (cardinalities[variable] != cardinality):
                    raise ValueError('Cardinality of variable {var} not matching among factors'.format(var=variable))

        return True
def Dulmage_Mendelsohn(g, eqs):
    '''The input graph g is assumed to be a bipartite graph with no isolated 
    nodes. Returns the diagonal blocks as a list of (equations, variables).'''
    assert_all_in_graph(g, eqs)
    assert_no_isolates(g)
    assert eqs, 'At least one equation is expected'
    assert is_bipartite_node_set(g, eqs)
    # Maximum matching
    mate = nx.max_weight_matching(g, maxcardinality=True)
    matches = sorted((k, mate[k]) for k in mate if k in eqs)
    log('Matches:')
    for eq, var in matches:
        log(eq, var)
    # Direct the edges of g according to the matching
    bipart = to_digraph(g, matches)
    plot(bipart)
    # Find the strongly connected components (SCCs) of the equations
    eq_sccs = nx.condensation(projected_graph(bipart, eqs))
    plot(eq_sccs)
    # Q: With proper implementation, shouldn't the SCCs be already top. sorted?
    precedence_order = nx.topological_sort(eq_sccs)
    # Collect the diagonal blocks as a list of (equations, variables)
    diagonal_blocks = []
    seen = set()
    for scc in precedence_order:
        equations = eq_sccs.node[scc]['members']
        variables = {
            n
            for eq in equations for n in g.edge[eq] if n not in seen
        }
        seen.update(variables)
        diagonal_blocks.append((equations, list(variables)))
    return diagonal_blocks
Exemple #4
0
    def check_model(self):
        """
        Check the model for various errors. This method checks for the following
        errors. In the same time it also updates the cardinalities of all the
        random variables.

        * Check whether bipartite property of factor graph is still maintained
        or not. (This check is not done explicitly here as it done in add_edges() method)
        * Check whether factors are associated for all the random variables or not.
        * Check if factors are defined for each factor node of not.
        * Check if cardinality of random variable remains same across all the
        factors.
        """
        variable_nodes = set([x for factor in self.factors for x in factor.scope()])
        if not bipartite.is_bipartite_node_set(self, variable_nodes):
            raise ValueError('Factors not associated for all the random'
                             'variables.')

        factor_nodes = set(self.nodes()) - set(variable_nodes)
        if len(factor_nodes) != len(self.factors):
            raise ValueError('Factors not associated with all the factor nodes.')

        for factor in self.factors:
            for variable, cardinality in zip(factor.scope(), factor.cardinality):
                if ((self.cardinalities[variable]) and
                        (self.cardinalities[variable] != cardinality)):
                    raise CardinalityError(
                        'Cardinality of variable %s not matching among factors' % variable)
                else:
                    self.cardinalities[variable] = cardinality

        return True
Exemple #5
0
def to_bipartite_from_test_string(mat_str):
    # Unaware of the optional opt in the tuple (dm_decomp does not have opt)
    rows = mat_str[0].split()
    cols_rowwise = [line.split() for line in mat_str[1].splitlines()]
    # check rows for typos
    eqs = set(rows)
    assert len(eqs) == len(rows), (sorted(eqs), sorted(rows))
    assert len(rows) == len(cols_rowwise)
    # check cols for typos
    all_cols = set(chain.from_iterable(cols for cols in cols_rowwise))
    both_row_and_col = sorted(eqs & all_cols)
    assert not both_row_and_col, both_row_and_col
    # check cols for duplicates
    for r, cols in izip(rows, cols_rowwise):
        dups = duplicates(cols)
        assert not dups, 'Duplicate column IDs {} in row {}'.format(dups, r)
    #print(rows)
    #print(cols_rowwise)
    g = nx.Graph()
    g.add_nodes_from(rows)
    g.add_nodes_from(all_cols)
    g.add_edges_from(
        (r, c) for r, cols in izip(rows, cols_rowwise) for c in cols)
    assert is_bipartite_node_set(g, eqs)
    return g, eqs
Exemple #6
0
def info_on_bipartite_graph(g, eqs, forbidden, log=print):
    log()
    log('Unordered equations (bipartite, no blocks)')
    log('Equations:', len(eqs))
    log('Variables:', len(g) - len(eqs))
    log('Non-zeros:', g.number_of_edges())
    log('Forbidden:', len(forbidden))
    assert bipartite.is_bipartite_node_set(g, eqs)
Exemple #7
0
def to_bipartite(rows, cols_rowwise):
    'Returns: (g, eqs). Assumes disjoint row and column identifier sets.'
    edge_list = ((r, c) for r, cols in izip(rows, cols_rowwise) for c in cols)
    g = Graph(edge_list)
    g.add_nodes_from(rows)  # Empty rows are allowed (but not empty columns)
    eqs = set(rows)
    assert is_bipartite_node_set(g, eqs)
    return g, eqs
def plot_dm_decomp(g, size):
    rows, cols = [], []
    for u, v in g.edges_iter(irange(size)):
        rows.append(u)
        cols.append(v - size)
    values = [1] * len(rows)
    shape = (size, size)
    g_dup, eqs, vrs = coo_matrix_to_bipartite(rows, cols, values, shape)
    assert is_bipartite_node_set(g_dup, eqs)
    assert is_bipartite_node_set(g_dup, vrs)
    from dm_decomp import blt_with_tearing
    msg = 'Size: {}'.format(size)
    blt_with_tearing(rows,
                     cols,
                     values,
                     shape, [size - 1], [0],
                     show=True,
                     name=msg)
def info_on_total_order_dag(dag, eqs, forbidden, tears):
    print()
    print('Ordered DAG (bipartite, no blocks)')
    print('Equations:', len(eqs))
    print('Variables:', len(dag) - len(eqs))
    print('Non-zeros:', dag.number_of_edges())
    print('Forbidden:', len(forbidden))
    print('Tears:', len(tears))
    print('Tear variables:', tears)
    assert bipartite.is_bipartite_node_set(dag.to_undirected(), eqs)
    assert nx.is_directed_acyclic_graph(dag)
Exemple #10
0
 def test_is_bipartite_node_set(self):
     G=nx.path_graph(4)
     assert_true(bipartite.is_bipartite_node_set(G,[0,2]))
     assert_true(bipartite.is_bipartite_node_set(G,[1,3]))
     assert_false(bipartite.is_bipartite_node_set(G,[1,2]))
     G.add_path([10,20])
     assert_true(bipartite.is_bipartite_node_set(G,[0,2,10]))
     assert_true(bipartite.is_bipartite_node_set(G,[0,2,20]))
     assert_true(bipartite.is_bipartite_node_set(G,[1,3,10]))
     assert_true(bipartite.is_bipartite_node_set(G,[1,3,20]))
Exemple #11
0
 def test_is_bipartite_node_set(self):
     G = nx.path_graph(4)
     assert_true(bipartite.is_bipartite_node_set(G, [0, 2]))
     assert_true(bipartite.is_bipartite_node_set(G, [1, 3]))
     assert_false(bipartite.is_bipartite_node_set(G, [1, 2]))
     G.add_edge(10, 20)
     assert_true(bipartite.is_bipartite_node_set(G, [0, 2, 10]))
     assert_true(bipartite.is_bipartite_node_set(G, [0, 2, 20]))
     assert_true(bipartite.is_bipartite_node_set(G, [1, 3, 10]))
     assert_true(bipartite.is_bipartite_node_set(G, [1, 3, 20]))
Exemple #12
0
def to_bipartite_w_forbidden(rows, cols_rowwise, vals_rowwise):
    '''Returns: (g, eqs, forbidden). Assumes disjoint row and column 
    identifier sets.'''
    g, forbidden = Graph(), set()
    g.add_nodes_from(rows)  # Empty rows are allowed (but not empty columns)
    for r, cols, vals in izip(rows, cols_rowwise, vals_rowwise):
        for c, v in izip(cols, vals):
            g.add_edge(r, c)
            if v > 1:
                forbidden.add((r, c))
    assert is_bipartite_node_set(g, rows)
    return g, set(rows), forbidden
def create_bipartite_graph():
    B = nx.Graph()
    B.add_nodes_from(['A', 'B', 'C', 'D', 'E'],
                     bipartite=0)  # label one set of nodes 0
    B.add_nodes_from([1, 2, 3, 4], bipartite=1)  # label other set of nodes 1
    B.add_edges_from([('A', 1), ('B', 1), ('C', 1), ('D', 2), ('E', 3),
                      ('E', 4)])  # adding edges
    # check if a graph is bipartite!!!
    print(bipartite.is_bipartite(B))
    # let's change something
    B.add_edge('A', 'B')
    print(bipartite.is_bipartite(B))
    B.remove_edge('A', 'B')
    # check if a set of nodes is part of bipartition -
    X = {1, 2, 3, 4}
    print(bipartite.is_bipartite_node_set(B, X))
    return B
Exemple #14
0
def to_bipart_w_weights(cols_rowwise, vals_rowwise):
    '''Returns the tuple of: g, eqs, mapping (a list) to undo the row 
    permutation by weight, and the row weights in the same order as in the 
    input. This function does not receive the row identifiers but makes up
    new ones: 0, 1, ..., n_rows-1.'''
    n_rows = len(cols_rowwise)
    rows = list(irange(n_rows))
    row_weights = [sum(vals, 0.0) for vals in vals_rowwise]
    row_pos = argsort(row_weights)
    #print('Row weights: ', row_weights)
    #print('Row position:', row_pos)
    g = Graph()
    g.add_nodes_from(rows)  # Empty rows are allowed (but not empty columns)
    # Apply row permutation row_pos
    edges = ((i, c) for i, r in enumerate(row_pos) for c in cols_rowwise[r])
    g.add_edges_from(edges)
    assert is_bipartite_node_set(g, rows)  # Same ID for both a col and a row?
    return g, set(rows), row_pos, row_weights
def digraph_as_rectangular_bipartite(dig):
    nodeid = count()
    eq_id = {n: next(nodeid) for n in sorted(dig)}
    edgeid = count()
    var_id = {e: 'x%d' % next(edgeid) for e in sorted(dig.edges_iter())}
    # Build the bipartite graph: edges of dig become the var node set, and
    # each var is connected to its equation(s).
    g = Graph(name=dig.graph['name'])
    for u, v in dig.edges_iter():
        eq1 = eq_id[u]
        eq2 = eq_id[v]
        var = var_id[(u, v)]
        assert not g.has_edge(eq1, var), (eq1, var)
        assert not g.has_edge(eq2, var), (eq2, var)
        g.add_edge(eq1, var)
        g.add_edge(eq2, var)
    eqs = set(six.itervalues(eq_id))
    assert is_connected(g)
    assert is_bipartite_node_set(g, eqs)
    set_lower_bound(g, eqs)
    return g, eqs
def create_block_pattern(n_blocks):
    '''The eq ids go from 0..size-1, the column ids from size..2*size-1.
    A pathological pattern, resulting in many ties:
    | x x x         | 
    | x x x         |
    | x x x x x     |
    |     x x x     |
    |     x x x x x |
    |         x x x | 
    |         x x x | '''
    size = 2 * n_blocks + 1
    g = Graph()
    g.add_nodes_from(irange(2 * size))
    for i in irange(0, size - 2, 2):
        eqs = [i, i + 1, i + 2]
        j = i + size
        vrs = [j, j + 1, j + 2]
        g.add_edges_from(product(eqs, vrs))
    #print('Nodes:', g.nodes())
    #print('Edges:', sorted(g.edges()))
    assert is_bipartite_node_set(g, set(irange(size)))
    return g, size
Exemple #17
0
def test_weighted_bipart(n_eqs, n_vars, seed):
    log('---------------------------------------------------------------------')
    bip = raw_rnd_bipartite(n_eqs, n_vars, seed)
    assert is_bipartite_node_set(bip, range(n_eqs))
    #
    rng = Random(seed)
    cols_rowwise = [ list(bip[i]) for i in range(n_eqs) ]
    vals_rowwise = [ rnd_weights(rng, len(cols)) for cols in cols_rowwise ]
    row_weights  = [ sum(vals, 0.0) for vals in vals_rowwise ]
    #
    g, eqs, mapping, _ = to_bipart_w_weights(cols_rowwise, vals_rowwise)
    rowp, colp, _, sinks, row_matches, _ = to_hessenberg_form(g, eqs)
    #
    rowp  = [ mapping[r] for r in rowp ]
    sinks = [ mapping[r] for r in sinks ]
    row_matches = [ mapping[r] for r in row_matches ]
    #
    log('bip rowp:', rowp)
    log('eqs =', n_eqs, ' vars =', n_vars, ' edges =', bip.number_of_edges())
    #
    check_nonincreasing_envelope(bip, rowp, colp)
    check_nondecreasing_row_weights(bip, rowp, colp, row_weights)
    log('---------------------------------------------------------------------')
Exemple #18
0
    def check_model(self):
        """
        Check the model for various errors. This method checks for the following
        errors. In the same time it also updates the cardinalities of all the
        random variables.

        * Check whether bipartite property of factor graph is still maintained
        or not. (This check is not done explicitly here as it done in add_edges() method)
        * Check whether factors are associated for all the random variables or not.
        * Check if factors are defined for each factor node of not.
        * Check if cardinality of random variable remains same across all the
        factors.
        """
        variable_nodes = set(
            [x for factor in self.factors for x in factor.scope()])
        if not bipartite.is_bipartite_node_set(self, variable_nodes):
            raise ValueError('Factors not associated for all the random'
                             'variables.')

        factor_nodes = set(self.nodes()) - set(variable_nodes)
        if len(factor_nodes) != len(self.factors):
            raise ValueError(
                'Factors not associated with all the factor nodes.')

        for factor in self.factors:
            for variable, cardinality in zip(factor.scope(),
                                             factor.cardinality):
                if ((self.cardinalities[variable])
                        and (self.cardinalities[variable] != cardinality)):
                    raise CardinalityError(
                        'Cardinality of variable %s not matching among factors'
                        % variable)
                else:
                    self.cardinalities[variable] = cardinality

        return True
    else:
        d['bipartite']=0

top_nodes = set(n for n,d in G.nodes(data=True) if d['bipartite']==0)
bottom_nodes = set(G) - top_nodes

def mymean(degreeiter):
    Sum = 0.0
    count = 0 
    for n,d in degreeiter:
        Sum += d
        count += 1
    return Sum / count


print "is bottom_nodes a bipartite set?",bipartite.is_bipartite_node_set(G, bottom_nodes) 	
print "is top_nodesa  bipartite set?",bipartite.is_bipartite_node_set(G, top_nodes) 	

print len(bottom_nodes)," bottom nodes",len(top_nodes)," top nodes"

print "Average subreddits moderated per moderator: ",mymean(G.degree_iter(bottom_nodes))
print "Average moderators per subreddit: ",mymean(G.degree_iter(top_nodes))
if export:
    nx.write_gexf(G,"C:\\Users\\Theseus\\Documents\\moderatorproject\\untouched.gexf")
    print "gexf exported"

pg1 = bipartite.projected_graph(G, bottom_nodes)
print "Unweighted moderator to moderator projection made"
print "Average unweighted degree: ",mymean(pg1.degree_iter())
if export:
    nx.write_gexf(pg1,"C:\\Users\\Theseus\\Documents\\moderatorproject\\bottoms.gexf")
Exemple #20
0
B = nx.Graph()
B.add_nodes_from(["A", "B", "C", "D", "E"], bipartite=0)
B.add_nodes_from([1, 2, 3, 4], bipartite=1)
B.add_edges_from([("A", 1), ("B", 1), ("C", 1), ("C", 3), ("D", 2), ("E", 3)])

from networkx.algorithms import bipartite

bipartite.is_bipartite(B)  # check if B is bipartite
B.add_edge("A", "B")  # break the rule
bipartite.is_bipartite(B)

B.remove_edge("A", "B")  # remove edge

# check set of nodes is bipartite
X = set([1, 2, 3, 4])
bipartite.is_bipartite_node_set(B, X)

X = set(["A", "B", "C", "D", "E"])
bipartite.is_bipartite_node_set(B, X)

bipartite.sets(B)

# Projected Graphs
B = nx.Graph()
B.add_edges_from([("A", 1), ("B", 1), ("C", 1), ("D", 1), ("H", 1), ("B", 2),
                  ("C", 2), ("D", 2), ("E", 2), ("G", 2), ("E", 3), ("F", 3),
                  ("H", 3), ("J", 3), ("E", 4), ("I", 4), ("J", 4)])
X = set(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"])
P = bipartite.projected_graph(B, X)
nx.draw(P)
Exemple #21
0
from networkx.algorithms import bipartite

B = nx.Graph() #no separate class for bipartite graphs
B.add_nodes_from (["A","B", "C", "D"], bipartite = 0) #LABEL ONE SET OF NODES ()
B.add_nodes_from([1,2,3,4], bipartite = 1) #label other set of nodes 1
B.add_edges_from ([("A",1),("B",1),("C",1), ("C", 3), ("D",2),("E", 3), ("E", 4)])

print (bipartite.is_bipartite(B)) #query if B is bipartite
B.add_edge("A", "B") #this breaks the bipartition and returns False in the next line
print (bipartite.is_bipartite(B))
B.remove_edge("A", "B") #removes the edge
print (bipartite.is_bipartite(B))

X = set([1,2,3,4])
print (bipartite.is_bipartite_node_set(B,X)) #check if this set is in B
X = set(["A","B","C","D","E"])
print (bipartite.is_bipartite_node_set(B,X)) #check if this set is in B

## PROJECT GRAPH

##Bipartitd weighted graph projection 


"""
==========================================================
Ex. Use NetworkX to construct the bipartite weighted graph 
projection of nodes A,B,C,D,E,F and find the weight of 
the edge (A,C).

What is the weight of the edge (A,C)?