0
\$\begingroup\$

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]
    Custo_Eqp = Ciclo = Custo_acumulado = Ciclo_acumulado = 0
    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
      Custo_acumulado = Custo_acumulado + Custo_Eqp
      Ciclo_acumulado = Ciclo_acumulado + Ciclo
    return Custo_acumulado/Ciclo_acumulado
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?

\$\endgroup\$
4
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Jun 24 at 1:56
  • \$\begingroup\$ j is incremented to 2 first thing in the first iteration of the while loop: Is this intentional? (((pi+pf)*1) looks funny, too) \$\endgroup\$
    – greybeard
    Jun 24 at 3:55
  • \$\begingroup\$ What exactly is being calculated? \$\endgroup\$
    – pacmaninbw
    Jun 24 at 14:05
  • \$\begingroup\$ (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? \$\endgroup\$
    – RootTwo
    Jun 29 at 5:59

1 Answer 1

2
\$\begingroup\$

(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: 
                Custo_acumulado += Cc
                break
            if ciclo < limit and cn_m <= cr \
                or ciclo == T:
                Custo_acumulado += Cp
                break
            if ciclo == W:
                Custo_acumulado += Cc
                break

        Custo_acumulado += Ce
        Ciclo_acumulado += ciclo
    return Custo_acumulado/Ciclo_acumulado

if __name__ == '__main__':
    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)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.