In [1]:
from bokeh.plotting import *
import bokeh
output_notebook()
import numpy as np
from numpy.linalg import norm
# Let's try on a simple function
def f(x):
return np.exp(-2.0*np.log(2)*((x-0.08)/0.854)**2)*(np.sin(5*np.pi*(x**0.75-0.05)))**6
def LineDistance( x1, x2, scale=1.0 ):
xm = 0.5*(x2+x1)
x1 = np.append(x1,scale*f(x1)) # create the base point
x2 = np.append(x2,scale*f(x2)) # the end point
xm = np.append(xm,scale*f(xm)) # the middle point
dx = (x2-x1)/norm(x2-x1) # direction of the vector
dv = np.dot(x1-xm, dx)*dx # projection to the unit vector
dv = (x1-xm) - dv # vector to projected point
return norm(dv) # norm-2
def LineAlt( x1, x2, scale=1.0 ):
xm = 0.5*(x2+x1)
sumx = ((x2-x1)**2).sum()
sumy = (scale*f(x2)-scale*f(x1))**2
sumdy = (0.5*(scale*f(x1)+scale*f(x2)) - scale*f(xm))**2
return np.sqrt(sumdy*sumx/(sumx+sumy))
def LineSimple( x1, x2 ):
eps = 1e-20
xm = 0.5*(x2+x1)
sumx = ((x2-x1)**2).sum()
sumy = (f(x2)-f(x1))**2
sumdy = (0.5*(f(x1)+f(x2)) - f(xm))**2
return np.sqrt(sumdy*sumx/(sumy+eps))
In [2]:
from bokeh.objects import HoverTool
from collections import OrderedDict
TOOLS="pan,wheel_zoom,box_zoom,reset,hover,save"
# create three 1-D points
x1 = np.array(0.1)
x2 = np.array(0.222)
x3 = np.array(0.25)
xs = np.array([x1,x2,x3])
def plot_graph(xs):
# plot them
x = np.arange(0,1,0.01)
y = f(x)
p = figure(title = 'Line Distance Example',plot_width=400, plot_height=400,
tools=TOOLS,background_fill="#ECECEC")
hold(True)
line(x,y, line_width=2)
ys = f(xs)
circle(xs,ys, radius=np.ones(xs.shape)*0.01)
line(xs,ys,color='red', line_width=3)
text([x1,x2,x3],[f(x1),f(x2),f(x3)],['x1', 'x2','x3'],angle=0,text_font_size="18pt")
xm = 0.5*(x1+x2)
line([xm,xm], [f(xm),0.5*(f(x2)+f(x1))], color='green', line_dash=[2,4], line_width=3)
hover = curplot().select(dict(type=HoverTool))
hover.tooltips = OrderedDict([
("x", "$x"),
("f(x)", "$y")])
hold(False)
p.ygrid.grid_line_color = "white"
p.ygrid.grid_line_width = 2
p.xgrid.grid_line_color = "white"
p.xgrid.grid_line_width = 2
p.axis.major_label_text_font_size = "18pt"
p.axis.major_label_text_font_style = "bold"
show()
# print the Line Distance
print("LD(x1,x2) = ", LineDistance(x1,x2), LineAlt(x1,x2), LineAlt(x1,x2, 100000), LineSimple(x1,x2))
print("LD(x1,x3) = ", LineDistance(x1,x3), LineAlt(x1,x3), LineAlt(x1,x3, 100000), LineSimple(x1,x3))
print("LD(x3,x2) = ", LineDistance(x3,x2), LineAlt(x3,x2), LineAlt(x3,x2, 100000), LineSimple(x3,x2))
plot_graph(xs)
In [3]:
# second case example of Local Optima Analysis
x1 = np.array(0.31)
x2 = np.array(0.491)
print("LD(x1,x2) = ", LineSimple(x1,x2))
xs = np.array([x1,x2,(x1+x2)/2])
plot_graph(xs)
In [4]:
# optimize alpha
from scipy.optimize import minimize_scalar, curve_fit
from ipywidgets import StaticInteract, RangeWidget
from IPython.html.widgets import interact
def optInteract(x=0.22, r=0.1):
x = np.array(x)
maxf = lambda alpha: -LineSimple(x,x+alpha)
alpha = minimize_scalar(maxf, bounds=(0.0001,r),method='bounded').x # define a closed interval comprising one optima
print("alpha = {alpha}, x+alpha = {x2}, LS(x1,x2) = {ls}, f(xm) = {ym}".format(
alpha=alpha, x2=x+alpha, ls = -maxf(alpha), ym = f((2*x+alpha)/2)))
# plot them
xs = np.array([x,x+alpha,(2*x+alpha)/2])
plot_graph(xs)
interact(optInteract, x=(0.01, 0.9, 0.1),r=(0.1,0.3,0.1))
In [ ]: