예제 #1
0
class Algorithm(object):
    """
    Runs the wintermute algorithm
    """

    def __init__(self, model, options):
        """
        Initialize the algorithm
        :return: None
        """
        self._model = model
        self._options = options
        self._history = History()
        self._surrogate = None
        self._rnd = None

    def run(self):
        """
        Run the optimization algorithm
        :return: The run history
        :rtype: History
        """
        self._rnd = Random()
        # TODO (JLD): Set the seed from the options
        self._rnd.seed()
        # Determine the initial population size based on the requirements for an initial surrogate model
        parent_pop = self.get_initial_population()

        # Evaluate the initial population
        self.evaluate(parent_pop)
        self._history.add_population(parent_pop)

        # Generate a surrogate model
        self._surrogate = Surrogate(parent_pop)

        # Apply the moving operators to generate a child population
        self.sort_population(parent_pop)
        pop_size = self.culling_function(len(parent_pop))
        child_pop = [ind.copy() for ind in parent_pop[0:pop_size]]

        # Flag children for movement

        for ind in child_pop:
            if


        # Sort the parent population and using the culling function, select the N+1 population size of individual
        # to apply the moving operators on
        # flag individuals for movement
        # Apply the global moving operator
        # Apply the local moving operator
        # Sort the combined parent and child population and select the best N+1 population size individuals
        # to become the new parent population
        # Check convergence (depends on dynamic culling functions as well)
        # Repeat
        pass

    def set_model(self, model):
        """
        Set the model for the algorithm to use
        :param model: The model to set
        :type model: Model
        :return: None
        """
        self._model = model

    def set_options(self, options):
        """
        Set the algorithm options
        :param options: The options to set
        :type options: Options
        :return: None
        """
        self._options = options

    def get_initial_population(self):
        """
        Generate an initial populaion
        :return: An initial population
        :rtype: list(Individual)
        """
        # Determine the initial population size
        # Initial popualtion size depends on the number of dimensions and minimum number of points
        # to generate an initial surrogate model
        # Rule of thumb (D+1)(D+2)
        # Require 2x the number of points 1) L2 Orthogonal Array 2) Latin Hypercube
        # TODO (JLD): Look into DOE methods for large dimensionality space

        # Given the model bounds, first generate an L2 orthogonal array DOE of size (n/2) and initialize
        # the individuals at those points, and add them to the list.

        # Then for the remaining n/2 individual, initialize them using a latin hypercube sampling and add them
        # to the list

        # return the population
        return []

    def get_initial_population_size(self):
        """
        Get the initial population size
        :return: The initial population size
        :trype: int
        """

        pass

    def evaluate(self, population):
        """
        Evaluate the population
        :param population: The population to evaluate
        :type population: list(Individual)
        :return: None
        """
        for ind in population:
            f, h, g = self._model.evaluate(ind.x)
            ind.f = f
            ind.h = h
            ind.g = g

    def select_for_movement(self, population):
        pass

    def culling_function(self, pop_size):
        """
        Given the current population size, return the size of the next population
        :param pop_size: The current population size
        :return: The next generation's population size
        """
        return len(pop_size) - 1

    def sort_population(self, population):
        """
        Sort the population and return the size best individuals, if size=None than the entire population is sorted
        and returned
        :param population: THe population to sort
        :param size: The maximum number of individuals to return
        """
        pass

    def move_popualation(self, population):
        """
        Apply local or global movement operations to construct a new population.
        :param population: The population to move
        :return: The new population
        """
        # Sort the population into local and global movement and make a copy
        # Apply local movement
        # For each individual in the local movement population
        # Optimize using the surrogate model with the location of the local individual as the start point
        # Use the converged location as the new location for the individual (this means that the optimizer
        # can operate on the individual object in place)
        # Apply global movement
        # Apply the crossover and mutation genetic operators on the population
        # TODO (JLD): Research crossover and mutation operators that do not require user input
        # return the new population.
        pass