def weights(g1): ''' Calculates the total neighboring weight of 'g1'. The total neighboring weight is a tuple of the sum of interactions in the same set as g1 and the sum of interactions in the opposite set as g1. The tuple in this case is represented by a dictionary with keys 'same' and 'other'. I'm using a dictionary because the values need to be mutable; they change as we move vertices between the partitions. ''' ws = {'same': 0, 'other': 0} for g2 in geneinter.genes: w = geneinter.gi(g1, g2) if same_set(g1, g2): ws['same'] += w else: ws['other'] += w return ws
def weights(g1): ''' Calculates the total neighboring weight of 'g1'. The total neighboring weight is a tuple of the sum of interactions in the same set as g1 and the sum of interactions in the opposite set as g1. The tuple in this case is represented by a dictionary with keys 'same' and 'other'. I'm using a dictionary because the values need to be mutable; they change as we move vertices between the partitions. ''' ws = { 'same': 0, 'other': 0 } for g2 in geneinter.genes: w = geneinter.gi(g1, g2) if same_set(g1, g2): ws['same'] += w else: ws['other'] += w return ws
def interweight((A, B)): ''' Calculates the interaction weight of a BPM. It is defined as the difference of sums of interaction scores within each module and the sum of interaction scores between each module divided by the number of genes in the entire BPM. The value returned is a BPM "decorated" with the interaction weight for sorting purposes. This roundabout means of decoration is used so that parallelism can be used for calculating the interaction weights. (As opposed to using a higher order function with 'sorted'.) ''' # For converting a tuple to two arguments gitup = lambda (g1, g2): geneinter.gi(g1, g2) def sum_within(S): return sum(map(gitup, combinations(S, 2))) within = sum_within(A) + sum_within(B) between = sum(map(gitup, product(A, B))) iweight = (within - between) / float(len(A) + len(B)) return (iweight, (A, B))
def localmaxcut(m): ''' Generates a random bipartition and makes the bipartition 'happy' by applying 'Weighted-Flip' (from Leiserson et al., 2011) until there are no unhappy genes left. ''' A, B = random_bipartition() same_set = lambda g1, g2: (g1 in A and g2 in A) or (g1 in B and g2 in B) def weights(g1): ''' Calculates the total neighboring weight of 'g1'. The total neighboring weight is a tuple of the sum of interactions in the same set as g1 and the sum of interactions in the opposite set as g1. The tuple in this case is represented by a dictionary with keys 'same' and 'other'. I'm using a dictionary because the values need to be mutable; they change as we move vertices between the partitions. ''' ws = {'same': 0, 'other': 0} for g2 in geneinter.genes: w = geneinter.gi(g1, g2) if same_set(g1, g2): ws['same'] += w else: ws['other'] += w return ws nweights = {g: weights(g) for g in geneinter.genes} unhappy = get_unhappy(nweights) while unhappy: v = random.choice(unhappy) if v in A: A.remove(v) B.add(v) else: A.add(v) B.remove(v) # This loop eliminates the need to recalculate 'weights' for every # gene again, which is O(n^2) in the number of genes. This loop is # O(n) but comes at the cost of clarity. # # The idea is to modify the weights of every other interacting gene and # to switch the 'same' and 'other' scores of the gene that was made # happy. for g, nw in nweights.iteritems(): if g == v: nw['same'], nw['other'] = nw['other'], nw['same'] continue # The interaction score between this gene and the gene that # was made happy. w = geneinter.gi(v, g) # If the two genes are now in the same set, then 'g' gets a boost # to its happiness. Otherwise, 'g' becomes more unhappy. if same_set(v, g): nw['same'] += w nw['other'] -= w else: nw['same'] -= w nw['other'] += w # Refresh the unhappy list unhappy = get_unhappy(nweights) parallel.inc_counter() parallel.print_progress() return A, B
def localmaxcut(m): ''' Generates a random bipartition and makes the bipartition 'happy' by applying 'Weighted-Flip' (from Leiserson et al., 2011) until there are no unhappy genes left. ''' A, B = random_bipartition() same_set = lambda g1, g2: (g1 in A and g2 in A) or (g1 in B and g2 in B) def weights(g1): ''' Calculates the total neighboring weight of 'g1'. The total neighboring weight is a tuple of the sum of interactions in the same set as g1 and the sum of interactions in the opposite set as g1. The tuple in this case is represented by a dictionary with keys 'same' and 'other'. I'm using a dictionary because the values need to be mutable; they change as we move vertices between the partitions. ''' ws = { 'same': 0, 'other': 0 } for g2 in geneinter.genes: w = geneinter.gi(g1, g2) if same_set(g1, g2): ws['same'] += w else: ws['other'] += w return ws nweights = { g: weights(g) for g in geneinter.genes } unhappy = get_unhappy(nweights) while unhappy: v = random.choice(unhappy) if v in A: A.remove(v) B.add(v) else: A.add(v) B.remove(v) # This loop eliminates the need to recalculate 'weights' for every # gene again, which is O(n^2) in the number of genes. This loop is # O(n) but comes at the cost of clarity. # # The idea is to modify the weights of every other interacting gene and # to switch the 'same' and 'other' scores of the gene that was made # happy. for g, nw in nweights.iteritems(): if g == v: nw['same'], nw['other'] = nw['other'], nw['same'] continue # The interaction score between this gene and the gene that # was made happy. w = geneinter.gi(v, g) # If the two genes are now in the same set, then 'g' gets a boost # to its happiness. Otherwise, 'g' becomes more unhappy. if same_set(v, g): nw['same'] += w nw['other'] -= w else: nw['same'] -= w nw['other'] += w # Refresh the unhappy list unhappy = get_unhappy(nweights) parallel.inc_counter() parallel.print_progress() return A, B