Пример #1
0
def center_of_mass_selection(run_id, max_generation, children_per_generation):
    filters = [Box.run_id == run_id, Box.generation <= max_generation]
    ids = [e[0] for e in session.query(Box.id).filter(*filters).all()]
    alpha = [e[0] for e in session.query(Box.alpha).filter(*filters).all()]
    beta = [e[0] for e in session.query(Box.beta).filter(*filters).all()]
    alpha_bar = sum(alpha) / len(alpha)
    beta_bar = sum(beta) / len(beta)
    distance = [
        sqrt((alpha[e] - alpha_bar)**2 + (beta[e] - beta_bar)**2)
        for e in range(len(alpha))
    ]
    weights = [e / sum(distance) for e in distance]
    normalized_weights = [e / sum(weights) for e in weights]
    return int(np.random.choice(ids, p=normalized_weights))
Пример #2
0
    def get_prior(cls, run_id, generation, alpha_bin, beta_bin,
                  initial_mutation_strength):
        """
        Looks for the most recent mutation_strength row. If a row doesn't exist
        for this bin, the default value is used from the configuration file.

        Args:
            cls (classmethod): here MutationStrength.__init__ .
            run_id (str): identification string for run.

        Returns:
            ms (float): either the mutation strength specified in the mutation
                stength datatable, or the default mutation strength if there is
                no row in the datatable corresponding to the bin.

        """

        ms = session.query(MutationStrength) \
                .filter(
                    MutationStrength.run_id == run_id,
                    MutationStrength.alpha_bin == alpha_bin,
                    MutationStrength.beta_bin == beta_bin,
                    MutationStrength.generation <= generation) \
                .order_by(MutationStrength.generation.desc()) \
                .first()

        if ms:
            return ms
        else:
            return MutationStrength(run_id, generation, alpha_bin, beta_bin,
                                    initial_mutation_strength)
Пример #3
0
def calculate_all_mutation_strengths(run_id, gen, initial_mutation_strength):
    parent_ids = get_all_parent_ids(run_id, gen)
    ms_bins = []
    for parent_id in parent_ids:
        parent_bin = session.query(Box).get(parent_id).bin
        if parent_bin not in ms_bins:
            calculate_mutation_strength(run_id, gen + 1, parent_bin,
                                        initial_mutation_strength)
        ms_bins.append(parent_bin)
Пример #4
0
def new_boxes(run_id, gen, children_per_generation, config):
    # calculate mutation strengths, if adaptive
    if 'adaptive' in config['mutation_scheme'] and gen > 1:
        calculate_all_mutation_strengths(run_id, gen - 1,
                                         config['initial_mutation_strength'])

    boxes = []
    for i in range(children_per_generation):
        if config['selection_scheme'] == 'smallest_bin':
            parent_id = smallest_bin_selection(run_id, gen - 1,
                                               children_per_generation)
        elif config['selection_scheme'] == 'center_of_mass':
            parent_id = center_of_mass_selection(run_id, gen - 1,
                                                 children_per_generation)
        elif config['selection_scheme'] == 'hybrid':
            select = random()
            if select < 0.5:
                parent_id = smallest_bin_selection(run_id, gen - 1,
                                                   children_per_generation)
            else:
                parent_id = center_of_mass_selection(run_id, gen - 1,
                                                     children_per_generation)
        else:
            print('REVISE CONFIG, UNSUPPORTED SELECTION SCHEME.')
        parent_box = session.query(Box).get(parent_id)

        if config['mutation_scheme'] == 'flat':
            mutation_strength = config['initial_mutation_strength']
        elif config['mutation_scheme'] == 'hybrid':
            mutation_strength = np.random.choice(
                [1., config['initial_mutation_strength']])
        elif config['mutation_scheme'] == 'adaptive':
            mutation_strength_key = [
                run_id, gen, *parent_box.bin,
                config['initial_mutation_strength']
            ]
            mutation_strength = MutationStrength.get_prior(
                *mutation_strength_key).clone().strength
        elif config['mutation_scheme'] == 'hybrid_adaptive':
            mutation_strength_key = [
                run_id, gen, *parent_box.bin,
                config['initial_mutation_strength']
            ]
            ms = MutationStrength.get_prior(
                *mutation_strength_key).clone().strength
            mutation_strength = np.random.choice([1., ms])
        else:
            print("REVISE CONFIG FILE, UNSUPPORTED MUTATION SCHEME.")

        # mutate material
        box = mutate_box(parent_box, mutation_strength, gen)
        boxes.append(box)
    return boxes
Пример #5
0
def boxes_in_generation(run_id, generation):
    """Count number of materials in a generation.

    Args:
        run_id (str): identification string for run.
        generation (int): iteration in overall bin-mutate-simulate rountine.

    Returns:

    """
    return session.query(Box).filter(Box.run_id == run_id,
                                     Box.generation == generation).count()
Пример #6
0
def calculate_mutation_strength(run_id, generation, mutation_strength_bin,
                                initial_mutation_strength):
    """Query mutation_strength for bin and adjust as necessary.

    Args:
        run_id (str): identification string for run.
        generation (int): iteration in bin-mutate-simulate routine.
        parent (sqlalchemy.orm.query.Query): parent-material corresponding to
            the bin being queried.

    Returns:
        mutation_strength.strength (float): mutation strength to be used for
        parents in the bin being queried. If the fraction of children from
        previous generation which populate the SAME bin as their parent is LESS
        THAN 10% then the mutation strength is REDUCED BY 5%. If the fraction
        of these children populating the SAME bin as their parent is GREATER
        THAN 50% then the mutation strength is INCREASED BY 5%.

    """
    mutation_strength_key = [run_id, generation, *mutation_strength_bin]
    mutation_strength = session.query(MutationStrength).get(
        mutation_strength_key)
    mutation_strength_key.append(initial_mutation_strength)

    if mutation_strength:
        pass
    else:
        mutation_strength = MutationStrength.get_prior(
            *mutation_strength_key).clone()
        mutation_strength.generation = generation

        try:
            fraction_in_parent_bin = calculate_percent_children_in_bin(
                run_id, generation, mutation_strength_bin)
            if fraction_in_parent_bin < 0.1 and mutation_strength.strength / 1.1 > 0:
                mutation_strength.strength /= 1.1
            elif fraction_in_parent_bin > 0.5 and mutation_strength.strength + 1.1 < 1:
                mutation_strength.strength *= 1.1
        except ZeroDivisionError:
            pass

        try:
            session.add(mutation_strength)
            session.commit()
        except (FlushError, IntegrityError) as e:
            print(
                "Somebody beat us to saving a row with this generation. That's ok!"
            )
            session.rollback()
            # it's ok b/c this calculation should always yield the exact same result!
    sys.stdout.flush()
    return mutation_strength.strength
Пример #7
0
    def calculate_generation_index(self):
        """Determine material's generation-index.

        Args:
            self (class): row in material table.

        Returns:
            The generation-index is used to count the number of materials
            present in the database (that is to have all definition-files in
            the RASPA library and simulation data in the materials datatable).
            This attribute is used to determine when to stop adding new
            materials to one generation and start another.

        """
        return session.query(Box).filter(
            Box.run_id == self.run_id,
            Box.generation == self.generation,
            Box.id < self.id,
        ).count()
Пример #8
0
def get_all_parent_ids(run_id, generation):
    return [e[0] for e in session.query(Box.parent_id) \
            .filter(Box.run_id == run_id, Box.generation == generation) \
            .distinct() if e[0] != None]