Example #1
0
 def halt(population, generation_count):
     """
     Given a population of candidate solutions and generation count (the
     number of epochs the algorithm has run) will return a boolean to
     indicate if an acceptable solution has been found within the referenced
     population.
     """
     fittest = population[0].chromosome
     suspensions = 0
     for i in range(1, len(fittest) - 2):
         # Check for a suspension.
         if is_suspension(fittest, i, cantus_firmus):
             suspensions += 1
     return (population[0].fitness >= MAX_REWARD + suspensions or
         generation_count > DEFAULT_MAX_GENERATION)
Example #2
0
 def halt(population, generation_count):
     """
     Given a population of candidate solutions and generation count (the
     number of epochs the algorithm has run) will return a boolean to
     indicate if an acceptable solution has been found within the referenced
     population.
     """
     fittest = population[0].chromosome
     suspensions = 0
     for i in range(1, len(fittest) - 2):
         # Check for a suspension.
         if is_suspension(fittest, i, cantus_firmus):
             suspensions += 1
     return (population[0].fitness >= MAX_REWARD + suspensions
             or generation_count > DEFAULT_MAX_GENERATION)
Example #3
0
    def fitness_function(genome):
        """
        Given a candidate solution will return its fitness score assuming
        the cantus_firmus in this closure. Caches the fitness score in the
        genome.
        """
        # Save some time!
        if genome.fitness is not None:
            return genome.fitness

        # The fitness score to be returned.
        fitness_score = 0.0
        # Counts the number of repeated notes in the contrapunctus.
        repeats = 0
        # Counts consecutive parallel thirds.
        thirds = 0
        # Counts consecutive parallel sixths.
        sixths = 0
        # Counts the amount of parallel motion.
        parallel_motion = 0
        # Counts the number of jumps in the melodic contour.
        jump_contour = 0

        contrapunctus = genome.chromosome

        # Make sure the solution starts correctly (at a 5th or octave).
        first_interval = contrapunctus[0] - cantus_firmus[0]
        if first_interval == 7 or first_interval == 4:
            fitness_score += REWARD_FIRST
        else:
            fitness_score -= PUNISH_FIRST

        # Make sure the solution finishes correctly (at an octave).
        if contrapunctus[-1] - cantus_firmus[-1] == 7:
            fitness_score += REWARD_LAST
        else:
            fitness_score -= PUNISH_LAST

        # Ensure the penultimate note is step wise onto the final note.
        if abs(contrapunctus[-1] - contrapunctus[-2]) == 1:
            fitness_score += REWARD_LAST_STEP
        else:
            fitness_score -= PUNISH_LAST_STEP

        # Reward contrary motion onto the final note.
        cantus_firmus_motion = cantus_firmus[-1] - cantus_firmus[-2]
        contrapunctus_motion = contrapunctus[-1] - contrapunctus[-2]

        if ((cantus_firmus_motion < 0 and contrapunctus_motion > 0) or
            (cantus_firmus_motion > 0 and contrapunctus_motion < 0)):
            fitness_score += REWARD_LAST_MOTION
        else:
            fitness_score -= PUNISH_LAST_MOTION

        # Make sure the penultimate note isn't a repeated note.
        penultimate_preparation = abs(contrapunctus[-2] - contrapunctus[-3])
        if penultimate_preparation == 0:
            fitness_score -= PUNISH_REPEATED_PENULTIMATE
        else:
            # Make sure the movement to the penultimate note isn't from too
            # far away (not greater than a third).
            if penultimate_preparation < 2:
                fitness_score += REWARD_PENULTIMATE_PREPARATION
            else:
                fitness_score -= PUNISH_PENULTIMATE_PREPARATION

        # Check the fitness of the body of the solution.
        solution = zip(contrapunctus, cantus_firmus)
        last_notes = solution.pop()
        last_interval = last_notes[0] - last_notes[1]
        for i in range(1, len(solution) - 2):
            current_notes = solution[i]
            contrapunctus_note, cantus_firmus_note = current_notes
            current_interval = contrapunctus_note - cantus_firmus_note

            # Punish parallel fifths or octaves.
            if ((current_interval == 4 or current_interval == 7) and
                (last_interval == 4 or last_interval == 7)):
                fitness_score -= PUNISH_PARALLEL_FIFTHS_OCTAVES

            # Check if the melody is a repeating note.
            if contrapunctus_note == last_notes[0]:
                repeats += 1

            # Check for a suspension.
            if is_suspension(contrapunctus, i, cantus_firmus):
                fitness_score += REWARD_SUSPENSION

            last_notes = current_notes
            last_interval = current_interval

        # Punish too many (> 1/3) repeated notes.
        if repeats > repeat_threshold:
            fitness_score -= PUNISH_REPEATS

        genome.fitness = fitness_score

        return fitness_score
