# Optimization using a differential evolution technique, ideally with a million iterations

I'm working on an optimization code using differential evolution to solve. However, it is taking a long time to get the solution. See that I have a variable called number_of_iterations that must equal 1000000. When I consider this decision variable equal to a smaller value (eg number_of_iterations=100), the result is pretty quick. But when I use a million, the result takes a long time. Does anyone have any suggestions on how to speed up this procedure?

Here's the code I'm using:

import numpy as np
import random
from scipy.optimize import differential_evolution,NonlinearConstraint
import math

V = 220
FP = 0.85
FS = 1.15
cn = 13.0
cm = cn*FS
alpha = 1
beta = 1000
Cp = 50
Cc = 250
h = 24
Ch = 0.4
n = 273.487851
B = 2.929689
pi = 4210.61

def otm(y):
T=y[0]
cn_m=y[1]
number_of_iterations=1000000
for i in range(1, number_of_iterations):
cn = 13.0
cr = cn
stop = 1
W = math.floor(random.weibullvariate(n,B))
j = 1
while stop == 1:
j = j+1
x = np.random.gamma(alpha,beta)
cr = cr+x
pf = (3**0.5)*V*cr*FP
p = ((pi+pf)*1)/2
Ce = ((p*(j*h))/1000)*Ch
if T < W:
if j <= T and cr > cm:
Custo_Eqp = Ce+Cc
Ciclo = j
stop = 0
elif j < T and cn_m <= cr <= cm:
Custo_Eqp = Ce+Cp
Ciclo = j
stop = 0
elif j == T and cr <= cm:
Custo_Eqp = Ce+Cp
Ciclo = T
stop = 0
else:
if j <= W and cr > cm:
Custo_Eqp = Ce+Cc
Ciclo = j
stop = 0
elif j < W and cn_m <= cr < cm:
Custo_Eqp = Ce+Cp
Ciclo = j
stop = 0
elif j == W and cr <= cm:
Custo_Eqp = Ce+Cc
Ciclo = W
stop = 0
y0=(round(n-(0.2*n)),round(n+(0.2*n)))
y1=(cn,cm)
bounds=(y0,y1)
nlc = NonlinearConstraint(otm, 0, +np.inf)
res=differential_evolution(otm, bounds=bounds, constraints=(nlc),disp = True,maxiter=100)
print(res)


I tried running it on colab pro, but little advance in speed I had. Is there any other place that might even pay to get a lot of speed?

• Welcome to Code Review! You would be more likely to get an answer if you put more effort into describing what calculations this code is performing, rather than expecting reviewers to reverse-engineer your code. MathJax is available for mathematical typesetting. Jun 24 at 1:56
• j is incremented to 2 first thing in the first iteration of the while loop: Is this intentional? (((pi+pf)*1) looks funny, too) Jun 24 at 3:55
• What exactly is being calculated? Jun 24 at 14:05
• (1) have you tried the workers argument to differential_evolution? It uses processes to run the problem on multiple CPU cores. And (2) is otm() deterministic? For example, does otm(274, 14) return the same value every time? It looks like the return value depends on two random values. If that's the case, how do you optimize a function that might return a different value for the exact same arguments? Jun 29 at 5:59

(No help to a lot of speed:
Describe "the Whys": What's special about 1000000? Is something supposed to converge? Is there some tolerable error limit for the result of otm()?)

Don't write, never publish/commit undocumented code.
For Python use docstrings.
Have a look at the Style Guide for Python Code in general. (Starting with naming)

Don't repeat yourself:
In every case you set the stop flag, you assign Ciclo = j
Both branches of if T < W are identical but for use of T and W, respectively, and choice of increment where j equals min(T, W)

    for _ in range(number_of_iterations):  # range(1, number_of_iterations) looked off-by-1
cr = cn = 13.0
W = math.floor(random.weibullvariate(n, B))
for ciclo in itertools.count(2):
x = np.random.gamma(alpha, beta)
cr += x
limit = min(T, W)
if limit < ciclo:
continue
pf = (3**0.5)*V*FP * cr
p = (pi+pf) / 2              # statistics.mean()?
Ce = (p*ciclo) * (h/1000)*Ch

if cm < cr:
break
if ciclo < limit and cn_m <= cr \
or ciclo == T:
break
if ciclo == W:
break