def mutate(child1, child2, p, proti): """ Causes random mutations of the directions in the conformations. """ # convert to lists to make the tuple mutable child1_list = list(child1) child2_list = list(child2) for i in range(len(child1_list)): # random number (0,1) r1 = random.random() r2 = random.random() possible = False if r1 < p: # save copy backup = copy.deepcopy(child1_list[i]) # check if mutation would be possible without making the conformation invalid for d in random.sample(['L', 'R', 'S'], 3): child1_list[i] = d x, y, z = directions(''.join(child1_list)) if not double(x, y, z): possible = True break # undo the mutation if it would invalidate the conformation if not possible: child1_list[i] = backup possible = False if r2 < p: backup = copy.deepcopy(child2_list[i]) for d in random.sample(['L', 'R', 'S'], 3): child2_list[i] = d x, y, z = directions(''.join(child2_list)) if not double(x, y, z): possible = True break if not possible: child2_list[i] = backup child1_list = ''.join(child1_list) child2_list = ''.join(child2_list) # return the mutated conformations along with their scores x1, y1, z1 = directions(child1_list) x2, y2, z2 = directions(child2_list) return (child1_list, score_it(proti, x1, y1, z1)), \ (child2_list, score_it(proti, x2, y2, z2))
def crossover(parent1, parent2): """ Uses crossover to producre a child from two parents. """ # select point of adjoinment at random n = random.randint(0, len(parent1[0]) - 1) # get the part of one parent up to the nth element partial_parent1 = parent1[0][:n] # get the part of the other parent from the n+1th elment onwards partial_parent2 = parent2[0][n+1:] # try different adjoinment directions for d in random.sample(['L', 'R', 'S'],3): child_string = partial_parent1 + d + partial_parent2 x, y, z = directions(child_string) # return is the conformation is valid if not double(x, y, z): return child_string # indicate that the conformation is invalid return ('impossible', 1)
def create_individual(proti): conformation = '' direction = ['L', 'R', 'S'] i = 1 while i < proti.length - 1: available_directions = [] for d in direction: x_pos, y_pos, z_pos = directions(conformation + d) if not double(x_pos, y_pos, z_pos): available_directions.append(d) try: random_direction = available_directions[random.randint(0,\ len(available_directions) - 1)] conformation += random_direction except: i = 0 conformation = '' i += 1 return conformation
def genetic_plot(string, score, best_yet, proti): """ Makes a graph of two lists list_x, list_y. """ list_x, list_y, list_z = directions(string) # differentiate between types of atom red_dots_x = [] red_dots_y = [] blue_dots_x = [] blue_dots_y = [] yellow_dots_x = [] yellow_dots_y = [] # search through protein and place each atom in the appropiate list for x, y, p in zip(list_x, list_y, proti.listed): if p == 'H': red_dots_x.append(x) red_dots_y.append(y) if p == 'P': blue_dots_x.append(x) blue_dots_y.append(y) if p == 'C': yellow_dots_x.append(x) yellow_dots_y.append(y) # create graphs with colors fig, (ax1, ax2) = plt.subplots(2, 1) ax1.plot(list_x, list_y, '--', color='darkgrey') ax1.plot(red_dots_x, red_dots_y, 'or', markersize=17) ax1.plot(blue_dots_x, blue_dots_y, 'ob', markersize=17) ax1.plot(yellow_dots_x, yellow_dots_y, 'oy', markersize=17) ax1.axis('equal') ax1.set_title(f'Folded protein of length {proti.length}, score: {score}') ax2.plot(best_yet) ax2.set_title('Lowest score per iteration') plt.show()
def initial_population(n, proti): """ Initialize population for tree. """ conformations_list = [] return_list = [] for i in range(2 * n): conformation_string = create_individual(proti) x, y, z = directions(conformation_string) score = score_it(proti=proti, list_x=x, list_y=y, list_z=z) conformation = (conformation_string, score) conformations_list.append(conformation) conformations_list.sort(key=operator.itemgetter(1)) for i in range(n): return_list.append(conformations_list[i]) return return_list
def run(proti): # start timer start = timeit.default_timer() bar = Bar('Progress', max=proti.length) bar.next() bar.next() k = 0 amino_time = [] # specifications for depth first tree building depth = proti.length - 2 q = queue.Queue() q.put('') final_configurations = [] # keep track of scores per substring lowest_score_k = {} all_scores_k = {} lowest_score = 0 # (0,1) probabilities of pruning a path, lower is more exact but less fast p1 = 1 p2 = 1 # set inital values for i in range(proti.length + 1): lowest_score_k[i] = 0 all_scores_k[i] = [0] amino_start = timeit.default_timer() # create a breadth first tree while not q.empty(): state = q.get() # if all aminos are placed, put the string in a list state_x, state_y, state_z = directions(state) if len(state) == depth and not double(state_x, state_y, state_z): final_configurations.append(state) if len(state) < depth: for i in ['L', 'R', 'S', 'U', 'D']: # substring child = copy.deepcopy(state) # string after potentialy placing the next amino child += i child_x, child_y, child_z = directions(child) # discard the string folding into themselves if double(child_x, child_y, child_z): continue if len(child) + 1 > k: amino_stop = timeit.default_timer() amino_time.append(amino_stop-amino_start) bar.next() amino_start = timeit.default_timer() # identify how for into the string it is k = len(child) + 1 # P's are always placed, rest have some conditions if not proti.listed[k] == 'P': # score if placed score = score_it(proti, child_x, child_y, child_z) # min score to get from remaining aminos possible_score = possible_score_func_dee(proti.listed[k+1:],\ score, proti.min_score, proti) if score + possible_score > lowest_score: continue # random number between 0 and 1 r = random.random() # avergage of all strings of the same length average_score_k = sum(all_scores_k[k]) / len(all_scores_k[k]) # conditions for pruning if score > average_score_k and r < p1: continue elif (average_score_k >= score and score > lowest_score_k[k])\ and r < p2: continue # add to tree q.put(child) all_scores_k[k].append(score) if score < lowest_score_k[k]: lowest_score_k[k] = copy.deepcopy(score) if score < lowest_score: lowest_score = copy.deepcopy(score) else: q.put(child) lowest_score = 0 # weed out the best configuration from the remaining strings for c in final_configurations: c_x, c_y, c_z = directions(c) if score_it(proti, c_x, c_y, c_z) < lowest_score: best_config = copy.deepcopy(c) lowest_score = copy.deepcopy(score_it(proti, c_x, c_y, c_z)) best_x, best_y, best_z = directions(best_config) bar.finish() # plot the result stop = timeit.default_timer() print(f'Length: {proti.length}') print(f'Score: {lowest_score}') print(f'Time: {stop - start}') print(f'Conformation: {best_config}') plot(proti, lowest_score, best_x, best_y,'Time per amino placement', 'Amino', 'Time[s]', best_z, scores=amino_time)