Quickstart Optimization

An optimization process can be presented as following:

../_images/optiScheme.svg
  • Optimization algorithm: algorithmInterface. This is the algorithm that performs the optimization, and outputs a vector of variables between [0, 1[.

  • Maths to physics: interfaceMathsToPhysics. Transforms the output vector of the optimization algorithm to the variables of a InterfaceDevice. The usage of this block becomes meaningful for more complex optimization problem, such as optimizing a BLDC motor while keeping the outer diameter constant. In this case, a good implementation of the M2P block automatically scales the inner dimensions of the motor to comply with this constraint.

  • Characterization: interfaceCharacterization. Based on the attributes of the device, performs some computation. This block is nearly useless for simple optimization problems (when the objective function is easily computed) but becomes interesting for more complex problems, where many things need to be precalculated before obtaining the objective functions and constraints. This for example can hold an analytical or a FEM magnetic model. A sub-optimization could also be performed there.

  • Objective and constraints: interfaceObjCons. These classes correspond to either what has to be minimized, or which constraints <=0 has to be complied with.

Quick example: \(\min_{x, y \in [0, 2]} f(x) = \sqrt{ 1 + (y+3) \cdot x^2 }, g(x) = 4 + 2 \sqrt{y+3} \cdot \sqrt{1+(x-1)^2}\), under the constrained that \(x \leq 0.55\). This is a bi-objective problem and will lead to a pareto front.

"""This example shows how to start a small optimization problem. Start with these imports: (note: full path is not necessary)"""

from optimeed.core import InterfaceDevice
from optimeed.optimize.optiAlgorithms import MultiObjective_GA as OptimizationAlgorithm
# from optimeed.optimize.optiAlgorithms import NLOpt_Algorithm as OptimizationAlgorithm  # Toggle this line to use NLOpt
from optimeed.optimize import Optimizer, Real_OptimizationVariable, InterfaceObjCons, InterfaceCharacterization
from optimeed.visualize.displayOptimization import OptimizationDisplayer
from optimeed.visualize import start_qt_mainloop
import time


"""User-defined structures"""


class Device(InterfaceDevice):
    """Define the Device to optimize."""
    x: float  # Type hinted -> will be automatically saved
    y: float  # Type hinted -> will be automatically saved

    def __init__(self):
        self.x = 1
        self.y = 1


class Characterization(InterfaceCharacterization):
    """Define the Characterization scheme. In this case nothing is performed,
     but this is typically where model code will be executed and results saved."""
    def compute(self, thedevice):
        time.sleep(0.005)


class MyObjective1(InterfaceObjCons):
    """First objective function (to be minimized)"""
    def compute(self, theDevice):
        return (1 + (theDevice.y+3)*theDevice.x**2)**0.5


class MyObjective2(InterfaceObjCons):
    """Second objective function (to be minimized)"""
    def compute(self, theDevice):
        return 4 + 2*(theDevice.y+3)**0.5*(1+(theDevice.x-1)**2)**0.5


class MyConstraint(InterfaceObjCons):
    """Constraints, that needs to be <= 0"""
    def compute(self, theDevice):
        return theDevice.x - 0.55


def run():
    """Start the main code. Instantiate previously defined classes."""
    theDevice = Device()
    theAlgo = OptimizationAlgorithm()
    theAlgo.set_optionValue(theAlgo.OPTI_ALGORITHM, "OMOPSO")
    theAlgo.set_optionValue(theAlgo.NUMBER_OF_CORES, 28)  # Toggle this line to use more cores. Default is 1 (single core)

    theCharacterization = Characterization()

    """Variable to be optimized"""
    optimizationVariables = list()
    optimizationVariables.append(Real_OptimizationVariable('x', 0, 2))  #
    optimizationVariables.append(Real_OptimizationVariable('y', 0, 2))

    """Objective and constraints"""
    listOfObjectives = [MyObjective1(), MyObjective2()]
    listOfConstraints = [MyConstraint()]

    """Set the optimizer"""
    theOptimizer = Optimizer()
    theOptimizer.set_optionValue(theOptimizer.KWARGS_OPTIHISTO, {"autosave": True, "compress_save": True})
    PipeOptimization = theOptimizer.set_optimizer(theDevice, listOfObjectives, listOfConstraints, optimizationVariables, theOptimizationAlgorithm=theAlgo, theCharacterization=theCharacterization)
    theOptimizer.set_max_opti_time(3)

    """Start the optimization"""
    display_opti = True
    if display_opti:  # Display real-time graphs
        optiDisplayer = OptimizationDisplayer(PipeOptimization, listOfObjectives, theOptimizer)
        _, _, _ = optiDisplayer.generate_optimizationGraphs()
        resultsOpti, convergence = optiDisplayer.launch_optimization()
    else:  # Just focus on results
        resultsOpti, convergence = theOptimizer.run_optimization()

    """Gather results"""
    print("Best individuals :")
    for device in resultsOpti:
        print("x : {} \t y : {}". format(device.x, device.y))

    if display_opti:
        start_qt_mainloop()  # To keep windows alive

    """Note that the results are automatically saved if KWARGS_OPTIHISTO autosaved=True.
    In this case, optimization folder is automatically generated in Workspace/optiX. It contains five files:
    -> autosaved: contains all the devices evaluated during the optimization
    -> logopti: contains all the information relating to the optimization itself: objectives, constraints, evaluation time.
    -> opticonvergence: contains all the information relative to the convergence of the optimization (saved only at the end)
    -> results: all the best devices as decided by the optimization algorithm
    -> summary.html: a summary of the optimization problem
    See other tutorials on how to save/load these information.
    """