294 lines
9.1 KiB
Python
294 lines
9.1 KiB
Python
import subprocess
|
|
from random import seed
|
|
import numpy as np
|
|
from mpl_toolkits.mplot3d import *
|
|
import matplotlib.pyplot as plt
|
|
from matplotlib import animation
|
|
from scipy.optimize import curve_fit
|
|
|
|
|
|
########################################################################
|
|
# General parameters
|
|
########################################################################
|
|
|
|
outfile = "test"
|
|
tmpfile = outfile+"_{0:03d}"
|
|
|
|
# xmin = -5.12
|
|
# xmax = 5.12
|
|
xmin = -3
|
|
xmax = 5
|
|
zmin = 0
|
|
zmax = 150
|
|
hres = 50
|
|
lres = 15
|
|
cnb = 20
|
|
samp_big_n = 100
|
|
gap = 50
|
|
ceil = zmax
|
|
view_alt = 32
|
|
view_angle = 105
|
|
nb_frames = 100
|
|
#nb_frames = 10
|
|
|
|
print(nb_frames,"frames")
|
|
|
|
np.random.seed(0)
|
|
|
|
def init():
|
|
########################################################################
|
|
# Plot initialization
|
|
########################################################################
|
|
|
|
fig = plt.figure(facecolor='black')
|
|
ax = fig.gca(projection='3d', axisbg="black")
|
|
ax.view_init(view_alt, view_angle)
|
|
# ax.axis('off')
|
|
|
|
# Black grid background
|
|
ax.w_xaxis.set_pane_color((0,0,0))
|
|
ax.w_yaxis.set_pane_color((0,0,0))
|
|
ax.w_zaxis.set_pane_color((0,0,0))
|
|
|
|
# Transparent axis grid lines
|
|
ax.w_xaxis._axinfo.update({'grid' : {'color': (1,1,1, 0.2)}})
|
|
ax.w_yaxis._axinfo.update({'grid' : {'color': (1,1,1, 0.2)}})
|
|
ax.w_zaxis._axinfo.update({'grid' : {'color': (1,1,1, 0.2)}})
|
|
|
|
# Transparent background:
|
|
#fig.patch.set_alpha(0.)
|
|
#ax.xaxis.set_visible(False)
|
|
#ax.yaxis.set_visible(False)
|
|
#ax.set_frame_on(False)
|
|
|
|
plt.hold(True)
|
|
|
|
return fig,ax
|
|
|
|
|
|
########################################################################
|
|
# Data grids and samples
|
|
########################################################################
|
|
|
|
# Low res grid
|
|
glx = np.arange(xmin, xmax, (xmax-xmin)/lres)
|
|
gly = np.arange(xmin, xmax, (xmax-xmin)/lres)
|
|
grid_low = np.meshgrid(glx, gly)
|
|
|
|
# Big res grid
|
|
ghx = np.arange(xmin, xmax, (xmax-xmin)/hres)
|
|
ghy = np.arange(xmin, xmax, (xmax-xmin)/hres)
|
|
grid_big = np.meshgrid(ghx, ghy)
|
|
|
|
# Big res sample
|
|
samp_big_x = np.random.random(samp_big_n)*(xmax-xmin)+xmin
|
|
samp_big_y = np.random.random(samp_big_n)*(xmax-xmin)+xmin
|
|
samp_big = (samp_big_x, samp_big_y)
|
|
|
|
|
|
########################################################################
|
|
# Fitness values
|
|
########################################################################
|
|
|
|
# "Real" problem: Rastrigin function
|
|
def rastrigin(x,y):
|
|
a=10
|
|
samp_big_n=2
|
|
return a*samp_big_n + (x*x-a*np.cos(2*np.pi*x)) + (y*y-a*np.cos(2*np.pi*y))
|
|
|
|
# "Model": a quadratic function
|
|
def sphere(x, a, b):
|
|
return a * (x[0]*x[0] + x[1]*x[1]) + b
|
|
|
|
def gauss_full(x, sx, sy, amp, b, x0, y0, ang):
|
|
a = np.cos(ang)*np.cos(ang)/2*sx*sx + np.sin(ang)*np.sin(ang)/2*sy*sy
|
|
b = -1*np.sin(2*ang)/4*sx*sx + np.sin(2*ang)/4*sy*sy
|
|
c = np.sin(ang)*np.sin(ang)/2*sx*sx + np.cos(ang)*np.cos(ang)/2*sy*sy
|
|
return amp * np.exp(-1*(a*(x[0]-x0)*(x[0]-x0) + 2*b*(x[0]-x0)*(x[1]-y0) + c*(x[1]-y0)*(x[1]-y0))) + b
|
|
|
|
def gauss_sb(x, std, b):
|
|
return -1e2 * np.exp(-1*(x[0]*x[0]/2*std*std + x[1]*x[1]/2*std*std)) + b
|
|
|
|
def gauss_sabx(x, std, amp, b, x0):
|
|
return -1*amp * np.exp(-1*((x[0]-x0[0])*(x[0]-x0[0])/2*std*std + (x[1]-x0[1])*(x[1]-x0[1])/2*std*std)) + b
|
|
|
|
|
|
# Sampled Rastrigin
|
|
samp_big_rast = rastrigin(*samp_big)
|
|
grid_big_rast = rastrigin(*grid_big)
|
|
grid_low_rast = rastrigin(*grid_low)
|
|
|
|
# Fit the quadratic model to the sample
|
|
sopt, scov = curve_fit(sphere, samp_big, samp_big_rast)
|
|
grid_big_sphr = sphere(grid_big, *sopt)
|
|
|
|
# Fit the gaussian model to the sample
|
|
gbounds = (0,[1,1e3])
|
|
guess = [0.1,1e2]
|
|
g0opt, g0cov = curve_fit(gauss_sb, samp_big, samp_big_rast, p0=guess, bounds=gbounds)
|
|
print(g0opt)
|
|
grid_big_gaus = gauss_sb(grid_big, *g0opt)
|
|
|
|
side=(xmax-xmin)/7
|
|
samp_big_zoom_x = np.random.random(samp_big_n)*side-side/2
|
|
samp_big_zoom_y = np.random.random(samp_big_n)*side-side/2
|
|
samp_big_zoom = (samp_big_zoom_x, samp_big_zoom_y)
|
|
samp_big_zoom_rast = rastrigin(*samp_big_zoom)
|
|
|
|
# Fit the gaussian model to the zoomed sample
|
|
gbounds = (0,[1e5,1e5])
|
|
guess = [1,1e2]
|
|
g1opt, g1cov = curve_fit(gauss_sb, samp_big_zoom, samp_big_zoom_rast, p0=guess, bounds=gbounds)
|
|
print(g1opt)
|
|
grid_big_gaus_zoom = gauss_sb(grid_big, *g1opt)
|
|
|
|
|
|
########################################################################
|
|
# Plot set up
|
|
########################################################################
|
|
|
|
# Plots that have their z-values manipulated during the animation
|
|
common_props = {"markeredgecolor":"none", "alpha":0.7}
|
|
first_sample = None
|
|
second_sample = None
|
|
|
|
def first_init():
|
|
|
|
# Grid Rastrigin surface
|
|
ax.plot_surface(*grid_big, grid_big_rast, alpha=0.2, color="magenta");
|
|
|
|
# Ground contour
|
|
ax.contour(*grid_low, grid_low_rast, offset=-1, colors="green")
|
|
|
|
# Optimum star
|
|
ax.scatter([0], [0], [gap], c="red", s=200, edgecolors="yellow", marker='*')
|
|
|
|
# Ground contour around optimum
|
|
ax.contour(*grid_big, grid_big_sphr, offset=-1, colors="red", levels=np.arange(0,1,0.2))
|
|
|
|
# Model 3D contour
|
|
#ls = range(0,int(np.ceil(np.max(grid_big_sphr))) +gap,int(np.ceil((np.max(grid_big_sphr) +gap)/cnb)))
|
|
#ax.contour(*grid_big, grid_big_sphr +gap, colors="#ffcc00",levels=ls)
|
|
|
|
lg0 = range(0,int(np.ceil(np.max(grid_big_gaus))) +gap,int(np.ceil((np.max(grid_big_gaus) +gap)/cnb)))
|
|
ax.contour(*grid_big, grid_big_gaus +gap, colors="#ffcc00",levels=lg0)
|
|
|
|
ax.set_zlim([zmin,zmax])
|
|
|
|
def second_init():
|
|
|
|
# Grid Rastrigin surface
|
|
ax.plot_surface(*grid_big, grid_big_rast, alpha=0.2, color="magenta");
|
|
|
|
# Ground contour
|
|
ax.contour(*grid_low, grid_low_rast, offset=-1, colors="green")
|
|
|
|
# Optimum star
|
|
ax.scatter([0], [0], [gap], c="red", s=200, edgecolors="yellow", marker='*')
|
|
|
|
# Ground contour around optimum
|
|
ax.contour(*grid_big, grid_big_sphr, offset=-1, colors="red", levels=np.arange(0,1,0.2))
|
|
|
|
# Model 3D contour
|
|
#ls = range(0,int(np.ceil(np.max(grid_big_sphr))) +gap,int(np.ceil((np.max(grid_big_sphr) +gap)/cnb)))
|
|
#ax.contour(*grid_big, grid_big_sphr +gap, colors="#ffcc00",levels=ls)
|
|
|
|
lg1 = range(0,int(np.ceil(np.max(grid_big_gaus_zoom))) +gap,int(np.ceil((np.max(grid_big_gaus_zoom) +gap)/cnb)))
|
|
ax.contour(*grid_big, grid_big_gaus_zoom +gap, colors="#ff5500",levels=lg1)
|
|
|
|
ax.set_zlim([zmin,zmax])
|
|
|
|
|
|
def sample_down(points,x,z,i,istart,iend):
|
|
n = i - istart
|
|
nmax = iend - istart
|
|
x,y = x
|
|
for j,p in enumerate(points):
|
|
p.set_data(x[j], y[j])
|
|
z_end = z[j]+gap
|
|
z_dist = ceil - z_end # Distance to ceil
|
|
z_perc = 1 - n/nmax # Remaining percentage of frames
|
|
zj = z_end + z_perc * z_dist
|
|
p.set_3d_properties(zj)
|
|
|
|
return points
|
|
|
|
|
|
def first_sample_down(artists, i, istart, iend):
|
|
#ax.scatter(*samp_big, samp_big_rast +gap, c="white", s=30, edgecolors="none")
|
|
return sample_down(artists, samp_big, samp_big_rast, i, istart, iend)
|
|
|
|
def second_sample_down(artists, i, istart, iend):
|
|
#ax.scatter(*samp_big_zoom, samp_big_zoom_rast +gap, c="#8888ff", s=30, edgecolors="none")
|
|
return sample_down(artists, samp_big_zoom, samp_big_zoom_rast, i, istart, iend)
|
|
|
|
|
|
# animation function. This will be called sequentially with the frame number
|
|
def first_animation(i):
|
|
global first_sample, second_sample
|
|
|
|
print("{}/{}".format(i,nb_frames), flush=True)
|
|
|
|
first_sample = sum([ax.plot([], [], [], 'o', c="white", **common_props) for k in range(samp_big_n)], [])
|
|
artists = first_sample_down(first_sample, i, 0, nb_frames//2)
|
|
|
|
# Rotate the view point around
|
|
#ax.view_init(view_alt, view_angle + np.degrees(i*(2*np.pi/nb_frames)))
|
|
fig.canvas.draw()
|
|
|
|
return artists
|
|
|
|
|
|
# animation function. This will be called sequentially with the frame number
|
|
def second_animation(i):
|
|
global first_sample, second_sample
|
|
|
|
print("{}/{}".format(i,nb_frames), flush=True)
|
|
|
|
second_sample = sum([ax.plot([], [], [], 'o', c="#8888ff" , **common_props) for k in range(samp_big_n)], [])
|
|
artists = second_sample_down(second_sample, i, nb_frames//2, nb_frames)
|
|
|
|
# Rotate the view point around
|
|
#ax.view_init(view_alt, view_angle + np.degrees(i*(2*np.pi/nb_frames)))
|
|
fig.canvas.draw()
|
|
|
|
return artists
|
|
|
|
|
|
# instantiate the animator.
|
|
|
|
# Save as mp4. This requires mplayer or ffmpeg to be installed
|
|
#anim.save('illuia.mp4', fps=15, extra_args=['-vcodec', 'libx264'])
|
|
|
|
#fig,ax = init()
|
|
#first_anim = animation.FuncAnimation(fig, first_animation, init_func=first_init, frames=nb_frames, interval=30)#, blit=True)
|
|
#first_anim.save('illuia_0.gif',writer='imagemagick',fps=20);
|
|
#plt.show()
|
|
#
|
|
#plt.clf()
|
|
#
|
|
#fig,ax = init()
|
|
#second_anim = animation.FuncAnimation(fig, second_animation, init_func=second_init, frames=nb_frames, interval=30)#, blit=True)
|
|
#second_anim.save('illuia_1.gif',writer='imagemagick',fps=20);
|
|
#plt.show()
|
|
|
|
|
|
fig,ax = init()
|
|
for i in range(nb_frames//2):
|
|
first_init()
|
|
first_animation(i)
|
|
fig.savefig(tmpfile.format(i)+'.png'.format(i))#, transparent = True)
|
|
ax.cla()
|
|
ax.clear()
|
|
|
|
for i in range(nb_frames//2, nb_frames):
|
|
second_init()
|
|
second_animation(i)
|
|
fig.savefig(tmpfile.format(i)+'.png'.format(i))#, transparent = True)
|
|
ax.cla()
|
|
ax.clear()
|
|
|
|
args = ["/usr/bin/convert", "-delay", "10", "-loop" , "0", "-dispose", "Background", outfile+"*.png", outfile+".gif"]
|
|
print(" ".join(args))
|
|
#subprocess.call(args, shell=True)
|
|
|