Skip to content
{{ message }}

# stl08007 / CenterStar

Cannot retrieve contributors at this time
189 lines (146 sloc) 4.86 KB
 import sys import os import itertools import numpy as np def backtrack(v, w, dir_graph): ''' Backtracks through dir_graph to find v_p, w_p ''' # Init prime strings, and the indel char v_p = "" w_p = "" indel = "-" # get our starting index i = len(v) j = len(w) # until we reach 0,0 go through the direction graph and work backwards while i != 0 and j != 0: direction = dir_graph[i,j] if direction == 0: # We go up, add letter to v_p, add indel to w_p v_p += v[i-1] w_p += indel i -= 1 elif direction == 1: # We go left, add indel to v_p, add letter to w_p v_p += indel w_p += w[j-1] j -= 1 else: # We go up/left (diag), add letter to v_p, w_p v_p += v[i-1] w_p += w[j-1] i -= 1 j -= 1 # Reverse the strings since we added from the end first v_p = v_p[::-1] w_p = w_p[::-1] return v_p, w_p def find_edit_distance(v,w): ''' Finds the edit distance between w and v Returns the distance between the two strings Edit graph is set up as v along y axis (left), w along x axis (top) Score 0 for match, 1 for mistmatch or indel ''' # n, m are number of rows, cols # Note we need the +1 because we need to add the 0th row and column as our starting point # And python indexes at 0 n = len(v)+1 m = len(w)+1 # Init graph edit_graph = np.zeros((n, m)) dir_graph = np.zeros((n,m)) # Add distances along x, y axis # +1 at every step along 0th row, col because indels -> +1 for i in range(n): edit_graph[i,0] = i for j in range(m): edit_graph[0,j] = j # Go through the graph for i in range(1, n): for j in range(1,m): # Get the diag distance if v[i-1] == w[j-1]: diag = edit_graph[i-1,j-1] else: diag = edit_graph[i-1,j-1] + 1 # Update min_index, min_score = min(enumerate([edit_graph[i-1, j]+1, edit_graph[i,j-1]+1, diag]), key=lambda p: p) edit_graph[i,j] = min_score # Store direction, backtrack later # 0 = Up, 1 = left, 2 = diag up left dir_graph[i,j] = min_index # Backtrack to get aligned strings (primes) v_p, w_p = backtrack(v, w, dir_graph) # Get distance and return it all distance = edit_graph[n-1,m-1] # Remember we index at 0 so -1 return distance, v_p, w_p def align_strings(S, min_index): ''' Aligns strings S around center string min_index ''' # Pop out our center string from the string list Sc = S.pop(min_index) # Loop through and align, going back and changing as needed for i in range(len(S)): while i >= 0: distance, v_p, w_p = find_edit_distance(Sc, S[i]) Sc = v_p S[i] = w_p i -= 1 return Sc, S def main(): ''' Main Function ''' print "Center Star Algorithm\nStephen Lincoln\nProgramming Assignment 2\n\n\n" # Try to get file as input try: input_file = sys.argv except: print "Please supply an input file" sys.exit() # Assuming that the input file is correct, for sake of brevity # Read in n, strings to S with open(input_file, 'r') as f: content = f.readlines() n = int(content.strip()) S = [s.strip() for s in content[1:]] # Dont forget to strip newlines and such if len(S) > 1000: sys.exit() # Init scoring table to find center string candidate scores = [0 for i in range(n)] # Create all index pairs of strings to score string_pairs = itertools.combinations(range(n), 2) # Iterate and score for pair in string_pairs: v = S[pair] w = S[pair] distance, v_p, w_p = find_edit_distance(v, w) # Update scores for i in range(n): if i in pair: scores[i] += distance # get the string number and score of the best candidate min_index, min_score = min(enumerate(scores), key=lambda p: p) # Now align all the strings with the center string Sc, S = align_strings(S, min_index) # Recombine into a list new_S = [Sc] + S # Init total cost total_cost = 0 # Find the total cost string_pairs = itertools.combinations(range(n), 2) for pair in string_pairs: v = new_S[pair] w = new_S[pair] for i in range(len(v)): if v[i] != w[i]: total_cost += 1 print "Sequences aligned\nmin star cost: %d\ntotal cost: %d" % (min_score, total_cost) for s in new_S: print s # End main if __name__ == '__main__': main()
You can’t perform that action at this time.