import sympy as sym
import numpy as np
import matplotlib.pyplot as pp
import IPython.display as ipd
import scipy.interpolate as sci
import scipy.linalg
def show_expr( expr, reps = [ "_{i}", "_{i + 1}", "_{i + 2}", "_{i + 3}", "_{i + 4}" ] ):
ltx = sym.latex( expr )
for i in range( len( reps ) ):
ltx = ltx.replace( "_{%i}" % ( i, ), reps[ i ] )
ipd.display(
ipd.Math(
ltx
)
)
# Ordem da spline:
k = 3
# Vamos criar as variáveis simbólicas:
( x, x_i, h_i, y_i, v_i ) = sym.symbols( 'x, x_0, h_0, y_0, v_0' )
# Coeficientes dos polinômios
As = []
for i in range( k ):
As.append( [] )
for j in range( k + 1 ):
As[ i ].append( sym.symbols( '%c' % ( chr( 65 + j ), ) + '_%i' % ( i, ) ) )
Ps = [ 0, 0 ]
for j in range( len( As[ 0 ] ) ):
Ps[ 0 ] += As[ 0 ][ j ] * ( ( x - x_i ) ** j )
Ps[ 1 ] += As[ 1 ][ j ] * ( ( x - ( x_i + h_i ) ) ** j )
interp = [
sym.Equality( Ps[ 0 ].subs( x, x_i ), y_i ),
sym.Equality( Ps[ 1 ].subs( x, x_i + h_i ), y_i + v_i )
]
for eq in interp:
show_expr( eq )
conti = []
for j in range( k ):
conti.append(
sym.Equality(
Ps[ 0 ].diff( x, j ).subs( x, x_i + h_i ),
Ps[ 1 ].diff( x, j ).subs( x, x_i + h_i )
)
)
for eq in conti:
show_expr( eq )
tmp = conti[ 0 ]
tmp = sym.Equality(
tmp.lhs - As[ 0 ][ 0 ],
tmp.rhs - As[ 0 ][ 0 ]
)
tmp = tmp.subs( interp[ 0 ].lhs, interp[ 0 ].rhs )
tmp = tmp.subs( interp[ 1 ].lhs, interp[ 1 ].rhs )
tmp = sym.Equality(
tmp.lhs / h_i,
tmp.rhs / h_i
).expand()
conti[ 0 ] = tmp
for eq in conti:
show_expr( eq )
alpha = conti[ 0 ].lhs.coeff( As[ 0 ][ 3 ] ) / \
conti[ 1 ].lhs.coeff( As[ 0 ][ 3 ] )
EqC = sym.Equality(
conti[ 0 ].lhs - alpha * conti[ 1 ].lhs,
conti[ 0 ].rhs - alpha * conti[ 1 ].rhs
)
EqC = sym.Equality(
EqC.lhs * 3 / h_i,
EqC.rhs * 3 / h_i
).expand()
EqC = sym.Equality(
EqC.lhs - ( EqC.lhs - As[ 0 ][ 2 ] ),
EqC.rhs - ( EqC.lhs - As[ 0 ][ 2 ] )
)
show_expr( EqC )
alpha = conti[ 0 ].lhs.coeff( As[ 0 ][ 2 ] ) / \
conti[ 1 ].lhs.coeff( As[ 0 ][ 2 ] )
EqD = sym.Equality(
conti[ 0 ].lhs - alpha * conti[ 1 ].lhs,
conti[ 0 ].rhs - alpha * conti[ 1 ].rhs
)
EqD = sym.Equality(
EqD.lhs * -2 / ( h_i ** 2 ),
EqD.rhs * -2 / ( h_i ** 2 )
).expand()
EqD = sym.Equality(
EqD.lhs - ( EqD.lhs - As[ 0 ][ 3 ] ),
EqD.rhs - ( EqD.lhs - As[ 0 ][ 3 ] )
)
show_expr( EqD )
EqCNext = EqC.subs( As[ 1 ][ 1 ], As[ 2 ][ 1 ] )\
.subs( As[ 0 ][ 1 ], As[ 1 ][ 1 ] )\
.subs( As[ 0 ][ 2 ], As[ 1 ][ 2 ] )\
.subs( h_i, sym.symbols( 'h_1' ) )\
.subs( v_i, sym.symbols( 'v_1' ) )
show_expr( EqC )
show_expr( EqCNext )
show_expr( EqD )
show_expr( conti[ -1 ] )
EqB = conti[ -1 ].subs( EqC.lhs, EqC.rhs )\
.subs( EqCNext.lhs, EqCNext.rhs )\
.subs( EqD.lhs, EqD.rhs )\
.expand()
EqB = sym.Equality(
EqB.lhs + 4 * As[ 1 ][ 1 ] / sym.symbols( 'h_1' ),
EqB.rhs + 4 * As[ 1 ][ 1 ] / sym.symbols( 'h_1' )
)
EqB = sym.Equality(
EqB.lhs + 2 * As[ 2 ][ 1 ] / sym.symbols( 'h_1' ),
EqB.rhs + 2 * As[ 2 ][ 1 ] / sym.symbols( 'h_1' )
)
EqB = sym.Equality(
EqB.lhs + 6 * v_i / ( h_i ** 2 ),
EqB.rhs + 6 * v_i / ( h_i ** 2 )
)
EqB = sym.Equality(
EqB.lhs / 2,
EqB.rhs / 2
)
EqB = sym.Equality(
EqB.lhs.collect( As[ 1 ][ 1 ] ),
EqB.rhs
)
show_expr( conti[ -1 ] )
show_expr( EqB )
$$ \begin{pmatrix} \displaystyle\frac 1{h_0} & \displaystyle\frac2{h_0} + \displaystyle\frac2{h_1} & \displaystyle\frac1{h_1}\\ \\ & \displaystyle\frac 1{h_1} & \displaystyle\frac2{h_1} + \displaystyle\frac2{h_2} & \displaystyle\frac1{h_2}\\ \\ && \displaystyle\frac 1{h_2} & \displaystyle\frac2{h_2} + \displaystyle\frac2{h_3} & \displaystyle\frac1{h_3}\\ \\ &&\qquad\ddots&\qquad\ddots & \qquad\ddots\\ \\ &&& \displaystyle\frac 1{h_{n - 2}} & \displaystyle\frac2{h_{n - 2}} + \displaystyle\frac2{h_{n - 1}} & \displaystyle\frac1{h_{n - 1}} \end{pmatrix} \begin{pmatrix} B_0\\ B_1\\ B_2\\ \vdots\\ B_n \end{pmatrix} = \begin{pmatrix} \displaystyle\frac{3v_0}{h_0^2} + \displaystyle\frac{3v_1}{h_1^2}\\ \\ \displaystyle\frac{3v_1}{h_1^2} + \displaystyle\frac{3v_2}{h_2^2}\\ \\ \vdots\\ \\ \displaystyle\frac{3v_{n - 2}}{h_{n - 2}^2} + \displaystyle\frac{3v_{n - 1}}{h_{n - 1}^2} \end{pmatrix} $$
EqNE = sym.Equality(
-Ps[ 0 ].diff( x, 2 ).subs( x, x_i ) + 6 * v_i / h_i ** 2,
+ 6 * v_i / h_i ** 2
).subs( EqC.lhs, EqC.rhs )
show_expr( EqNE, [] )
$$ \begin{pmatrix} \displaystyle\frac 4{h_0} & \displaystyle\frac2{h_0}\\ \\ \displaystyle\frac 1{h_0} & \displaystyle\frac2{h_0} + \displaystyle\frac2{h_1} & \displaystyle\frac1{h_1}\\ \\ & \displaystyle\frac 1{h_1} & \displaystyle\frac2{h_1} + \displaystyle\frac2{h_2} & \displaystyle\frac1{h_2}\\ \\ && \displaystyle\frac 1{h_2} & \displaystyle\frac2{h_2} + \displaystyle\frac2{h_3} & \displaystyle\frac1{h_3}\\ \\ &&\qquad\ddots&\qquad\ddots & \qquad\ddots\\ \\ &&& \displaystyle\frac 1{h_{n - 2}} & \displaystyle\frac2{h_{n - 2}} + \displaystyle\frac2{h_{n - 1}} & \displaystyle\frac1{h_{n - 1}} \end{pmatrix} \begin{pmatrix} B_0\\ B_1\\ B_2\\ \vdots\\ B_n \end{pmatrix} = \begin{pmatrix} \displaystyle\frac{6v_0}{h_0^2}\\ \\ \displaystyle\frac{3v_0}{h_0^2} + \displaystyle\frac{3v_1}{h_1^2}\\ \\ \displaystyle\frac{3v_1}{h_1^2} + \displaystyle\frac{3v_2}{h_2^2}\\ \\ \vdots\\ \\ \displaystyle\frac{3v_{n - 2}}{h_{n - 2}^2} + \displaystyle\frac{3v_{n - 1}}{h_{n - 1}^2} \end{pmatrix} $$
EqND = sym.Equality(
Ps[ 0 ].diff( x, 2 ).subs( x, x_i + h_i ) + 6 * v_i / h_i ** 2,
+ 6 * v_i / h_i ** 2
).subs( EqC.lhs, EqC.rhs ).subs( EqD.lhs, EqD.rhs )
EqND = sym.Equality(
EqND.lhs.expand(),
EqND.rhs
)
show_expr( EqND, [ '_{n - 1}', '_{n}' ] )
$$ \begin{pmatrix} \displaystyle\frac 4{h_0} & \displaystyle\frac2{h_0}\\ \\ \displaystyle\frac 1{h_0} & \displaystyle\frac2{h_0} + \displaystyle\frac2{h_1} & \displaystyle\frac1{h_1}\\ \\ & \displaystyle\frac 1{h_1} & \displaystyle\frac2{h_1} + \displaystyle\frac2{h_2} & \displaystyle\frac1{h_2}\\ \\ && \displaystyle\frac 1{h_2} & \displaystyle\frac2{h_2} + \displaystyle\frac2{h_3} & \displaystyle\frac1{h_3}\\ \\ &&\qquad\ddots&\qquad\ddots & \qquad\ddots\\ \\ &&& \displaystyle\frac 1{h_{n - 2}} & \displaystyle\frac2{h_{n - 2}} + \displaystyle\frac2{h_{n - 1}} & \displaystyle\frac1{h_{n - 1}}\\ \\ &&&& \displaystyle\frac 2{h_{n - 1}} & \displaystyle\frac 4{h_{n - 1}} \end{pmatrix} \begin{pmatrix} B_0\\ B_1\\ B_2\\ \vdots\\ B_n \end{pmatrix} = \begin{pmatrix} \displaystyle\frac{6v_0}{h_0^2}\\ \\ \displaystyle\frac{3v_0}{h_0^2} + \displaystyle\frac{3v_1}{h_1^2}\\ \\ \displaystyle\frac{3v_1}{h_1^2} + \displaystyle\frac{3v_2}{h_2^2}\\ \\ \vdots\\ \\ \displaystyle\frac{3v_{n - 2}}{h_{n - 2}^2} + \displaystyle\frac{3v_{n - 1}}{h_{n - 1}^2}\\ \\ \displaystyle\frac{6v_{n - 1}}{h_{n - 1}^2} \end{pmatrix} $$
x_nodes = np.linspace( -6.0, 6.0, 8 )
y_nodes = np.sin( x_nodes )
cs = sci.CubicSpline( x_nodes, y_nodes, bc_type = 'natural' )
# cs = sci.CubicSpline( x_nodes, y_nodes, bc_type = ( ( 2, 0.0 ), ( 2, 0.0 ) ) )
pp.figure( figsize = ( 12, 8 ) )
x_plot = np.linspace( -6.0, 6.0, 500 )
pp.plot( x_plot, np.sin( x_plot ) )
pp.plot( x_plot, cs( x_plot ) )
pp.show()
err = []
n_points = []
a = -1.0
b = 1.0
def runge( x ):
return np.exp( -np.abs( x ) )
# return 1.0 / ( 1.0 + 25.0 * ( x ** 2 ) )
x_eval = np.linspace( a, b, 500 )
runge_x_eval = runge( x_eval )
for n in range( 7, 50 ):
x_nodes = np.linspace( a, b, n )
y_nodes = runge( x_nodes )
cs = sci.CubicSpline( x_nodes, y_nodes, bc_type = 'natural' )
cs_x_eval = cs( x_eval )
curr_err = np.max( np.abs( cs_x_eval - runge_x_eval ) )
err.append( curr_err )
n_points.append( n )
pp.plot( n_points, err )
$$ \epsilon_n \approx C h^q = \frac C{n^q} $$
$$ \log \epsilon_n \approx \log C - q\log n $$
def q_estimate( n_points, err ):
n_points = np.array( n_points, dtype = 'float' )
err = np.array( err )
y = np.log( err )
A = np.empty( ( len( n_points ), 2 ) )
A[ :, 0 ] = 1.0
A[ :, 1 ] = np.log( n_points )
AA = np.dot( A.T, A )
b = np.dot( A.T, y )
x = np.linalg.solve( AA, b )
return -x[ 1 ]
print( q_estimate( n_points[ 0 : : 2 ], err[ 0 : : 2 ] ) )
print( n_points[ 0 : : 2 ] )
pp.figure( figsize = ( 12, 8 ) )
x_plot = np.linspace( a, b, 500 )
pp.plot( x_plot, runge( x_plot ) )
pp.plot( x_plot, cs( x_plot ) )
pp.show()
def cs_rep( x_nodes, y_nodes ):
x = np.array( x_nodes )
y = np.array( y_nodes )
h = x[ 1 : ] - x[ : -1 ]
v = y[ 1 : ] - y[ : -1 ]
b = np.empty( ( len( x ) ) )
b[ 0 ] = 6.0 * v[ 0 ] / ( h[ 0 ] ** 2 )
b[ -1 ] = 6.0 * v[ -1 ] / ( h[ -1 ] ** 2 )
h2 = h ** 2
tmp = v / h2
b[ 1 : -1 ] = 3.0 * ( tmp[ : -1 ] + tmp[ 1 : ] )
M = np.empty( ( 3, len( x ) ) )
M[ 1, 0 ] = 4.0 / h[ 0 ]
M[ 2, 0 ] = 1.0 / h[ 0 ]
for i in range( 1, len( x ) - 1 ):
M[ 0, i ] = 1.0 / h[ i - 1 ]
M[ 1, i ] = 2.0 / h[ i - 1 ] + 2.0 / h[ i ]
M[ 2, i ] = 1.0 / h[ i ]
M[ 0, 1 ] += 1.0 / h[ 0 ]
M[ -1, -2 ] += 1.0 / h[ -1 ]
M[ 0, -1 ] = 1.0 / h[ -1 ]
M[ 1, -1 ] = 4.0 / h[ -1 ]
B = scipy.linalg.solve_banded( ( 1, 1 ), M, b )
C = -( 2.0 * B[ : -1 ] + B[ 1 : ] ) / h + 3.0 * v / h2
D = ( B[ : -1 ] + B[ 1 : ] ) / h2 - 2.0 * v / ( h ** 3 )
return ( x, y, B, C, D )
def cs_eval( rep, x ):
# Índice do polinômio atual:
i = 0
y = []
for j in range( len( x ) ):
while ( x[ j ] >= rep[ 0 ][ i ] ) and ( i < len( rep[ 0 ] ) - 1 ):
i += 1
i -= 1
if ( i < 0 ):
i = 0
h = x[ j ] - rep[ 0 ][ i ]
tmp = rep[ 4 ][ i ]
tmp = h * tmp + rep[ 3 ][ i ]
tmp = h * tmp + rep[ 2 ][ i ]
tmp = h * tmp + rep[ 1 ][ i ]
y.append( tmp )
return np.array( y )
x_nodes = np.linspace( -6.0, 6.0, 8 )
y_nodes = np.sin( x_nodes )
rep = cs_rep( x_nodes, y_nodes )
cs = sci.CubicSpline( x_nodes, y_nodes, bc_type = 'natural' )
pp.figure( figsize = ( 12, 8 ) )
x_plot = np.linspace( -6.0, 6.0, 500 )
pp.plot( x_plot, np.sin( x_plot ) )
pp.plot( x_plot, cs( x_plot ) )
pp.plot( x_plot, cs_eval( rep, x_plot ) )
pp.show()