You are on page 1of 4

Mainak Samanta Homework 4

Solution 1:

1. Function to calculate natural cubic spline interpolant of any function f on [0, 1] given n (the
number of subintervals):

> require(limSolve)
> require(ggplot2)
> ncsp <- function(f, n){
+ k = 1:(n-1)
+ B = 6*n^2*(f((k+1)/n) + f((k-1)/n) - 2*f(k/n))
+ q = c(0, Solve.tridiag(rep(1, n-2), rep(4, n-1), rep(1, n-2), B), 0)
+ g <- function(x){
+ i = ceiling(replace(x, x==0, 1/n)*n)
+ o = (q[i]*(i/n - x)^3 + q[i+1]*(x - (i-1)/n)^3)*n/6
+ o = o + (n*f((i-1)/n) - q[i]/(6*n))*(i/n - x) + (n*f(i/n) - q[i+1]/(6*n))*(x - (i-1)/n)
+ return(o)
+ }
+ p <- ggplot(data.frame(x=c(0, 1)), aes(x=x)) + scale_x_continuous(breaks=0:n/n)
+ p <- p + stat_function(fun=f, colour='yellow')
+ p <- p + stat_function(fun=g, colour='black', linetype='longdash')
+ print(p)
+ }

It will plot both the function and the interpolant. We will try it on 1/(1 + x2 ) with n = 10 :

1.0

0.9

0.8
y

0.7

0.6

0.5

0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
x

Yellow is Function, Dashed Black is Natural Cubic Spline

1
Function to calculate piecewise cubic Hermite interpolant of any function f on [0, 1] given n (the
number of subintervals):

> hcsp <- function(f, df, n){


+ g <- function(x){
+ i = ceiling(replace(x, x==0, 1/n)*n)
+ o = f((i-1)/n) + df((i-1)/n)*(x - (i-1)/n)
+ o = o + (3*n^2*(f(i/n) - f((i-1)/n)) - n*(df(i/n) + 2*df((i-1)/n)))*(x - (i-1)/n)^2
+ o = o + (n^2*(df(i/n) + df((i-1)/n)) - 2*n^3*(f(i/n) - f((i-1)/n)))*(x - (i-1)/n)^3
+ return(o)
+ }
+ p <- ggplot(data.frame(x=c(0, 1)), aes(x=x)) + scale_x_continuous(breaks=0:n/n)
+ p <- p + stat_function(fun=f, colour='yellow')
+ p <- p + stat_function(fun=g, colour='black', linetype='longdash')
+ print(p)
+ }

It will plot both the function and the interpolant. We will try it on 1/(1 + x2 ) with n = 10 :

1.0

0.9

0.8
y

0.7

0.6

0.5

0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
x

Yellow is Function, Dashed Black is Natural Cubic Spline

Solution 2:

Functions to approximate the diferential using:

(i) Rectangle Rule:

2
> rect_rule <- function(f, T, x_0, n){
+ h = T/n
+ x = c(x_0, 1:n)
+ for(i in 1:n) x[i+1] = x[i] + h*f((i-1)*h, x[i])
+ return(x)
+ }

(ii) Explicit Midpoint Rule:

> expmidp_rule <- function(f, T, x_0, n){


+ h = T/n
+ x = c(x_0, 1:n)
+ for(i in 1:n) x[i+1] = x[i] + h*f((i-.5)*h, x[i] + h*f((i-1)*h, x[i])/2)
+ return(x)
+ }

(iii) Implicit Midpoint Rule:

> impmidp_rule <- function(f, dfx, T, x_0, n){


+ h = T/n
+ x = c(x_0, 1:n)
+ for(i in 1:n){
+ g <- function(y) x[i] + h*f((i-0.5)*h, (x[i] + y)/2) - y
+ dgx <- function(y) h*dfx((i-0.5)*h, (x[i] + y)/2)/2 - 1
+ x[i+1] = newton(g, dgx, x[i])
+ }
+ return(x)
+ }
> newton <- function(f, df, a, eps=1e-6){
+ if(f(a)==0) return(a)
+ b = a - f(a)/df(a)
+ while(abs(b-a)>=eps){
+ a = b
+ b = b - f(b)/df(b)
+ if(f(b)==0) return(b)
+ }
+ return((a+b)/2)
+ }

Function to and the approximate differential using the above functions and plot them vs t :

> find_diff <- function(f, dfx, T, x_0, n){


+ df <- data.frame(t = seq(0, T, T/n))
+ df$rect = rect_rule(f, T, x_0, n)

3
+ df$exmp = expmidp_rule(f, T, x_0, n)
+ df$immp = impmidp_rule(f, dfx, T, x_0, n)
+ p <- ggplot(data=df, aes(x=t)) + theme_minimal() + scale_y_continuous(name="x")
+ p <- p + scale_x_continuous(name="t", breaks=seq(0, T, T/n))
+ p <- p + geom_line(aes(y=rect), colour='blue')
+ p <- p + geom_line(aes(y=exmp), colour='red')
+ p <- p + geom_line(aes(y=immp), colour='black', linetype='longdash')
+ print(p)
+ }

Now lets try it on f (t, x) = t2 sin(x) with T = 1, x0 = 1 and n = 10:

1.3

1.2
x

1.1

1.0

0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
t

Blue - Rectangle Rule, Red - Implicit Midpoint Rule, Dashed Black - Explicit Midpoint Rule

You might also like