アルゴリズムと計算量fuchida/lecture/algorithm/alg...algorithms and data structures on c...

35
Algorithms and Data Structures on C アルゴリズムと計算量

Upload: others

Post on 25-Aug-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

アルゴリズムと計算量

Page 2: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

この回の要点

• アルゴリズムの性能の基準は計算量• 計算量(complexity)

– 時間計算量(time complexity)– 空間計算量(space complexity)– 最大計算量(worst case complexity)– 平均計算量(expected comlexity)

• オーダー(order)の概念• 計算量の増加の形

– 指数時間アルゴリズム(exponetial time alg.)– 多項式時間アルゴリズム(polynomial time alg.)

• 再帰的アルゴリズム

Page 3: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

アルゴリズムの性能

• アルゴリズムの性能はどのようにして計るか?– 実際にプログラムを作ってみて、実行時間を比べる?(ベンチマークテスト)

– 問題点• 使用するマシンの性能に依存する

• コードを書く人間の技量に依存する

• 使用する(高級)言語の性能に依存する

• 使用した入力データに依存する

– 仮想的な計算モデルを使用する• レジスタのビット数は不問

• CPUのクロック数も不問

• 1つの命令は単位時間で実行できる。

Page 4: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量とは

• プログラム:入力→出力を得るもの– ある特定の入力例には関心がない

• 偏った入力に対する結果は意味がない

– 入力データ数 n (入力の規模・サイズ)

– n が増えたときに、出力が得られるまでの時間がどのように変わるか?

– アルゴリズムの計算時間を n の関数として f(n) と表し、この f(n) をアルゴリズムの時間計算量と呼ぶ。

– 「時間」を「空間(メモリ)」に置き換えた場合、空間計算量と呼ぶ。

• サイズ n の入力データにはいろいろある– そのアルゴリズムにとって最悪のデータを使った場合を最大計算量という

– すべての入力の計算量の平均をとったものを平均計算量という

Page 5: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量の例(1)

• ハイ&ローゲーム– 2人(親と子)で遊ぶ

– 親は、1から128までの数字の中から1つを子に内緒で思う

– 子は、親がどの数字を思っているかをできるだけ少ない回数で当てる

– 子は親に以下の質問をすることができる• あなたの思っている数字は○○より小さいですか?

• どのような戦略が考えられるだろうか?

• 数字が1から n までの場合はどうだろうか?

32

78

21

98104

39

11

Page 6: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量の例(2)

• 線形探索(リニアサーチ)– 子は、2から128までの数字を順番に言っていく

• あなたの思っている数字は2より小さいですか?• あなたの思っている数字は3より小さいですか?• あなたの・・・

– 最大計算量は?• 親がいつも128を思っていたとき• 常に127回が必要

– 平均計算量は?• 親がランダムに1つの数字を選んで思っていたとき• 場合によって早く当たることもあれば、遅く当たることもある• 平均すると、64回くらいで当たる

– ちょうど真ん中だから。

Page 7: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量の例(3)

• 二分探索(バイナリサーチ)– 探索範囲を半分に分ける

• あなたの思っている数字は64より小さいですか?→いいえ

• あなたの思っている数字は96より小さいですか?→はい

• あなたの思っている数字は80より小さいですか?→はい

• あなたの・・・

– 最大計算量=平均計算量• どの数字を思っていても、7回で当てることができる

1 12864 72 968076

74

①②③

④⑤

なぜ7回?

27=128 だから

Page 8: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量の例(4)

• 思う数字が1から n までだったら?

– 線形探索• 最大計算量= n

• 平均計算量= n/2

– 二分探索• 最大計算量=平均計算量=log2 n

• この計算量は、親への「問い」に関するもの

– 1回の問いに一定の時間必要ならば、時間計算量

– 1回の問いに一定のメモリーが必要ならば、空間計算量

Page 9: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

n と log n の計算量(1)

0

20000

40000

60000

80000

100000

0 20000 40000 60000 80000 100000

n

n/2

log n

通常のグラフ

Page 10: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

n と log n の計算量(2)

1

10

100

1000

10000

100000

1 10 100 1000 10000 100000

n

n/2

log n

