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))


BokehJS successfully loaded.

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)


('LD(x1,x2) = ', 0.55551125612930519, 0.55551125612930519, 7.659861839658392, 7.6598619120948079)
('LD(x1,x3) = ', 0.27002371718741464, 0.27002371718741464, 0.28977486433891453, 0.28977486434111166)
('LD(x3,x2) = ', 0.0086935268352529918, 0.0086935268352529762, 0.0087175570503933517, 0.0087175570503957613)

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)


('LD(x1,x2) = ', 0.0032520716010061915)

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))


alpha = 0.074047193961, x+alpha = 0.284047193961, LS(x1,x2) = 4344.20522352, f(xm) = 0.948246891268

In [ ]: