Source code for optimeed.optimize.optiAlgorithms.NLOpt_Algorithm

import nlopt
import numpy as np

from optimeed.core.tools import isNonePrintMessage, printIfShown, SHOW_ERROR, SHOW_WARNING, indentParagraph
from .algorithmInterface import AlgorithmInterface
from optimeed.optimize.optiVariable import Binary_OptimizationVariable, Integer_OptimizationVariable, Real_OptimizationVariable
from .convergence import EvolutionaryConvergence
from optimeed.core import Option_class


[docs]class ConvergenceManager: def __init__(self): self.objectives = [] self.currStep = 0 self.popSize = 0 self.convergence = EvolutionaryConvergence()
[docs] def add_point(self, newObj): self.objectives.append([newObj]) if len(self.objectives) == self.popSize: self.convergence.set_points_at_step(self.currStep, self.objectives, [[]]*len(self.objectives)) self.currStep += 1 self.objectives = []
[docs] def set_pop_size(self, popSize): self.popSize = popSize
[docs]class NLOpt_Algorithm(AlgorithmInterface, Option_class):
[docs] ALGORITHM = 0
[docs] POPULATION_SIZE = 1
def __init__(self): super().__init__() self.maxTime = None # set by set_maxtime self.evaluationFunction = None # set by set_evaluationFunction self.theDimensionalConstraints = None self.Options.add_option(self.ALGORITHM, "Algorithm. Recommended local/global: LN_SBPLX/GN_CRS2_LM . Consult NLopt help page for more.", 'GN_CRS2_LM') self.Options.add_option(self.POPULATION_SIZE, "Size of the population (stochastic algorithms only)", 20) self.convManager = ConvergenceManager() self.curr_pop = 0
[docs] def compute(self, initialVectorGuess, listOfOptimizationVariables): # Check if variables properly initialized, otherwise return notInit_message = " not initialized in NLOpt_Algorithm. Aborting optimization loop." if isNonePrintMessage(self.maxTime, "maxTime" + notInit_message, SHOW_ERROR): return if isNonePrintMessage(self.evaluationFunction, "evaluationFunction" + notInit_message, SHOW_ERROR): return if self.Options.get_value(self.POPULATION_SIZE) <= len(initialVectorGuess): raise ValueError("Population size must be bigger than the number of parameters of this algorithm. Use options") self.convManager.set_pop_size(self.Options.get_value(self.POPULATION_SIZE)) # If everything exists: create nlopt and launch it numberOfOptimizationParameters = len(initialVectorGuess) theOptimizationAlgorithm = nlopt.opt(getattr(nlopt, self.Options.get_value(self.ALGORITHM)), numberOfOptimizationParameters) theOptimizationAlgorithm.set_min_objective(self.evaluationFunction) theOptimizationAlgorithm.set_maxtime(float(self.maxTime)) self.__set_optimizationVariables(listOfOptimizationVariables, theOptimizationAlgorithm) theOptimizationAlgorithm.set_population(int(self.Options.get_value(self.POPULATION_SIZE))) return [theOptimizationAlgorithm.optimize(np.array(initialVectorGuess).astype(float))]
@staticmethod
[docs] def __set_optimizationVariables(listOfOptimizationVariables, theOptimizationAlgorithm): lowerBounds = [] upperBounds = [] for optimizationVariable in listOfOptimizationVariables: if type(optimizationVariable) is Real_OptimizationVariable: lowerBounds.append(optimizationVariable.get_min_value()) upperBounds.append(optimizationVariable.get_max_value()) elif type(optimizationVariable) is Integer_OptimizationVariable: printIfShown("Integer variables not natively supported by the optimization algorithm", SHOW_WARNING) lowerBounds.append(optimizationVariable.get_min_value()) upperBounds.append(optimizationVariable.get_max_value()) elif type(optimizationVariable) is Binary_OptimizationVariable: printIfShown("Boolean variables not natively supported by the optimization algorithm", SHOW_WARNING) lowerBounds.append(0) upperBounds.append(1) else: raise ValueError("Optimization algorithm not working with this kind of optimization variables") theOptimizationAlgorithm.set_lower_bounds(np.array(lowerBounds).astype(float)) theOptimizationAlgorithm.set_upper_bounds(np.array(upperBounds).astype(float))
[docs] def set_evaluationFunction(self, evaluationFunction, callback_on_evaluate, numberOfObjectives, _numberOfConstraints): if numberOfObjectives > 1: printIfShown("Optimization algorithm does not support true multiobjective. Using sum instead", SHOW_WARNING) def adapted_evaluationFunction(x_in, _grad): returnedValues = evaluationFunction(x_in) objs = returnedValues["objectives"] const = returnedValues["constraints"] sum_const = 0 for constraint in const: if constraint > 0: sum_const += constraint*7000 callback_on_evaluate(returnedValues) objective = np.float(sum(objs) + sum_const) self.convManager.add_point(objective) return objective self.evaluationFunction = adapted_evaluationFunction
[docs] def set_maxtime(self, maxTime): self.maxTime = maxTime
[docs] def __str__(self): theStr = '' theStr += "NLOpt optimization library\n" theStr += indentParagraph(str(self.Options), indent_level=1) return theStr
[docs] def get_convergence(self): return self.convManager.convergence