Skip to content

Instantly share code, notes, and snippets.

@pablormier
Last active March 12, 2024 16:59
Show Gist options
  • Save pablormier/0caff10a5f76e87857b44f63757729b0 to your computer and use it in GitHub Desktop.
Save pablormier/0caff10a5f76e87857b44f63757729b0 to your computer and use it in GitHub Desktop.
Small and efficient implementation of the Differential Evolution algorithm using the rand/1/bin schema
import numpy as np
def de(fobj, bounds, mut=0.8, crossp=0.7, popsize=20, its=1000):
dimensions = len(bounds)
pop = np.random.rand(popsize, dimensions)
min_b, max_b = np.asarray(bounds).T
diff = np.fabs(min_b - max_b)
pop_denorm = min_b + pop * diff
fitness = np.asarray([fobj(ind) for ind in pop_denorm])
best_idx = np.argmin(fitness)
best = pop_denorm[best_idx]
for i in range(its):
for j in range(popsize):
idxs = [idx for idx in range(popsize) if idx != j]
a, b, c = pop[np.random.choice(idxs, 3, replace = False)]
mutant = np.clip(a + mut * (b - c), 0, 1)
cross_points = np.random.rand(dimensions) < crossp
if not np.any(cross_points):
cross_points[np.random.randint(0, dimensions)] = True
trial = np.where(cross_points, mutant, pop[j])
trial_denorm = min_b + trial * diff
f = fobj(trial_denorm)
if f < fitness[j]:
fitness[j] = f
pop[j] = trial
if f < fitness[best_idx]:
best_idx = j
best = trial_denorm
yield best, fitness[best_idx]
@vietvo89-ADL
Copy link

vietvo89-ADL commented Apr 18, 2020

Hi Pablomier

I got some problems when following your post here: https://pablormier.github.io/2017/09/05/a-tutorial-on-differential-evolution-with-python/

Issue # 1:
I ran:

from yabox.problems import problem
problem(lambda x: sum(x**2)/len(x), bounds=[(-5, 5)] * 2).plot3d()

ImportError: cannot import name 'problem'

I found that there is no problem class in your yabox.problems but BaseProblem instead. How can your code work? Even though I replaced it with BaseProblem but there is another error.

Issue #2
I ran:

result = list(de(lambda x: x**2 / len(x), bounds=[(-100, 100)] * 32))

IndexError: index 251 is out of bounds for axis 0 with size 20

It seems that "pop_denorm" is 2D array but "best_idx" which is returned from np.argmin(fitness) is work for 1D array and out of size
pop_denorm[best_idx] is not right, is not it? pop_denorm is a 2D array but you used it as 1D array (pop_denorm[best_idx]).

Can you show me how to fix it in your code?

Thanks

@vietvo89-ADL
Copy link

Hi Pablo

Why one of these two functions work but the other cannot? It seems that you write this function wrongly since it does not sum x^2 as the formula.

list(de(lambda x: x**2 / len(x), bounds=[(-100, 100)] * 32))
-> fail to run

list(de(lambda x: sum(x**2) / len(x), bounds=[(-100, 100)] * 32))
-> good to run

Thanks

Viet

@pablormier
Copy link
Author

Hi,

You have to provide an objective function to optimize, which returns a number. x ** 2 / len(x) in you case is a 32 vector, but sum(x**2)/len(x) is a number.

Cheers,
P

@vietvo89-ADL
Copy link

Hi Pablo

Thank you for your response. So you mean if any objective function = f(x) returns a vector/matrix/array will not work. Is it right? In this case, I have to select which dimension of a vector/matric/array such as f [i, j, k] to return?

How about the issue "ImportError: cannot import name 'problem'"? What's wrong?

Thanks

Viet

@pablormier
Copy link
Author

Yes you are right, you need to assign values to your vectors that you can compare. If your goal is to maximize or minimize other kind of funcion, you would need multiobjective optimization.

The import problems you are having I guess is for not using Yabox?:

pip install yabox

Then in python:

from yabox import problems

It should work.

Cheers

@rjm227
Copy link

rjm227 commented Oct 1, 2020

hi Pablo, how I fit the follow function in your code? fobj = lambda x: sum(((1-x) ^2)+ 100*(((x+1) - x^2)^2)/len(x-1)
all the bounds i put give me a SyntaxError: invalid syntax

@pablormier
Copy link
Author

Python does not use the ^ operator, but ** instead: (1-x)**2 + 100...

@mj-ribeiro
Copy link

Hi Pablo, I have the same problem: cannot import name 'problem' from 'yabox.problems'

I installed yabox in my machine and doesn't work.

@bummuck
Copy link

bummuck commented Oct 31, 2023

Hi how should I change the code to get best/1/bin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment