가장 쉬운 차등 진화 (differential evolution) [python 3] by 바죠


가장 쉬운 차등 진화 (differential evolution) [python 3]



다차원의 연속변수들을 독립변수로 산정한다. 유전 알고리듬과 사실상 동일 부류의 최적화 알고리듬이다.
유전 알고리듬에서 보다 더 기계적인 변이/교차 연산자를 활용한다.
이것으로 해당 컴퓨터 프로그램이 간단하게 된다.
목적함수를 최소화한다.
연속변수들을 활용하고 있기 때문에 가능하면 국소 최소화 알고리듬을 활용한다.

파이썬 리스트를 이용한다. 
동일한 형식으로 정의된 객체를 다수 만들고 파이썬 리스트 항목으로 저장할 수 있다. 
그런데 객체가 클래스로 정의 된 것이 될 수도 있다. 파이썬 리스트는 매우 포괄적인 것을 하나의 항목으로 인정한다.
먼저 PARTICLE이라는 객체를 정의한다. [입자 하나에 대한 많은 정보를 가지고 있다. 위치, 속도, 목적함수 값, 역대 최적값, 역대 최적 위치] [입자마다 고유의 특성이 다를 수 있다.]
이것들로 구성된 또 다른 종류의 객체를 정의한다. [입자들로 구성된 무리를 정의한다.]
import random
from scipy.optimize import minimize
import numpy as np
def functuser(x):
    case=3

    if case == 1:
       total=0.
       for j in range(len(x)):
           total+=(x[j])**2
    if case == 2:
#    Rastrigin
       total=10.*len(x)
       for j in range(len(x)):
           total+=x[j]**2-10.*np.cos(2.*np.pi*x[j])
    if case == 3:
#   Rosenbrock
       xarray0=np.zeros(len(x))
       for j in range(len(x)):
          xarray0[j]=x[j]
       total=sum(100.0*(xarray0[1:]-xarray0[:-1]**2.0)**2.0 + (1-xarray0[:-1])**2.0)
    if case == 4:
#   Styblinski-Tang
       total=0.
       for j in range(len(x)):
           total+=(x[j]**4-16.*x[j]**2+5.*x[j])/2.

    return total
class PARTICLE:
    def __init__(self,startx0,ptbmp,pccrr,ff,xbounds,lverbo):
        self.position_i=[]
        self.position_best_i=[]
        self.obj_best_i=9e99
        self.obj_i=9e99
        self.dimensions=len(startx0)
        self.ptbmp=ptbmp+(random.random()-0.5)*0.2
        self.pccrr=pccrr+(random.random()-0.5)*0.2
        self.ff=ff+(random.random()-0.5)*0.2
        if self.pccrr > 0.999 or self.pccrr < 0.001:
           self.pccrr=random.random()
        if self.ff > 1.999 or self.ff < 0.001:
           self.ff=random.random()*2.
        if lverbo:
           print(self.ptbmp,self.pccrr,self.ff)
        for j in range(self.dimensions):
            self.position_i.append(startx0[j]*(1.+(random.random()-0.5)*2.*ptbmp))
        if random.random() < 0.8:
           for j in range(self.dimensions):
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
        for j in range(self.dimensions):
            if self.position_i[j] > xbounds[j][1]:
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
            if self.position_i[j] < xbounds[j][0]:
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
        self.position_best_i=self.position_i.copy()
    def evaluate(self,objfunct):
