このとき

Download Report

Transcript このとき

3.多項式計算アルゴリズム
• べき乗の計算
• 多項式の計算
1
3-1:べき乗問題
入力: x , n
(ここで、入力サイズは、 n
す。)
n
出力: f ( x ) = x
としま
2
素朴なべき乗の求め方
• アィディア
–
を繰り返し、
x
n
回乗算する。
n
x
n
=
Õ
i= 1
x = x14442
gx gL4443
gx
n
3
アルゴリズムnaïve_pow(x,n)
入力:x,n
出力:xのn乗
初期化が重要
1. f=1.0;
2. for(i=0;i<N;i++){
3. f=f*x;
4. }
5. return f;
4
• アルゴリズムnaïve_powの正当性。
(ほとんど明らかだが、証明することもできる。)
練習
正当性を帰納法で証明するためには、どのよう
な命題を設定すればよいか?
5
アルゴリズムnaïve_powの時間計算量
• 高々 n 回の繰り返し。
• 各繰り返し中では、1回の乗算と、1回の
代入が行われているだけである。
 O (n)
の時間計算量である。
6
数学の記号とプログラム
n - 1
Õx
i = 0
n - 1
å xi
i = 0
i
1. for(i = 0 ;i < n ;i++){
2. f=f* x [i ] ;
3. }
1. for(i = 0 ;i < n ;i++){
2. f=f+ x [i ] ;
3. }
7
高速なべき乗の求め方。
• 注意
– とりあえず、入力に制限を加える
– n が2のべき乗と仮定する。すなわち、
n = 2
k
• アィディア
– 倍、倍に計算した方が高速にもとまる。
k
x gx
– (一方、
i
k
= x
x gx = x
2k
i+ 1
)
8
アルゴリズムfast_pow(x,n)
入力:x,n(ただし、 n = 2 k )
出力:xのn乗
1. f=x;
2. for(i=1;i<k;i++){
3. f=f*f;
4. }
5. return f;
9
命題FP1(fast_powの正当性)
forループが k回繰り返されたとき、
fの値は、
である。
f = x
2
k
証明 繰り返し回数kによる帰納法による。
繰り返し回数kのときのfの値を f k と表す。
基礎: k = 0
アルゴリズム中のステップ1より、
2
0
f0 = x
である。
1
= x = x
一方、右辺= x
よって、命題は成り立つ。
10
帰納: 0 < k
0 £ k ' < k なる全ての k ' に対して、
命題が成り立つと仮定する(帰納法の仮定)
k ' = k - 1 として、 k - 1 回の繰り返しで、
fk - 1 = x
2
k- 1
である。よって、 k 回めの繰り返しでは、
f k = f k - 1 gf k - 1 = x
2
k- 1
gx
2
k- 1
= x
2
k
QED
11
fast_powの時間計算量
アルゴリズムは、明らかに、k回繰り返す。
繰り返し中は、1回の乗算しか行っていない。
したがって、
O (k )
の時間計算量である。
n = 2
k
\ k = lo g 2 n
なので、結局
O ( log n )
の時間計算量である。
12
一般の自然数に対する高速な
べき乗アルゴリズム
n
が2のべき乗でないときを考える。
このとき、前の高速なべき乗アルゴリズムを
サブルーチンとして用いることができる。
n の2進数表現を次のように表す。
(n )10
m
= (bm bm - 1 L b1b0 )2
= 2 ´ bm + 2
m- 1
0
´ bm - 1 + L + 2 ´ b0
13
このとき、
x
=
n
x
m
= x
2
m
2 bm + 2
bm
(x ) g(x
m
=
は次のように表せる。
n
i
m- 1
2
0
bm - 1 + L + 2 b0
m- 1
bm -
)
1
gL g(x
1 b0
)
bi
Õ (x )
2
i= 0
これより、一般のnに対する高速なアルゴリズムが
得られる。
14
アルゴリズムgeneral_fast_pow(x,n)
入力:x,n(nは一般の数)
出力:xのn乗
1.
2.
3.
4.
5.
6.
7.
8.
f=1.0;
nを2進数 (bm bm - 1 L b1b 0 )2 に変換する。
for(i=0;i<m;i++){
if( bi = = 1 ){
f=f*fast_pow(x, 2 i );
}
}
return f;
15
3-2:多項式の計算
• 入力: x , n , a 0 , a 1 , L
• (ここで、入力サイズは、 n
す。)
• 出力:
,an
としま
f ( x ) = a 0 + a 1x + L + a n x
n
n
=
å
aix
i
i= 0
16
素朴な多項式の求め方
• アィディア
– 各項を素朴な乗算で計算し、
総和を求める。
f ( x ) = a 0 + a 1x + L + a n x
n
n
=
å
aix
i
i= 0
n
=
å
i= 0
æi ö
÷
a i ççÕ x ÷
÷
çç
÷
èj= 0 ø
17
アルゴリズムnaive_poly()
入力:x,次数n,係数a[n]
n
出力:
i
f (x ) =
1.
2.
3.
4.
5.
6.
7.
8.
9.
å
a [i ]x
i= 0
fx=0;
for(i=0;i<=N;i++){
tmp=a[i];
for(j=0;j<i;j++){
tmp=tmp*x;
}
fx=fx+tmp;
}
return fx;
3-6は、
第i項の計算
18
素朴な多項式計算アルゴリズム
の正当性
命題NP1(naive_polyの正当性1)
2.のforループが i回繰り返されたとき、
tmpの値は、
aix
i
である。
19
証明
アルゴリズム中のステップ3より、 t m p = a i に設定される。
また、4の繰り返しは明らかにi回である。
したがって、
よって、
x
はi回乗算される。
tm p = a ix
である。
i
より厳密な帰納法でも
証明できる。
QED
20
命題NP2(naive_polyの正当性2)
naïve_polyは
n
f (x ) =
å
a ix
i
i= 0
を計算する。
次数 n に関する帰納法による。
証明
基礎 n = 0
t m p = a 0 = f (x )
帰納
であり正しい。
n > 0
0£ n'< n
の時正しいと仮定する。
21
n ' = n - 1 とする。
n-1の繰り返しのときのfxの値を f n - 1 ( x )
このとき、帰納法の仮定より、
と書く。
n- 1
fn - 1 ( x ) =
å
aix
i
i= 0
が成り立つ。 n 回目の繰り返しでは、 i = n なので、
tm p = an x
n
(命題PL1より)
また、ステップ7より、
f ( x ) = fn - 1 ( x ) + t m p
æn - 1
ö
i
n
= çç å a i x ÷
+
a
x
÷
n
÷
÷
çè i = 0
ø
n
=
å
i= 0
anx
n
QED
22
素朴な多項式計算アルゴリズム
の計算時間
ステップ5の部分が最も時間を多く繰り返される。
ステップ4のforループは、i の値にしたがって、
i 回繰り返される。
よって、時間計算量を T ( n ) とすると、
T ( n ) は、次のように計算できる。
n
T (n ) =
å
i
i= 0
= 1+ 2+ 3+ L + n
=
n ( n + 1)
2
2
= O (n )
23
以上から、naive_polyの最悪時間計算量は、
2
O (n )
であることがわかる。
また、繰り返し回数は、入力サイズ(n)だけに依存し、
問題例(係数配列の状態)に依存しない。
よって、
2
Q (n )
の時間計算量を持つこともわかる。
24
補足:べき乗に高速なアルゴリ
ズムを用いた場合
n
T (n ) =
2
å (log i )
i= 0
2
2
2
£ (log 1 ) + (log 2 ) + L + (log n )
2
2
2
£ (log n ) + (log n ) + L + (log n )
(
(
= O n logn
2
))
2
と計算できるので、 O n (logn )
(
)
のアルゴリズムといえる。
(べき乗の計算に、mathライブラリのpowを用いた場合、
この計算量になると考えられる。)
25
ホーナーの方法
• アィディア
– xをできるだけくくりだしながら計算する。
f ( x ) = a 0 + a 1x + L + a n x
= (a 0 + (a 1 + (L (a n -
2
n
+ (a n ) * x ) * x ) L ) * x * x )
26
アルゴリズムを示すまえに、等式の正当性を証明する。
命題H1(hornerの正当性1)
f ( x ) = a 0 + a 1x + L + a n x
= (a 0 + (a 1 + (L (a n -
証明
fk ( x ) º a n -
+ (a n ) * x ) * x ) L ) * x * x )
2
a 0 , a 1, L , a n
n
に対して、
2
k
+ a n - k + 1x + a n - k + 2 x + L + a n x
k
k
=
å
an-
k+ i
x
i
i= 0
と定義する。
27
このとき、各関数は次のような系列になる。
f0 (x ) = a n
f1 ( x ) = a n - 1 + a n x
f2 (x ) = a n -
2
+ a n - 1x + a n x
2
M
2
f n ( x ) = a 0 + a 1x + a 2 x + L + a n x
n
= f (x )
この f k ( x ) に関して、
次式を k に関する帰納法で命題を証明する。
f k ( x ) = (a n -
k
+ (a n -
k+1
+ (L (a n -
1
+ (a n ) * x ) L ) * x ) * x )
28
基礎
k = 0
f 0 ( x ) = a n = (a n )
であり、満たされる。
帰納
k > 0
0 £ k ' < k なる全ての k ' で
k'
f k ' ( x ) = a n - k ' + a n - k ' + 1x + L + a n x
= (a n - k ' + (a n - k ' + 1 + (L (a n - 1 + (a n ) * x ) L ) * x ) * x )
と仮定する。(帰納法の仮定)
k ' = k - 1 として
k- 1
fk - 1 ( x ) = a n - k + 1 + a n - k + 2x + L + a n x
= (a n - k + 1 + (a n - k + 2 + (L (a n - 1 + (a n ) * x ) L ) * x ) * x )
29
このとき、
an-
k
+ an-
k+ 1
x + L + anx
帰納法の仮定を
用いている。
k
k- 1
= an-
k
+ (a n -
k+1
+ L + anx
= an-
k
+ (a n -
k+1
+ (L (a n - 1 + (a n ) * x ) L ) * x ) * x
= (a n -
k
+ (a n -
k+1
)*x
+ (L (a n - 1 + (a n ) * x ) L ) * x ) * x )
よって、命題は成り立つ。
QED
30
ホーナーの方法の計算手順
(a 0 + (a 1 + (L (a n - 1 + (a n ) * x ) * x ) L ) * x ) * x )
31
アルゴリズムhorner_poly()
入力:x,次数n,係数a[n]
n
出力:
i
f (x ) =
å
a [i ]x
i= 0
1. horner(int k,double x){
2. if(k==0){
3.
return a[n];
4. }else
5.
f_k=a[n-k]+horner(k1,x)*x;
6.
return f_k;
7.
}
8. }
32
ホーナーの方法の計算時間
計算時間を T ( n ) とすると次の漸化式を満たす。
ìï c 0
ï
T (n ) = í
ï c 1 + T ( n - 1) + c 2
ïïî
( n = 0)
( n > 0)
ここで、 c 1 を加算に必要な計算時間とし、
c 2 を乗算に必要な計算時間としている。
c = m a x {c 1 , c 2 } とすると、次のようにかける。
ìï c 0
ï
T (n ) £ í
ï T ( n - 1) + 2c
ïïî
( n = 0)
( n > 0)
33
T (n )
£ T ( n - 1) + 2c
£ (T ( n - 2) + 2c ) + 2c
= T ( n - 2) + 4c
M
£ T ( 0) + 2 n c
これより、
£ (c 0 + 2c ) n
T (n ) = O (n )
よって、ホーナーの方法による多項式の計算は、
線形時間アルゴリズムである。
34
ホーナーの方法の繰り返し版
ホーナーの方法は、次のように、繰り返しを用いても
実現できる。
1. horner(int k,double x){
2. double f_k=a[n];
3. for(k=1;k<=n;k++){
4.
f_k=a[N-k]+( f_k )*x;
5. }
6.
return f_k;
7. }
このアルゴリズムも明らかに線形時間で実行される。
35