platypusで多目的GA


platypusライブラリが使い勝手良さそうだったので試してみます。ただ途中過程を出力できないのが微妙です。

preparation

!conda install platypus-opt -y
from IPython.display import HTML

HTML('''
<script>  
code_show=true; 
function code_toggle() {
  if (code_show){
    $(\'div.input\').hide();
  } else {
    $(\'div.input\').show();
  }
  code_show = !code_show
}  
$( document ).ready(code_toggle);
</script>
<form action="javascript:code_toggle()">
    <input type="submit" value="Toggle code">
</form>
''')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
plt.rcParams['font.size']=15

def plt_legend_out(frameon=True):
    plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0, frameon=frameon)

拘束条件なし

$f_1(x)$と$f_2(x)$が最小になる条件を探索します。

x = np.linspace(-10,10,100)
f1 = x**2
f2 = (x-2)**2

fig, ax = plt.subplots(figsize=[5, 4])

ax.plot(x,f1,label='$f_1(x)$')
ax.plot(x,f2,label='$f_2(x)$')
ax.axvline(1,color='k',ls='dashed',lw=0.8,label='$f_1(x)=f_2(x)=1$')
ax.axhline(1,color='k',ls='dashed',lw=0.8)
ax.set_xlabel('$x$')
ax.set_ylabel('$f(x)$')
plt_legend_out()

axins = ax.inset_axes([0.5, 0.5, 0.47, 0.47])
axins.plot(x,f1)
axins.plot(x,f2)
axins.axvline(1,color='k',ls='dashed',lw=0.8)
axins.axhline(1,color='k',ls='dashed',lw=0.8)
axins.set_xlim(-0.5,2.5)
axins.set_ylim(-0.5,3.5)
axins.set_xticklabels('')
axins.set_yticklabels('')

ax.indicate_inset_zoom(axins)

plt.show()

fig, ax = plt.subplots(figsize=[5, 4])

ax.plot(f1,f2,color='k')
ax.axvline(1,color='k',ls='dashed',lw=0.8,label='$f_1(x)=f_2(x)=1$')
ax.axhline(1,color='k',ls='dashed',lw=0.8)
ax.set_xlabel('$f_1(x)$')
ax.set_ylabel('$f_2(x)$')
plt_legend_out()

axins = ax.inset_axes([0.5, 0.5, 0.47, 0.47])
axins.plot(f1,f2,color='k')
axins.axvline(1,color='k',ls='dashed',lw=0.8)
axins.axhline(1,color='k',ls='dashed',lw=0.8)
x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9
axins.set_xlim(-0.5,4)
axins.set_ylim(-0.5,4)
axins.set_xticklabels('')
axins.set_yticklabels('')

ax.indicate_inset_zoom(axins)

plt.show()

fig, ax = plt.subplots(figsize=[5, 4])

ax.plot(f1+f2,color='k')
ax.axhline(2,color='k',ls='dashed',lw=0.8,label='$f_1(x)+f_2(x)=2$')
ax.set_xlabel('index')
ax.set_ylabel('$f_1(x)+f_2(x)$')
plt_legend_out()

axins = ax.inset_axes([0.5, 0.5, 0.47, 0.47])
axins.plot(f1+f2,color='k')
axins.axhline(2,color='k',ls='dashed',lw=0.8)
axins.set_xlim(48,60)
axins.set_ylim(1,4)
axins.set_xticklabels('')
axins.set_yticklabels('')

ax.indicate_inset_zoom(axins)

plt.show()

from platypus import NSGAII, Problem, Real

def schaffer(x):
    return [x[0]**2, (x[0]-2)**2]

problem = Problem(1, 2)
problem.types[:] = Real(-10, 10)
problem.function = schaffer

algorithm = NSGAII(problem)
algorithm.run(10000)
plt.scatter([s.objectives[0] for s in algorithm.result],
            [s.objectives[1] for s in algorithm.result],color='k',s=3)
plt.xlabel("$f_1(x)$")
plt.ylabel("$f_2(x)$")
plt.axvline(1,color='k',ls='dashed',lw=0.8)
plt.axhline(1,color='k',ls='dashed',lw=0.8)
plt.show()

拘束条件あり

$f_1(x_1,x_2)$と$f_2(x_1,x_2)$が最小になる条件を探索します。拘束条件も2つ設定します。

from mpl_toolkits import mplot3d
fig = plt.figure()
ax = plt.axes(projection='3d')

x1 = np.linspace(0,5,100)
x2 = np.linspace(0,3,100)

X1,X2 = np.meshgrid(x1,x2)
f = -2*X1 + X2
ax.plot_surface(X1, X2, f,cmap='Reds')

f = 2*X1 + X2
ax.plot_surface(X1, X2, f,cmap='Blues')

#ax.plot_surface(X, Y, Y-X-1, cmap='Greys')
#ax.plot_surface(X, Y, X+Y-7, cmap='Greys')

ax.set_xlabel('$x_1$')
ax.set_ylabel('$x_2$')
ax.set_zlabel('$f(x_1,x_2)$')

#ax.view_init(0, 360)

plt.tight_layout()
plt.show()

def belegundu(vars):
    x1 = vars[0]
    x2 = vars[1]
    return [-2*x1 + x2, 2*x1 + x2], [-x1 + x2 - 1, x1 + x2 - 7]

problem = Problem(2, 2, 2)
problem.types[:] = [Real(0, 5), Real(0, 3)]
problem.constraints[:] = "<=0"
problem.function = belegundu

algorithm = NSGAII(problem)
algorithm.run(10000)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter([s.variables[0]  for s in algorithm.result],
           [s.variables[1]  for s in algorithm.result],
           [s.objectives[0] for s in algorithm.result],label='$f_1(x_1,x_2)$')
ax.scatter([s.variables[0]  for s in algorithm.result],
           [s.variables[1]  for s in algorithm.result],
           [s.objectives[1] for s in algorithm.result],label='$f_2(x_1,x_2)$')
ax.set_xlabel('$x_1$')
ax.set_ylabel('$x_2$')
ax.set_zlabel('$f(x_1,x_2)$')
plt.legend()
plt.tight_layout()
plt.show()

plt.scatter([s.objectives[0] for s in algorithm.result],
            [s.objectives[1] for s in algorithm.result],color='k',s=3)
plt.xlabel("$f_1(x_1,x_2)$")
plt.ylabel("$f_2(x_1,x_2)$")
#plt.axvline(1,color='k',ls='dashed',lw=0.8)
#plt.axhline(1,color='k',ls='dashed',lw=0.8)
plt.show()

reference