アルゴリズムデザイン
Algorithm Design

アルゴリズムは機械学習分野などを含む情報科学分野の重要な概念である。アルゴリズムとは、計算問題を解くための基礎的な演算等を用いて記述された手段であり、計算問題の入力から出力するなどの諸条件を満たすように設計されなければならない。ここでいう計算問題とは、最適化問題や推論問題などであり、これらも情報科学における設計対象の一つである。さらにアルゴリズムを設計すると、次にこれを実働化するためにコンピュータ・プログラムを設計する。つまり情報科学分野は様々な対象を設計し成果物を作り出す営みと える。アルゴリズム、計算問題、プログラムを作り出すことを「設計する」と表現できるが、この言葉に加えて、意味するところをより明確化するために、定義(definition)や定式化(formulation)そしてモデル化(modeling) 等の表現もよく用いられている。以下では、計算問題、アルゴリズム、コンピュータ・プログラムのデザインを概観していく。

計算問題を定義することは、現実の問題などを抽象化することにより昇華させ、数理的な言葉で記述する行為と捉えることができる。例えば、あなたが営業の仕事をしていて上司から指定されたN都市を訪問し最後に出発都市に戻らなければならないのであるが、移動する都市間の移動コストの総和を最小とする順に回る都市の順番を見つけなさいという問題を考える。この問題は巡回セールスマン問題(traveling salesman problem)として知られており、この問題の入力例(input instance)は2頂点u, v間の e = {u, v} に移動コストw (e) を割り当てた辺重み付き無向グラフでよく表現される。そして、全ての頂点(都市)を訪問する閉路pを考えたとき、pの評価値はpに含まれる辺の重みの総和(移動コストの総和)である。このようにして計算問題は形式的に定義されることになる。さて、このような入力例が一つ与えられたときに、コスト最小もしくは近似的な解である閉路を求める計算手順がアルゴリズムであり、我々はこれを設計しなければならない。

アルゴリズムに関しては『アルゴリズムデザイン』と題する名著もあるくらいデザインという概念と関係が深い。アルゴリズムの設計とは、一般的には次のように述べることが出来る。まず、入力xに対して出力yという何らかの関係が与えられる。これがアルゴリズムが満たすべき条件である。この条件を満たすように、つまり定義域のすべてのxに対してy=A(x)を満たす計算手順(アルゴリズム)Aを設計する。つまり、単純にアルゴリズムを設計すると言っても、アルゴリズム設計の場合には、当然のこととして指定された入出力関係を満たす条件が存在している。さらに、アルゴリズムは実現され、それをもとに計算機プログラムが実働化されると便利な道具として繰り返し使われることになる。それ故、計算時間と記憶領域の2点における効率が設計で重要視される。現代では、多くの人がパソコンやスマホ上でプログラムやアプリを実行しているが、これらがメモリ不足のエラーメッセージを出すことなく、また瞬時に結果を提示することができるのは長年のアルゴリズムデザインの成果でもある。また、アルゴリズムを設計するということは与えられた入出力関係を満たしているという数学的な証明を与える技(art)が必要である。実際、ドナルド・クヌース(Donald N. Knuth)のアルゴリズムに関する名著の題はThe art of computer programmingである。

また、アルゴリズムをコンピューター上で実働化することをプログラミングという。コンピューター・プログラムでは、全体として満たすべき入出力関係をどのような部品から構成するかの設計が必要である。さらに、各部品の具現化を設計する。具体的には、データ構造、関数、クラスなどの部品やこれらをまとめたライブラリがあげられる。とくにクラスの設計に関しては、「デザインパターン」という概念が知られている。これは、オブジェクト指向言語におけるクラス設計のパターン集である。クラスが満たすべき良く出くわす条件に対して、それを満たすクラス設計のパターンを対応付けたものである。アルゴリズムデザインに加えて、プログラムデザインも技が必要である。

また、プログラムに関しては、第三者が読みやすいコード(readable code)を書くことが求められる傾向がある。『The Art of Readable Code: Simple and Practical Techniques for Writing Better Code』という原著タイトルの書籍はリーダブルコード設計のための虎の巻と言える。例え自分で書いたコードであっても、一カ月後に見直すと何を書いているか分からない場合がある。特にやっつけ的に書いた場合などはそうである。また、リーダブル・コードを書くことは、共同研究者や学生とコードを共有する場合にも重要であることは自明であろう。さらに、Githubなどでソースコードを公開する場合には、当然第三者が読むことを想定してコーディングすべきである。「良い習慣がより良い人生をつくる」という言葉があるように「リーダブルコードがより良い成果をもたらす」と言えるのかもしれない。リーダブルコードを書くことはプログラムのデザイン上の良い習慣と言えそうである。

(丸山修)

参考文献

  • Boswell, Boswell and Trevor Foucher(2012)『リーダブルコード より良いコードを書くためのシンプルで実践的なテクニック』角征典訳、オライリージャパン
  • Gamma, Erich, Richard Helm, Ralph Johnson, John Vlissides, and Grady Booch(1999)『オブジェクト指向における再利用のためのデザインパターン』吉田和樹・本位田真一監修、ソフトバンククリエイティブ
  • Kleinberg, John and Eva Tardos(2008)『アルゴリズムデザイン』浅野孝夫・浅野泰仁・小野孝男・平田富夫訳、共立出版
  • Knuth, Donald E(2015)『The Art of Computer Programming Volume 1: Fundamental Algorithms, Third Edition』有澤誠・和田英一監訳、KADOKAWA