def create_initial_solution(instance, path): oligos = instance.oligos result_length = instance.result_length oligos_len = len(oligos[0].nuc) overlaps_pairs = create_overlaps_hash(oligos) start = time() starting_oligo = choose_starting_oligo(oligos, overlaps_pairs) sequence, overlaps = make_starting_solution(starting_oligo, result_length, oligos_len, overlaps_pairs) stop = time() elapsed_time = round(stop-start,2) solution = Solution() solution.sequence = sequence solution.overlaps = overlaps log_to_file (instance, solution, overlaps, sequence, oligos_len, path, elapsed_time, "INITIAL") return solution
def transform(solution): new_solution = Solution(solution) used_oligos = filter(lambda x: x.used, instance.oligos) unused_oligos = filter(lambda x: not x.used, instance.oligos) def choose_used(): probability = 0.8 * ((float(len(used_oligos)) / len(used_oligos + unused_oligos)) ** 2) dice = random.random() return (dice < probability) if len(used_oligos) == 0: choose_from = unused_oligos elif len(unused_oligos) == 0: choose_from = used_oligos else: choose_from = used_oligos if choose_used() else unused_oligos chosen_oligo = random.choice(choose_from) new_oligo_pos = -1 # print len(solution.overlaps) if len(solution.overlaps) > 0: tabu_filtered_overlaps = filter(lambda x: x not in tabu_overlaps, solution.overlaps) min_overlap = min(tabu_filtered_overlaps, key=lambda(o1,o2,len,pos): len) # Add overlap to tabu list if exceeded limit global revert_attempts, max_revert_attempts if revert_attempts >= max_revert_attempts: revert_attempts = 0 tabu_overlaps.append(min_overlap) left_trailing = -1 * solution.overlaps[0][3] right_trailing = -1 * (len(instance.solution.sequence) - solution.overlaps[-1][3] - 2 * oligo_length + solution.overlaps[-1][2]) o1, o2, overlap_len, o1_pos = min_overlap # print overlap_len, left_trailing, right_trailing while not (new_oligo_pos in range(0, len(solution.sequence) - oligo_length + 1)): if (overlap_len <= min(left_trailing, right_trailing)) or (left_trailing == 0 and right_trailing == 0): # print "Inserting in the middle" # calculate offset defined as distance from the overlap's beginning offset = random.randint(0, oligo_length + o1.overlap(o2)) - oligo_length new_oligo_pos = o1_pos + oligo_length - overlap_len + offset elif (overlap_len > left_trailing) and (overlap_len > right_trailing): # print "Inserting in random trailing space" # left_index = random.randint(0, -1 * left_trailing) # right_index = random.randint(len(solution.sequence) - oligo_length - (-1 * right_trailing) + 1, len(solution.sequence) - oligo_length + 1) left_index = 0 right_index = len(solution.sequence) - oligo_length new_oligo_pos = random.choice([left_index, right_index]) elif overlap_len > left_trailing: # print "Inserting in left trailing space" # new_oligo_pos = random.randint(0, -1 * left_trailing) new_oligo_pos = 0 elif overlap_len > right_trailing: # print "Inserting in right trailing space" # new_oligo_pos = random.randint(len(solution.sequence) - oligo_length - (-1 * right_trailing) + 1, len(solution.sequence) - oligo_length + 1) new_oligo_pos = len(solution.sequence) - oligo_length else: new_oligo_pos = random.randint(0, len(solution.sequence) - oligo_length) else: new_oligo_pos = random.randint(0, len(solution.sequence) - oligo_length) # print "Inserting %s at %d" % (chosen_oligo, new_oligo_pos) new_oligo_end = new_oligo_pos + (oligo_length - 1) # this is some info returned for reverting changes old_overlaps = copy(solution.overlaps) old_oligo_usage = { oligo: oligo.used_times for oligo in instance.oligos } # substitute the newly chosen oligo into the sequence new_solution.sequence = solution.sequence[:new_oligo_pos] + chosen_oligo.nuc + solution.sequence[new_oligo_end + 1:] # print new_solution.sequence # calculate new usage of oligos new_overlaps = [] previous = None for oligo in instance.oligos: oligo.used_times = 0 for i in range(len(new_solution.sequence) - oligo_length + 1): nuc = new_solution.sequence[i:i+oligo_length] if instance.oligos_dict.has_key(nuc): oligo = instance.oligos_dict[nuc] oligo.used_times += 1 if previous == None: # next iteration if it's the first found oligo previous = (oligo, i) continue else: prev_oligo, prev_pos = previous overlap_len = oligo_length - i + prev_pos new_overlaps.append((prev_oligo, oligo, overlap_len, prev_pos)) previous = (oligo, i) x = len(filter(lambda o: o.used, instance.oligos)) # print x, "used out of", len(instance.oligos) if x > len(instance.oligos): raw_input() new_solution.overlaps = new_overlaps return new_solution, old_overlaps, old_oligo_usage pass