Example #4
0
    def fitness_function(genome):
        """
        Given a candidate solution will return its fitness score assuming
        the cantus_firmus in this closure. Caches the fitness score in the
        genome.
        """
        # Save some time!
        if genome.fitness is not None:
            return genome.fitness

        # The fitness score to be returned.
        fitness_score = 0.0
        # Counts the number of repeated notes in the contrapunctus.
        repeats = 0
        # Counts consecutive parallel thirds.
        thirds = 0
        # Counts consecutive parallel sixths.
        sixths = 0
        # Counts the amount of parallel motion.
        parallel_motion = 0
        # Counts the number of jumps in the melodic contour.
        jump_contour = 0

        contrapunctus = genome.chromosome

        # Make sure the solution starts correctly (at a 5th or octave).
        first_interval = contrapunctus[0] - cantus_firmus[0]
        if first_interval == 7 or first_interval == 4:
            fitness_score += REWARD_FIRST
        else:
            fitness_score -= PUNISH_FIRST

        # Make sure the solution finishes correctly (at an octave).
        if contrapunctus[-1] - cantus_firmus[-1] == 7:
            fitness_score += REWARD_LAST
        else:
            fitness_score -= PUNISH_LAST

        # Ensure the penultimate note is step wise onto the final note.
        if abs(contrapunctus[-1] - contrapunctus[-2]) == 1:
            fitness_score += REWARD_LAST_STEP
        else:
            fitness_score -= PUNISH_LAST_STEP

        # Reward contrary motion onto the final note.
        cantus_firmus_motion = cantus_firmus[-1] - cantus_firmus[-2]
        contrapunctus_motion = contrapunctus[-1] - contrapunctus[-2]

        if ((cantus_firmus_motion < 0 and contrapunctus_motion > 0)
                or (cantus_firmus_motion > 0 and contrapunctus_motion < 0)):
            fitness_score += REWARD_LAST_MOTION
        else:
            fitness_score -= PUNISH_LAST_MOTION

        # Make sure the penultimate note isn't a repeated note.
        penultimate_preparation = abs(contrapunctus[-2] - contrapunctus[-3])
        if penultimate_preparation == 0:
            fitness_score -= PUNISH_REPEATED_PENULTIMATE
        else:
            # Make sure the movement to the penultimate note isn't from too
            # far away (not greater than a third).
            if penultimate_preparation < 2:
                fitness_score += REWARD_PENULTIMATE_PREPARATION
            else:
                fitness_score -= PUNISH_PENULTIMATE_PREPARATION

        # Check the fitness of the body of the solution.
        solution = zip(contrapunctus, cantus_firmus)
        last_notes = solution.pop()
        last_interval = last_notes[0] - last_notes[1]
        for i in range(1, len(solution) - 2):
            current_notes = solution[i]
            contrapunctus_note, cantus_firmus_note = current_notes
            current_interval = contrapunctus_note - cantus_firmus_note

            # Punish parallel fifths or octaves.
            if ((current_interval == 4 or current_interval == 7)
                    and (last_interval == 4 or last_interval == 7)):
                fitness_score -= PUNISH_PARALLEL_FIFTHS_OCTAVES

            # Check if the melody is a repeating note.
            if contrapunctus_note == last_notes[0]:
                repeats += 1

            # Check for a suspension.
            if is_suspension(contrapunctus, i, cantus_firmus):
                fitness_score += REWARD_SUSPENSION

            last_notes = current_notes
            last_interval = current_interval

        # Punish too many (> 1/3) repeated notes.
        if repeats > repeat_threshold:
            fitness_score -= PUNISH_REPEATS

        genome.fitness = fitness_score

        return fitness_score