def evolution_step(step, pop, fitnesses, save_best=False, display_chords=True, console_prints=True): if display_chords: f.canvas.set_window_title('Step {}/{}'.format(step+1, NUM_STEPS)) if console_prints: print('BEGINNING STEP NUMBER', step) print('Size of pop:', len(pop)) kill_ratio = interpolations['Kill Ratio'].interpolate(step) penalty = interpolations['Incorrect Num Notes Penalty'].interpolate(step) # **Display each chord** if display_chords: for i in range(MAX_SHOW_SIZE): plt.subplot(n_rows, n_cols, i+1) pop[i].plot() chord_pos[pop[i]] = i+1 pop[i].subplot = i+1 plt.title('Chord {}: f=unknown'.format(i+1)) plt.pause(FITNESS_PAUSE) # **Calculate and assign fitness to each organism** row = [] for c, chord in enumerate(pop): frequencies = Guitar.frequency_list(chord.read()) try: fitness = fitness_eval(frequencies, penalty) chord.fitness = fitness if display_chords: if c<MAX_SHOW_SIZE: plt.subplot(n_rows,n_cols,c+1) plt.title('Chord {}: f={}'.format(c+1,round(fitness,2))) row.append(fitness) except Exception as e: print(e,frequencies) if display_chords: plt.pause(FITNESS_PAUSE) avg_f = np.mean(row) if save_best: if len(fitnesses) > 0: if avg_f < min(np.mean(fitnesses, axis=1)): if console_prints: print('Saving this population to file...') with open('best.pickle', 'wb') as file: pickle.dump(pop, file) fitnesses.append(row) # **Kill the weakest chords** # The bottom 50% or so of the population in terms of fitness # will be eliminated and will not have a chance to breed. # - sort by fitness # - remove the bottom half pop.sort(key=lambda x: (x.fitness), reverse=False) kill_count = np.ceil(len(pop)*(kill_ratio)) if console_prints: print('Killing {} organisms with the lowest fitness...'.format(kill_count)) for c, chord in enumerate(pop[-1:int(len(pop)*(1-kill_ratio)):-1]): if display_chords: if chord in chord_pos: plt.subplot(n_rows, n_cols,chord_pos[chord]) plt.title('Killed') draw_x() chord.alive = False #print('Killed Chord {} with f={}'.format(chord_pos[chord],chord.fitness)) pop.remove(chord) if display_chords: plt.pause(KILL_PAUSE) # **Breed the organisms to refill the population** # - Lowest fitness should breed the most # - Use chord_breeder.py to generate offspring candidates = np.copy(pop) [np.append(candidates,pop[0]) for _ in range(first_place_bonus)] [np.append(candidates,pop[1]) for _ in range(second_place_bonus)] [np.append(candidates,pop[2]) for _ in range(third_place_bonus)] candidates = np.repeat(candidates,4) candidates = np.random.permutation(candidates) if console_prints: print('Beginning breeding of remaining population...') diff = MAX_POP_SIZE - len(pop) i = 0 while len(pop) < MAX_POP_SIZE: chord_breeder.set_mutation_rate(interpolations['Mutation Rate'].interpolate(step)) offspring_a = chord_breeder.breed(candidates[i*2], candidates[i*2+1], debug=False) offspring_b = chord_breeder.breed(candidates[i*2], candidates[i*2+1], debug=False) pop.append(offspring_a) empty_spot = find_empty_spot() if empty_spot is not None: chord_pos[offspring_a] = empty_spot if(len(pop)< MAX_POP_SIZE): pop.append(offspring_b) empty_spot = find_empty_spot() if empty_spot is not None: chord_pos[offspring_b] = empty_spot i+=1 if console_prints: print('Bred {} new chords.'.format(diff)) if display_chords: plt.pause(KILL_PAUSE)
step = 0 while patient(fitnesses, monitor='mean'): plt.clf() evolution_step(step, pop, fitnesses, save_best=True, display_chords=display_chords, console_prints=False) step+=1 if __name__ == "__main__": # Defining master chord f1 = Finger(string=2, technique='Single_Note', start_fret=1) f2 = Finger(string=4, technique='Single_Note', increment=1) f3 = Finger(string=5, technique='Single_Note_Mute_Above', increment=1) #f4 = Finger(string=1, technique='Single_Note', increment=3) master_chord = Chord(fingers=[f1,f2,f3]) master_frequencies = Guitar.frequency_list(master_chord.read()) master_chord.plot() plt.title('Master Chord') plt.show() #master_frequencies = q_transform.analyze('./tmp/target.wav', plot_q_transform=True, debug=True) print('Master frequencies:',master_frequencies) print('Showing {0}% of organisms in the population'.format(MAX_SHOW_SIZE/MAX_POP_SIZE*100)) # Initializing the population randomly f, axs = plt.subplots(n_rows, n_cols, sharex=True) #f.tight_layout(pad=1.0) chord_pos = {} #mng = plt.get_current_fig_manager() #mng.window.state('zoomed') kill_interp = LinearInterpolation(start=.3,end=.6,end_step=25) mutation_interp = LinearInterpolation(start=.1,end=.6,end_step=60)