#       self.obj_i=objfunct(self.position_i)
        xarray0=np.zeros(self.dimensions)
        for j in range(self.dimensions):
            xarray0[j]=self.position_i[j]
        res=minimize(objfunct,xarray0,method='nelder-mead',options={'xtol':1e-6,'disp':True})
        self.position_i=res.x.copy()
        self.obj_i=res.fun
        if self.obj_i < self.obj_best_i :
           self.position_best_i=self.position_i.copy()
           self.obj_best_i=self.obj_i
    def update_mutationcrossover(self,x1vec,x2vec,x3vec,ff):
        ir=int(random.random()*self.dimensions)
        for j in range(self.dimensions):
            if random.random() < self.pccrr or j == ir:
               self.position_i[j]=x1vec[j]+ff*(x2vec[j]-x3vec[j])
            else:
               self.position_i[j]=self.position_best_i[j]
    def update_position(self,xbounds):
        for j in range(self.dimensions):
            if self.position_i[j] > xbounds[j][1]:
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
            if self.position_i[j] < xbounds[j][0]:
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
class DE():
    def __init__(self, objfunct, startx0, xbounds, ptbmp=1.1, pccrr=0.5, ff=1.0, nparticles=50, maxiter=50000, verbose=False):
        obj_best_g=9e99
        position_best_g=[]
        swarm=[]
        x1vec=[]
        x2vec=[]
        x3vec=[]
        for _ in range(nparticles):
            swarm.append(PARTICLE(startx0,ptbmp,pccrr,ff,xbounds,verbose))
        it=0
        while it < maxiter:
            if verbose:
               print(f'iter: {it:>6d} best solution: {obj_best_g:16.8e}')
            for i in range(nparticles):
                swarm[i].evaluate(objfunct)
                if swarm[i].obj_i < obj_best_g :
                   position_best_g=list(swarm[i].position_i)
                   obj_best_g=float(swarm[i].obj_i)
            for i in range(nparticles):
                while True:
                   i1=int(random.random()*nparticles)
                   i2=int(random.random()*nparticles)
                   i3=int(random.random()*nparticles)
                   if i1 == i :
                      continue
                   if i2 == i :
                      continue
                   if i3 == i :
                      continue
                   if i1 != i2 and i2 != i3 and i3 != i1:
                      break
                x1vec=list(swarm[i1].position_best_i)
                x2vec=list(swarm[i2].position_best_i)
                x3vec=list(swarm[i3].position_best_i)
                swarm[i].update_mutationcrossover(x1vec,x2vec,x3vec,ff)
                swarm[i].update_position(xbounds)
            it+=1
        print('\nfinal solution:')
        print(f'   > {position_best_g}')
        print(f'   > {obj_best_g}\n')
        if True:
           abc=np.zeros(nparticles)
           abcvec=np.zeros((nparticles,len(startx0)))
           for i in range(nparticles):
               abc[i]=swarm[i].obj_best_i
               abcvec[i]=swarm[i].position_best_i
           idx=abc.argsort()
           abc=abc[idx]
           abcvec=abcvec[idx,:]
           for i in range(nparticles):
               print(abc[i])
               print(abcvec[i,:])

startx0=[]
xbounds=[]
for j in range(10):
    startx0.append(0.)
for j in range(len(startx0)):
    xbounds.append((-20., 20.))
DE(functuser, startx0, xbounds, ptbmp=1.1, pccrr=0.5, ff=1.0, nparticles=50, maxiter=50000, verbose=True)



---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

# differential evolution global optimization for the ackley multimodal objective function
from scipy.optimize import differential_evolution
from numpy.random import rand
from numpy import exp
from numpy import sqrt
from numpy import cos
from numpy import e
from numpy import pi

# objective function
def objective(v):
    x, y = v
    return -20.0 * exp(-0.2 * sqrt(0.5 * (x**2 + y**2))) - exp(0.5 * (cos(2 * pi * x) + cos(2 * pi * y))) + e + 20

# define range for input
r_min, r_max = -5.0, 5.0
# define the bounds on the search
bounds = [[r_min, r_max], [r_min, r_max]]
# perform the differential evolution search
result = differential_evolution(objective, bounds)
# summarize the result
print('Status : %s' % result['message'])
print('Total Evaluations: %d' % result['nfev'])
# evaluate solution
solution = result['x']
evaluation = objective(solution)
print('Solution: f(%s) = %.5f' % (solution, evaluation))

---------------------------------------------------------------------------------------------------------------------


import numpy as np
import os
import os.path
from scipy.optimize import dual_annealing
from scipy.optimize import minimize
from scipy import optimize
def append_new_line(file_name, text_to_append):
    with open(file_name, "a+") as file_object:
        file_object.seek(0)
        data = file_object.read(100)
        if len(data) > 0:
            file_object.write("\n")
        file_object.write(text_to_append)
def append_multiple_lines(file_name, lines_to_append):
    with open(file_name, "a+") as file_object:
        appendEOL = False
        file_object.seek(0)
        data = file_object.read(100)
        if len(data) > 0:
            appendEOL = True
        for line in lines_to_append:
            if appendEOL == True:
                file_object.write("\n")
            else:
                appendEOL = True
            file_object.write(line)

lw = [-15.0] * 10
up = [15.0] * 10
if True:
   ret = dual_annealing(func, bounds=list(zip(lw, up)), seed=1234, maxiter=20)
if False:
   ret=optimize.differential_evolution(func, bounds=list(zip(lw, up)), maxiter=10)
if False:
   x0=[ 0. for i in range(10)]
   ret = minimize(func, x0, method='Nelder-Mead', tol=1e-6)
lines=[]
lines.append(str(ret.fun))
for i in range(len(ret.x)):
    lines.append(str(ret.x[i]))
append_multiple_lines('./OUTPUT', lines)


---------------------------------------------------------------------------------------------------------------------


핑백

덧글

댓글 입력 영역

최근 포토로그



MathJax