#!/usr/bin/env python
# coding: utf-8
# # Table of Contents
#
#
#
#
#
# 数値計算プレ試験解答例(2015)
#
#
#
# 18/12/14 関西学院大学 西谷滋人
#
# # 数値解の収束性:25点
#
# 次の関数
# $$
# f(x)=-4\,\exp(-x)+2\,\exp(-2\, x)
# $$
# は$x=-1..0$に解$-\ln(2)$を持つ.二分法によって数値解を求めよ.繰り返しは10回程度でいい.また,収束の様子を片対数(logplot)でプロットせよ.
# In[15]:
import matplotlib.pyplot as plt
import numpy as np
def func(x):
return -4*np.exp(-x)+2*np.exp(-2*x)
x1, x2 = -1.0, 0.0
x = np.linspace(x1,x2, 101)
y = func(x)
plt.plot(x, y, color = 'k')
plt.plot([x1,x2],[0,0])
plt.grid()
plt.show()
# In[16]:
x1, x2 = -1.0, 0.0
f1, f2 = func(x1), func(x2)
print('%+15s %+15s %+15s %+15s' % ('x1','x2','f1','f2'))
print('%+15.10f %+15.10f %+15.10f %+15.10f' % (x1,x2,f1,f2))
x0 = -np.log(2.0)
list_bisec = [[0],[abs(x1-x0)]]
for i in range(0, 20):
x = (x1 + x2)/2
f = func(x)
if (f*f1>=0.0):
x1, f1 = x, f
list_bisec[0].append(i)
list_bisec[1].append(abs(x1-x0))
else:
x2, f2 = x, f
list_bisec[0].append(i)
list_bisec[1].append(abs(x2-x0))
print('%+15.10f %+15.10f %+15.10f %+15.10f' % (x1,x2,f1,f2))
list_bisec
print()
# In[17]:
import matplotlib.pyplot as plt
X = list_bisec[0]
Y = list_bisec[1]
plt.plot(X, Y)
plt.yscale("log") # y軸を対数目盛に
plt.show()
# # 丸め誤差:25点
#
# 大きな数どおしのわずかな差は,丸め誤差にとくに影響を受ける.
# 1. 23.173-23.094を有効数字がそれぞれ5桁,4桁,3桁,2桁で計算した結果を示せ.
# 1. 同様に,0.81321/(23.173-23.094)を有効数字がそれぞれ5桁,4桁,3桁,2桁で計算した結果を示せ.
#
# (E.クライツィグ著「数値解析」(培風館,2003), p.10, 問題1.1-3改)
#
# In[12]:
from decimal import *
def pretty_p(result,a,b,operator):
print('context.prec:{}'.format(getcontext().prec))
print(' %20.14f' % (a))
print( '%1s%20.14f' % (operator, b))
print('-----------')
print( ' %20.14f' % (result))
# In[14]:
getcontext().prec = 5
a=Decimal('0.81321')
b=Decimal('23.173')
c=Decimal('23.094')
pretty_p(b-c,b,c,'-')
print(b-c)
print(a/(b-c))
# In[15]:
TWOPLACES = Decimal(10) ** -2
getcontext().prec = 4
a=Decimal('0.81321').quantize(Decimal(10) ** -4)
b=Decimal('23.173').quantize(Decimal('0.01'))
c=Decimal('23.094').quantize(Decimal('0.01'))
pretty_p(b-c,b,c,'-')
print(b-c)
print(a/(b-c))
# In[16]:
ONEPLACES = Decimal(10) ** -1
getcontext().prec = 3
a=Decimal('0.81321').quantize(Decimal(10) ** -3)
b=Decimal('23.173').quantize(ONEPLACES)
c=Decimal('23.094').quantize(ONEPLACES)
pretty_p(b-c,b,c,'-')
print(b-c)
print(a/(b-c))
# In[17]:
ZEROPLACES = Decimal(10) ** 0
getcontext().prec = 2
a=Decimal('0.81321').quantize(Decimal(10) ** -2)
b=Decimal('23.173').quantize(ZEROPLACES)
c=Decimal('23.094').quantize(ZEROPLACES)
pretty_p(b-c,b,c,'-')
print(b-c)
print(a/(b-c))
# 2桁の時には0割となっている.また,3桁でも相当大きなズレが出ていることが確認できる.似た同士の数値の引き算には注意が必要.
# # Newtonの差分商公式:25点
#
# 次の4点の内挿式をNewtonの差分商公式を用いて求める.
# ``` python
# X:=[-1, 0, 1, 2];
# Y:=[4., -2., -1.2, -.52];
# ```
# 最初の3点を用いて求めた2次の補間式は,
#
# $$
# - 2.00 - 6.00\,x+ 3.40\, \left( x+1 \right) x
# $$
#
# である.4点目を取り入れて3次の補間式を求めよ.
# In[19]:
# https://stackoverflow.com/questions/14823891/newton-s-interpolating-polynomial-python
# by Khalil Al Hooti (stackoverflow)
def _poly_newton_coefficient(x,y):
"""
x: list or np array contanining x data points
y: list or np array contanining y data points
"""
m = len(x)
x = np.copy(x)
a = np.copy(y)
for k in range(1,m):
a[k:m] = (a[k:m] - a[k-1])/(x[k:m] - x[k-1])
return a
def newton_polynomial(x_data, y_data, x):
"""
x_data: data points at x
y_data: data points at y
x: evaluation point(s)
"""
a = _poly_newton_coefficient(x_data, y_data)
n = len(x_data) - 1 # Degree of polynomial
p = a[n]
for k in range(1,n+1):
p = a[n-k] + (x -x_data[n-k])*p
return p
# In[22]:
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
# もとの点
x = np.array([-1,0,1,2])
y = np.array([4,-2,-1.2,-0.52])
for i in range(0,4):
plt.plot(x[i],y[i],'o',color='r')
print(_poly_newton_coefficient(x,y))
xx = np.linspace(-1,2, 100)
yy = newton_polynomial(x, y, xx)
plt.plot(xx, yy, color = 'b')
plt.grid()
plt.show()
# Newtonの差分商公式の利点であるデータ点の追加に伴う煩雑さの回避は,このコードでは実感できない.pythonは,やっぱり便利なのかな.
# # ページランク:25点
#
# 次のようなリンクが張られたページ群のページランクを求めよ.
# In[8]:
from pprint import pprint
from numpy import array, zeros, diagflat, dot, transpose, set_printoptions
from scipy.linalg import eig
A = array([[0,1,1,1,0],
[1,0,1,0,0],
[0,0,0,1,0],
[0,0,1,0,1],
[1,1,0,0,0]])
n = 5
diag = []
for i in range(0,n):
tmp = 0.0
for j in range(0,n):
tmp += A[i,j]
diag.append(1.0/tmp)
D = diagflat(diag)
tA = dot(transpose(A),D)
set_printoptions(formatter={'float': '{: 0.3f}'.format})
pprint(tA)
# 初期ベクトルを等分の値にして,3度ほどホップさせた結果.
# In[9]:
x = array([1/5,1/5,1/5,1/5,1/5])
pprint(dot(tA,dot(tA,dot(tA,x))))
# 固有値を求める.固有値がソートされているか自信がないので,表示させてみた.
# In[10]:
l, V = eig(tA)
pprint(l)
# l[0]に対応する最大固有値のベクトルを取り出す.
# さらに,初期ベクトルからのホップと比較するために値を揃えている.
# だいたい一致しているが,ホップ数が少ないので一致はそれほど高くない.
# In[11]:
v0 = V[:,0]
pprint(v0[0]/0.294*v0)
# これより,ページランクは,
# [4, 3, 5, 1, 2]
# の順になる.
# In[14]:
get_ipython().run_line_magic('pinfo', 'eig')
# In[ ]: