-
Notifications
You must be signed in to change notification settings - Fork 7
Basic usage
We will demonstrate using NMMSO to solve a one-dimensional optimisation problem. The function will we optimise is:
-x4 + x3 + 3x2
Plotting this function with x in the range [-2, 3] gives:

This function has two optima (one global and one local). We can use NMMSO to find these optima.
First we need to write Python code that captures the problem we wish to solve. Problems must be written as a Python class that implements two functions: fitness and get_bounds.
The fitness function takes one argument. This argument is a 1D Numpy array containing a value for each parameter of the problem. Since our problem is one dimensional this array will contain a single value. The function must return a single scalar value which is the fitness for the given parameter values. This is where we implement the function to be optimised.
The get_bounds function takes no arguments and returns two Python lists that define the bounds of the parameter search. The first list specifies the minimum value for each parameter, the second list specifies the maximum value for each parameter. As our problem is one dimensional there will only be one value in each list.
The implementation of our problem in Python is therefore:
class MyProblem:
@staticmethod
def fitness(params):
x = params[0]
return -x**4 + x**3 + 3 * x**2
@staticmethod
def get_bounds():
return [-2], [3]The following code uses NMMSO to solve this problem. The Nmmso object is constructed
with an instance of the problem class. The algorithm is then run and will stop at the
end of the iteration where the number of fitness function evaluations exceeds the given
amount. When run the algorithm returns a list of objects that contain the location and
value for each of the discovered modes.
from pynmmso import Nmmso
class MyProblem:
@staticmethod
def fitness(params):
x = params[0]
return -x**4 + x**3 + 3 * x**2
@staticmethod
def get_bounds():
return [-2], [3]
def main():
number_of_fitness_evaluations = 1000
nmmso = Nmmso(MyProblem())
my_result = nmmso.run(number_of_fitness_evaluations)
for mode_result in my_result:
print("Mode at {} has value {}".format(mode_result.location, mode_result.value))
if __name__ == "__main__":
main()Running this code produces output similar to the following:
Mode at [1.65586203] has value 5.247909824656198
Mode at [-0.90586887] has value 1.0450589249496887
The algorithm has successfully found the two optima of this problem.
To demonstrate a two dimensional example we will use the following function which is the same function as our 1D example but applied to both parameters and the result added together:
-x4 + x3 + 3x2 - y4 + y3 + 3y2
This functions looks like:

This function has four optima (one global and three local).
Our problem class is very similar but the fitness function now extracts two parameter values from the given
array and the get_bounds function includes an additional dimension on each of the lists it returns.
class My2DProblem:
@staticmethod
def fitness(params):
x = params[0]
y = params[1]
return -x**4 + x**3 + 3 * x**2 -y**4 + y**3 + 3 * y**2
@staticmethod
def get_bounds():
return [-2, -2], [3, 3]The rest of the code is identical to the 1D case except we now pass Nmmso an instance of this the My2DProblem class and we have increased the number of allowed evaluations of the fitness function as this is a more complex problem.
from pynmmso import Nmmso
class My2DProblem:
@staticmethod
def fitness(params):
x = params[0]
y = params[1]
return -x**4 + x**3 + 3 * x**2 -y**4 + y**3 + 3 * y**2
@staticmethod
def get_bounds():
return [-2, -2], [3, 3]
def main():
number_of_fitness_evaluations = 5000
nmmso = Nmmso(My2DProblem())
my_result = nmmso.run(number_of_fitness_evaluations)
for mode_result in my_result:
print("Mode at {} has value {}".format(mode_result.location, mode_result.value))
if __name__ == "__main__":
main()This produces output like:
Mode at [-0.90587247 -0.90586955] has value 2.0901178498359814
Mode at [-0.90587247 1.65586884] has value 6.292968749938909
Mode at [ 1.65586884 -0.90586955] has value 6.292968749997689
Mode at [1.65586884 1.65586884] has value 10.495819650100618
The algorithm can be used for n-dimensional problems in the same way.