対数グラフ

Page 11: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

C言語による実装

• ハイ&ローゲームをC言語で実装してみる• ソースコード(HiAndLow.cc)• コンパイル(Cygwin環境)

– g++ –o HiAndLow HiAndLow.cc -lwinmm

• 実行方法– HiAndLow L 1000

• 1から1000までの範囲の数字を線形探索で探す

– HiAndLow B 20000• 1から20000までの範囲の数字を二分探索で探す

• 結果(csv形式)– 最大数, 1回の探索に要した時間[ms]

• 連続実行– HiAndLow.sh

• いくつかの n に対して上記2つの方法を連続的に実行する

Page 12: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

実行結果

1.E-05

1.E-04

1.E-03

1.E-02

1.E-01

1.E+00

1.E+01

1.E+02

1.E+03

1.E+04

1.E+05

1.E+00 1.E+01 1.E+02 1.E+03 1.E+04 1.E+05 1.E+06

b_search

l_search

n

log n

Page 13: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

オーダーの概念

• 計算量のオーダー記法– 入力データの大きさ n に対する計算量を f(n)

– ある関数 g(n) と2つの定数 n0,c が存在し、n>n0 なる n に対し常にf(n)<cg(n) となるとき、f(n)=O(g(n)) と記し、計算量はオーダー g(n) である、という

• 十分大きな n に対しては f(n) は g(n) の定数倍である

• n0 は n が小さい場合の例外を許すため

– 例:• のオーダーは O(n2)

• なぜなら、十分大きい n に対しては

• 定数倍の違いは、計算量の増え方には関係しない

– オーダーの計算• O(n2)+O(n)=O(n2) :和は大きい方になる

• O(n2)O(n3)=O(n5) :積は積になる

