Say we have an unconstrained convex function \(f(x)\) that has an optimal value \(p^*\) when \(x=x^*\). If \(f(x)\) is twice differentiable we can try to use Newton’s method to find \(x\approx x^*\) through a recursive relation.

Key questions we must address

Psuedo code for Newton’s Method

Code for Newton’s Method

Now it’s time to code this thing up. Although I’m using python I will be trying to use basic structures that can be universally coded using any language.

#--------------------------------
#   Libraries
#--------------------------------
import sys
import numpy
import math
import matplotlib.pyplot as plt
#--------------------------------
#   Modules
#--------------------------------
def f(x):
  return math.log(2*math.cosh(x))

def d1_f(x):
  #---  d1_f(x) = f'(x)
  return math.tanh(x)

def d2_f(x):
  #---  d2_f(x) = f''(x)
  return (math.cosh(x)**(-1))**2

class Log:
  k=[]
  x=[]
  fp=[]#f(x)-p*
  def __init__(self,name):
    self.name = name
  def record(self,k,x,fp):
    self.k.append(k)  
    self.x.append(x)
    self.fp.append(fp)

def newton_method_pure(x0,p,kmax,e):
  #print 'Running newton_method() ...'
  log=Log('newton_method_pure')
  log.record(0,x0,f(x0)-p)
  k=1 #initialize step number
  x=x0 #initialize x
  t=1 #required for pure case
  while k<kmax:
    lamb = math.sqrt((d1_f(x)**2)/d2_f(x))
    if (lamb**2)/2 <= e:
      #print '... stopping criterion reached'
      break
    x_step = -(d1_f(x)/d2_f(x))
    x += t*x_step
    log.record(k,x,f(x)-p)
    k+=1
  return log
#--------------------------------
#   Main
#--------------------------------
if __name__ == "__main__":
    #---------------------------------
    #   Visualize functions    
    #---------------------------------
    x = [-2.+0.1*float(i) for i in range(0,40)]
    plt.plot(x,[f(y) for y in x])
    plt.plot(x,[d1_f(y) for y in x])
    plt.plot(x,[d2_f(y) for y in x])
    plt.title('functions for pure newton')
    plt.legend(['f(x)','d1_f(x)','d2_f(x)'])
    plt.show()
    plt.clf()
    #---------------------------------
    #   Run Solver
    #---------------------------------
    x0=1.0
    x_opt=0.0
    p=f(x_opt)
    kmax=10
    e=0.000001
    log=newton_method_pure(x0,p,kmax,e)
    plt.plot(log.k,log.fp)
    plt.yscale('log')
    plt.title('convergence: abs(f(x(k))-p) vs k')
    plt.show()
    plt.clf()

Analyzing our output

Changing things up


Suggested Tutorials/References