52)( 2 nnnf23)( nnf

Page 14: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量の増加の形(1)

• ある問題を解くのに7種類のアルゴリズム

– A:log(n)

– B:n

– C:n log(n)

– D:n2

– E:n3

– F:2n

– G:n!

Page 15: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量の増加の形(2)

1

1E+10

1E+20

1E+30

1E+40

1E+50

1E+60

1E+70

1E+80

1E+90

1E+100

1E+110

1E+120

1E+130

1E+140

1E+150

10 100 1000 10000 100000

log(n)

n

n log(n)

n*n

n*n*n

2^n

n!

Page 16: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量の増加の形(3)

1

10

100

1000

10000

100000

1000000

10000000

100000000

1E+09

1E+10

1E+11

1E+12

1E+13

1E+14

1E+15

10 100 1000 10000 100000

log(n)

n

n log(n)

n*n

n*n*n

Page 17: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

計算量の増加の形(4)

• 指数時間アルゴリズム(exponential time alg.)– 時間計算量が n の指数関数(2n や 3n など、n!も含む)

– n の増加に伴い急激に計算量が増加する厄介な問題

• 多項式時間アルゴリズム(polynomial time alg.)– 時間計算量が n の多項式(n や n2 など)

– ある程度実用的なアルゴリズム

• NP困難(完全)問題(NP-hard(complete) problem)– NP = Nondeterministic-Polynomial (非決定的多項式)

– 指数時間アルゴリズムは得られているが、多項式時間アルゴリズムがわからないような問題

– 巡回セールスマン問題、ハミルトン閉路問題、ナップサック問題など

– 規模が大きいと、事実上解けない

– 規模を小さくするか、近似解でごまかすか?

Page 18: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

巡回セールスマン問題(TSP)

• N個の都市– 各都市間の距離は決まっている– 距離はコストをあらわす(時間などでも良い)

• 問題– 一人のセールスマンがある都市を出発し、すべての都市を1回だけ訪問して元の都市に戻るとき、最短経路を求めよ。

位置は同じ道のりは?

Page 19: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

TSPの解法

• NP困難な問題– 多項式時間では解けそうにない– 一般には規模(=都市数)が大きくなると、近似的にしか解けない

– 完全解を求めるには全探索法しかない• 枝刈り等で若干探索空間を狭めることは可能

• 全探索法– 考えられるすべての経路長を計算し、その中で最も短いものを探す

• 最初の都市を選ぶ→N-1通り• 次の都市を選ぶ→N-2通り• その次の都市を選ぶ→N-3通り• ・・・• 最後の都市を選ぶ→1通り

– すべての組み合わせは、(N-1)!通り

Page 20: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

TSP解法時間(1つの組み合わせに1ミリ秒かかるとした場合)

都市数

組み合わせの数 時間

5 (4!)/2 = 12 12ミリ秒

6 (5!)/2 = 60 60ミリ秒

7 (6!)/2 = 360 360ミリ秒

8 (7!)/2 = 2620 2.6秒

9 (8!)/2 = 20160 20秒

10 (9!)/2 = 181440 (18万) 3分

11 (10!)/2 = 1814400 (181万) 30分

12 (11!)/2 = 19958400 (2000

万)

5.5時間

都市数

組み合わせの数 時間

13 (12!)/2 = 239500800 (2億4000万) 2.8日

14 (13!)/2 = 3113510400 (31億) 36日

15 (14!)/2 = 43589145600 (435億) 1.4年

16 (15!)/2 = 653837184000 (6500億) 20.7年

17 (16!)/2 = 10461394944000 (10兆) 332年

18 (17!)/2 = 177843714048000 (177

兆)

5639年

19 (18!)/2 = 3200兆 10万年

20 (19!)/2 = 60000兆 200万年

Page 21: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

再帰的アルゴリズム(1)

• アルゴリズムの中で自分自身を使っているような形のアルゴリズム– 階乗の計算– ユークリッドの互除法– ハノイの塔– クラス HiAndLow の searchBinary()

– 漸化式で表される数列も

• 帰納的アルゴリズムとも言う• どこかで「底入れ」が行われなければならない

– 処理を中断・終了する条件が必要– 暴走、もしくはスタックオーバーフロー

Page 22: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

再帰的アルゴリズム(2)

• 階乗の計算– long fact(long n){

if(n==0) return 1; // 0!は1return fact(n-1)*n; // n!は(n-1)!*n

}

• ユークリッドの互除法– int gcd(int m,int n){

if(n==0) return m;

return gcd(n,m%n);

}

Page 23: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

課題191017

• 再帰呼び出しによるユークリッドの互除法を用いて、与えられた2つの整数の最大公約数を出力するCのプログラムGCD.cc を作成し、そのソースコードと実行結果を示せ。– $ GCD 45 18 ←入力

– 9 ←出力(結果)

– $ GCD 130 39

– 13 《提出要領》• 作成方法:Cのソースと実行結果の画像もしくはテキストファイルをワードに貼り付けて提出すること。(課題はCygwinで作成しなくてもVisualStudio等の他の環境で作成しても良い)• ファイル名はscXXXXXX-al191017.docx

• 提出方法:メールで• 提出先:[email protected]

• メールタイトル:“アルゴリズム課題191017” ← 厳守!• メール本文に氏名と学生番号を明記すること• 提出期限:2019年10月20日(日) 24:00

• 警告:内容が酷似している2つ以上のレポートがあった場合は、双方、不可になる可能性がある。

Page 24: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

アルゴリズムと計算量終了

Page 25: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.cc

main( )

playManually( )exp( )

searchBinary( )

searchLinear( )

ask( )

answer

min_can

max_can

globals

$ HiAndLow L 1000

Page 26: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.cc

/***

*** ハイアンドローゲーム

*** ---

*** 親が思っている数字を当てるゲーム

*** 子が可能な質問は「その数字は○○より小さいですか?」のみ

*** 質問によって答えの存在範囲を限定していき、1つに絞れた時点で終了

***/

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <windows.h>

#include <mmsystem.h> // -lwinmmが必要

long answer; // 親が思っている数字

long min_can; // 最小の候補

long max_can; // 最大の候補

Page 27: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.cc (main)

// メイン

int main(int argc,char **argv){

srand(time(NULL));

if(argc==1)

playManually();

else if(argc==3)

exp(argv[1][0],atoi(argv[2]));

else

fprintf(stderr,"Usage: HiAndLow [L|B max]");

return 0;

}

Page 28: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.cc (playManually)

// 手動探索モード

void playManually(){

long n1=1,n2=100,num,cnt=0;

min_can=n1;

max_can=n2;

answer=(int)((double)rand()*(n2-n1+1)/RAND_MAX)+n1;

while(min_can!=max_can){

printf("Is your number lower than this number ?(from %d to %d) : ",n1,n2);

scanf("%ld",&num);

if(ask(num))

printf("Yes. My number is lower than %ld.¥n",num);

else

printf("No. My number is NOT less than %ld.¥n",num);

cnt++;

}

printf("You found %ld! (%d times)¥n",min_can,cnt);

}

Page 29: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.cc (exp)// 連続実験モード

void exp(char type,long max){

clock_t start=timeGetTime();

long n1=1;

long n2=max;

long cnt=(type=='L'?100000:10000000);

for(int i=0;i<cnt;i++){

answer=(long)((double)rand()*(n2-n1+1)/RAND_MAX)+n1;

min_can=n1;

max_can=n2;

switch(type){

case 'L': searchLinear(n1,n2); break;

case 'B': searchBinary(n1,n2); break;

}

}

clock_t end=timeGetTime();

printf("%ld %g¥n",max,((double)end-start)/cnt/CLOCKS_PER_SEC*1000);

}

Page 30: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.cc (searchBinary)

// 二分探索

// 何回で当てたかを返す

long searchBinary(long n1,long n2){

if(min_can==max_can) return 1;

long m=(n1+n2+1)/2;

if(ask(m))

return searchBinary(n1,m-1)+1;

else

return searchBinary(m,n2)+1;

}

Page 31: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.cc (searchLinear)

// 線形探索

// 何回で当てたかを返す

long searchLinear(long n1,long n2){

long i;

for(i=n1+1;min_can!=max_can;i++)

ask(i);

return i-n1+1;

}

Page 32: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.cc (ask)

// 親への質問「その数字はnより小さいですか?」

// その答えを返す(Yesなら1、Noなら0)

// 同時に、答えの存在範囲を限定する

int ask(long n){

if(answer<n){

if(max_can>n-1)

max_can=n-1;

return 1;

}

else{

if(min_can<n)

min_can=n;

return 0;

}

}

Page 33: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.sh

• シェルスクリプト– コマンドライン入力をまとめて実行する仕組み

– シェルによって読み込まれて1行ずつ実行される

– 変数や、for や if などの制御構文も利用可能

– cmd.exeとは異なる

• Windows環境のCygwinでbashを使う場合– シェルスクリプトの改行コードはLFでなければならない

• Windowsの通常の改行コードはCR+LF

– サクラエディタなどで変更できる

Page 34: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.sh#!bash

L_NUMS="2 3 5 7 ¥

10 20 30 50 70 ¥

100 200 300 500 700 ¥

1000 2000 3000 5000 7000 ¥

10000 20000 30000 50000 70000 ¥

100000"

OUT="lap_L.csv"

echo "*** Search by Linear ***" >> $OUT

date >> $OUT

for i in $L_NUMS

do

echo $i

./HiAndLow L $i >> $OUT

done

date >> $OUT

maxを変化させる数のリスト文字列

実験前の出力

実行するシェル名

実験後の出力

変数 i に L_NUMSに入っている数を1つずつ代入しながらdo ~ doneの間を実行する

注意:このコードは、bashというシェル(Cygwinに付属)でのみ実行可能

Page 35: アルゴリズムと計算量fuchida/lecture/algorithm/alg...Algorithms and Data Structures on C 計算量とは • プログラム:入力→出力を得るもの – ある特定の入力例には関心がない

Algorithms and Data Structures on C

HiAndLow.shB_NUMS="2 3 5 7 ¥

10 20 30 50 70 ¥

100 200 300 500 700 ¥

1000 2000 3000 5000 7000 ¥

10000 20000 30000 50000 70000 ¥

100000 200000 300000 500000 700000 ¥

1000000"

OUT="lap_B.csv"

echo "*** Search by Binary ***" >> $OUT

date >> $OUT

for i in $B_NUMS

do

echo $i

./HiAndLow B $i >> $OUT

done

date >> $OUT

二分探索も同様