2015-12-27

"7つの言語 7つの世界" Bruce A. Tate 著

プログラミング言語を効果的に習得する方法は、その言語の得意とする問題を記述してみること... そんな当たり前にも思える学習モデルを実践することは意外と難しい。優れた思想ほど宗教化しやい側面があり、開発組織は政治的な思惑に支配される傾向がある。言語信奉者に自己存在を問えば、宗教熱にも拍車がかかる。愛着のある言語の柔軟性を自負して、他言語を迫害するのであれば、使い手の思考の柔軟性はいったいどこへ。まさか思想の開祖が、弾圧を目的としてきたわけではあるまい。自由と柔軟性は相性がいい。柔軟性をともなわない自由は、窮屈なものとなろう。どんな言語にも、哲学、思想、文化といったものが育まれる。言語システムがある程度の妥協を受け入れてきた理由を理解するには、その言語が辿ってきた歴史を知らなければならない。こうした背景を単なる記述の手段として片付けるのは、あまりにも惜しい。概念、言語、パラダイム、技法に直接触れてみることの重要さは、いくら強調しても足りない。
しかしながら、一つの言語を習得することは、一つの文化を学ぶことを意味し、生半可な覚悟では済まない。その根底にある動機はプログラミングを楽しむこと、そして、最終的に自分自身の言語を見つけ出すことになろうか。自然言語が人間魂の投影であるならば、プログラミング言語は技術魂の投影とでもしておこうか...

"Ruby, Io, Prolog, Scala, Erlang, Clojure, and Haskell"
ここでは、Java, C++, Python などの人気言語が意図的に外されるが、むしろ惚れっぽい天の邪鬼にはありがたい。商用プロジェクトにどっぷり浸かっていると、新たな言語に触れる機会は著しく限られ、新たな概念を持ち込もうとすれば、激しい抵抗にもあう。おまけに、プログラミング言語の評価では、勝者と敗者に振り分けて語られる風潮がある。人間社会がこれだけ多様化しているにもかかわらず、多数決が正義とされるのは、この分野に限った話ではない。ドメイン固有とは、多様化した人間社会における居場所を求めることに他ならない。真に汎用言語というものは、それが長所であると同時に短所となりうる。これといったキラーアプリケーションがないことを意味するのだから。おそらく相対的な認識能力しか発揮できない知的生命体が、万能な言語を編み出すことなど不可能であろう。
また、Ruby が比較対象とされるところも、個人的に馴染みやすい書となっている。各言語とも三日間の講習コースとして計画され、21日 + αというわけだが、読破するのに1ヶ月以上かかってしまった。
本書の不思議なところは、掲載されるコードをそのまま入力し、同じ結果が得られるかどうかを確かめるだけで、何かに挑戦してみたいという気分にさせてくれることだ。新たなスキルを身につけようとする時、最初に良き教師に出会えれば幸運である。ただ、教師は人とは限るまい。書籍も素晴らしい教師となりうる。とはいえ、学問の道で最短距離を駆け抜けることは至難の業。学ぶ側から高みに昇っていき、良き教師、良き書籍を嗅ぎ分ける眼力を養うしかない。そのために、失敗を受け容れるしかなさそうだ...

「プログラミングを学ぶことは、泳ぎを覚えるのに似ている。いくら理論を学んでも、プールに飛び込んで、息をしようと喘ぎながら水の中で手足をばたつかせる経験には代えられない。最初水中に沈んだときはパニック状態になるが、水面にひょいと顔を出して空気を飲み込むと、うれしい気分になる。自分は泳げる!と思えるからだ。 ...
禅の指導者は、数学が出来るようになりたければラテン語を勉強せよと言うだろう。プログラミングでも同じだ。オブジェクト指向プログラミングの本質を深く理解するには、論理プログラミングや関数型プログラミングを勉強する必要がある。関数型プログラミングに上達したければ、アセンブラを勉強する必要がある。」
... Erlang の作者 Joe Armstrong

1. 7つの言語とその人物像
言語の性格を語るのに、映画とその登場人物を重ねながら、多分に文学的な要素を交える趣向(酒肴)もなかなか...

Ruby は、メリー・ポピンズ。
乳母という仕事から考え得る限り情熱を引き出すことで、家事を効率的なものにする。スプーン一杯の砂糖があるだけで、苦い薬も飲めるのよ!まさにシュガーシンタックスこそが抽象度を高める。コレクション操作におけるシンプルなループ構文や直感的な範囲指定など豊富な API によって...
「オブジェクト指向の設計哲学における重要な教義は、実装ではなく、インタフェースに合わせてコーディングするというものだ。ダックタイピングを導入すると、ほとんど何の作法もなしに、この設計哲学を簡単に適用できる。」

Io は、フェリス・ビューラー。
何でも一度はやってみるタイプで、若くて、ずる賢く、分かりやすいが、まったく予測不能ときた。柔軟性が高いがゆえに、少しおかしな動きをする。
「問題は何をするかではない、何をしないかだ!」
商業的には成功していない言語だが、コルーチン、アクター、フューチャに基づく並行性構文を絶賛している。

Prolog は、レインマンのレイモンド。
要領の悪い自閉症だが、型にはまると超人的な能力を発揮する。確かに古い言語で、洗練されているとは言い難いが、条件の厳しい専門性において強力。
「この言語は驚くほど利口な場合もあれば、それと同じくらいイライラさせられることもある。素晴らしい答えが得られるのは、質問の仕方が分かっている場合だけだ。」

Scala は、エドワード・シザーハンズ。
はさみを持つ人間と機械のあいのこは、まさにオブジェクト指向型と関数型の橋渡しをするハイブリッド。世間から非難される幻想的なキャラクターは、時にはぎこちなく振る舞い、時には驚くほどの能力を見せる。厳密に言えば、純粋な関数型ではない。C++ が純粋なオブジェクト指向型ではないように。

Erlang は、マトリックスのエージェント・スミス。
仮想世界マトリックスの人工知能プログラムであるスミスは、姿形を自由に変え、複数の場所に同時に存在できる。この言語は並行性における分散処理と耐障害性という特徴を有し、そこには「クラッシュさせろ!」という哲学があるという。普通とは真逆の発想だが、信頼性に自信がある裏返しか。それも、副作用なしという前提で初めて機能する哲学だ。
「Erlang のような謎めいた言語はほとんど見かけない。Erlangは、難しいことを簡単にし、簡単なことを難しくする並行処理指向言語だ。」

Clojure は、スターウォーズのヨーダ。
賢明なカンフーの達人、丘の上に立つ預言者、謎めいたジェダイの指導者。見た目は地味ながら非常に高い能力を秘め、ありとあらゆる生命体に遍在するエネルギー、すなわちフォースを自在に操る。Lisp 方言の一つで、マクロや高階構文を使いこなすには、フォースを見抜く修行が必要というわけだ。おまけに、話し方は語順が逆で理解しづらく、前置記法ときた。

Haskell は、スタートレックのスポック。
論理と真理を崇拝し、世代を超えて愛されるひたむきな純粋さ。
「Haskell は、関数型プログラミングにおける多くの純粋主義者にとって、純粋と自由の象徴である。その機能は豊富で強力だが、それには代償が伴う。Haskell では、関数型プログラミングを少しかじってみるといった安易な考えは許されない。とにかく関数型プログラミングという料理を余すことなく完食することを強制される。」

2. 関数型とオブジェクト指向型の相互運用
プログラミング言語の進化が、コンピュータ科学の中で比較的ゆるやかなのは、頭の固いアル中ハイマーとってありがたい。歴史を振り返れば、二十年くらいのサイクルで大きなパラダイム変革が生じている。現在では、並行性と信頼性が中心的な話題であろうか。
ここでは、Ruby と Prolog を除く5つの言語が並行性モデルを採用している。並行性におけるオブジェクト指向型言語の問題は、副作用から生じる可変状態を許すことにある。複数のスレッドやプロセスが同時に発生すると、この可変状態の管理が極端に複雑になる。
とはいえ、状態を持つことはモジュールの抽象度を高める効果があり、オブジェクト指向では根幹をなす概念の一つである。
一方、純粋な関数型は、同じ関数を何度呼び出しても、同じ入力に対して必ず同じ答えを返す。まさに数学の関数概念だ。副作用なし!これを保証するだけで、競合状態における複雑さが解消される。このタイプには、Scale, Erlang, Clojure, Haskell が属す。
しかしながら、オブジェクト指向との関わり方では、大きく戦略が違うようだ。関数型とオブジェクト指向型の共存を目指すものもあれば、オブジェクト指向と完全に決別するものもあり、あるいは、現実的に共存を認めながら最終的に決別しようというものもある。
Scala のアプローチは共存方針で、強い関数型の性質を用いながらオブジェクト指向を混入している。
Clojure のアプローチは互換性重視だが、「OOPは基本的に一部欠陥がある」という考え方が根底にある。JVM上で構築され、Javaオブジェクトを直接利用できるメリットがあるが、Javaとの相互運用性の方が重視され、Clojure という言語自体を拡張することが目的ではないようだ。
Erlang と Haskell は基本的にスタンドアロン言語で、オブジェクト指向を一切許容しない。
ちなみに、Ruby はオブジェクト指向型でありながらコードブロックによって関数型の概念を少し導入しているものの、これらの並行性からは程遠いようである。

3. 並行性構文のコンポーネント
本書は、並行性構文で鍵となる三つのコンポーネントを挙げている。それは、コルーチン、アクター、フューチャ。その基盤を成すのがコルーチンで、プロセスの実行を自由に停止し、再開できる機構だという。複数の入口と出口を持つ関数のようなものか。
Java や Cベースの言語は、プリエンプティブ・マルチタスクの概念が用いられる。この並行性概念に、変更可能な状態を持つオブジェクトが組み合わさると、予測が極端に難しくなる。
対して、コルーチンは従来方式とは異なり、協調的マルチタスク(ノンプリエンプティブ・マルチタスク)に不可欠な機構で、非同期でメソッドが呼び出せるという。
アクターは、メッセージの送信、メッセージの処理、他のアクターの生成を行う並行性プリミティブで、複数のメッセージを同時に受信してキューに登録し、その内容をコルーチンで処理していく。
メッセージは、sender, target, arguments の三つのコンポーネントからなり、リフレクションを実行するためのメソッドが多数用意されている。尚、アクターは、理論上スレッドより有利だという。
フューチャは、非同期のメッセージを呼び出しによって返される結果オブジェクトのこと。他からの問い合わせは、結果値が使用可能になるまでブロックされるという。
本書は、こうした並行性概念を、Io の事例で味あわせてくれる。というのも、シンタックスが、コルーチン、アクター、フューチャの実装にマッチしているからだという。
Io のシンタックスは、なかなかの感動モノ!母音二文字の名が象徴するように、単純でローレベルに設計されている。それはメッセージを単純にチェーン連結したもので、クラスとオブジェクトを区別しない。メッセージそのものがオブジェクトで、ルートオブジェクトからひたすら実体を複製していく(クローニング)。このクローンがプロトタイプと呼ばれ、プロトタイプベースの言語というわけだ。非同期のメッセージを送信すると、アクターそのものがオブジェクトになる。しかも、Io のフューチャは、デッドロックを自動的に検出する機能を備えているという。シンタックスは、Lisp のように単純で、セマンティクスは強力で柔軟。
しかしながら、Ruby のように動的な性質を実現した代償として、単一スレッドではパフォーマンスが悪い傾向にあるという。乱暴に言えば、すべての知識や経験は関連付けで成り立っている。DNAの螺旋構造もまたチェーン連結のごとく増殖していく。プラトンが唱えたイデアのような精神の雛形は、いわば理想像。理想なんてものは暇人の考えることで、実体はすべて実践の関連付けのみで構築されることを暗示しているのだろうか。
尚、もともとは、Steve Dekorte がインタープリタの動作を理解するための練習で書いた、いわば趣味レベルの言語だそうな。
アクターの機構は、Scala や Erlang も継承し、パターンマッチングを用いて着信メッセージを照合し、条件分岐させて実行するという。その高度なパターンマッチングの方法としてユニフィケーションを紹介してくれる。ユニフィケーションは、パターンマッチングの親戚のようなもので、実は、Prolog の備える機構だという。
さらに、Erlang とその仮想マシンは堅牢なモニタリング機能を備えるため、異常な兆候を察知した時点で、通知したりプロセスを再起動したりできるという。
いまや、スレッドやプロセスを開始してセマフォを持つような仕組みでは不十分で、アクターやフューチャなどの高機能な並行性構文の必要性が高まっているようである。

4. ソフトウェアトランザクションメモリ(STM)
並行処理にとって可変状態は、オブジェクト指向に潜む悪の根源。これに対処するため、Io と Scala はアクターベースのモデルを用いて、変更不能な構文を用意している。
Erlang は軽量プロセスを用いたアクターと、効果的なモニタリングと通信を可能にする仮想マシンによって、比類のない信頼性を実現している。
一方、Clojure のアプローチは他とは異なり、STM を使う。
ところで、データベースではトランザクションによってデータの整合性を保証する、二つの制御方法を見かける。一つはロックで、競合するトランザクションが同時に同じ行にアクセスするのを防ぐ。二つはバージョニングで、各トランザクションが競合データのコピーを保持できるように複数のバージョンを用意して、互いの干渉を防ぐ。Java などでは、競合スレッドから保護するためにロックを用いるため、こちらの方が馴染みがあろうか。
しかし、ロックは並行制御のための作業が負担となり、なかなか耐え難いものがある。
対して、STM の戦略では、複数のバージョンを用いて一貫性と整合性を維持するという。Clojure で STM を用いるのは、スレッド間の一貫性を保ちながら可変状態を実装できるということらしい。STM は、共有リソースに対する分散アクセスをトランザクションでくるむ方法で、参照状態を変更する時はトランザクションのスコープ内で行う必要がある。その意味では、Clojure はデータベース言語にも見えてくる。Clojure では、dosync関数でくるみ、複数のスレッドやプロセス間での整合性を維持するという。Lisp方言の Clojure は、こうしたアプローチに理想的な言語だという。Lispは、マルチパラダイム言語だから。
尚、STM は比較的新しい概念で、人気のある言語でも採用され始めているようである。

5. リスト内包表記とモナド
Haskell は、本書に登場する唯一の純粋な関数型言語である。Scale、Erlang、Clojure も関数型ではあるが、命令型の概念を少し取り入れている。Haskell にそのような逃げ道はない。純粋とは、同じ関数に同じ入力を与えれば必ず同じ結果が得られるという意味で、けして副作用を許さず、書き換えることのできる状態がどこにも存在しないってことだ。
そのために、I/O処理やエラー処理といった簡単な処理が難しくなる。その対処法として、Haskell では「モナド」という概念を用いて状態を保持する方法を紹介してくれる。
ところで、リスト内包表記は、Python など他の言語にも広まりつつある表記法ではあるのだけど、極めて数学的な表現であることを改めて実感させてくれる。つまり、カリー化や高階関数を表記する上で効果的だということを。カリー化とは複数の引数をとる関数を渡す表記法で、高階関数とは戻り値に関数を返したり、引数に関数を受け取る関数のこと。どちらもラムダ計算のような理論モデルに欠かせない概念だ。この表記法によって、再帰処理がリスト処理によって強力になる。ちなみに、Ruby は高階関数の代わりにコードブロックを使う。
リスト内包表記は、複数の概念をまとめて一つの強力な構文を作り上げる。これを適合しやすい演算は、フィルタ、マップ、直積といったところであろうか。
さて、モナドの方だが、それは精神融合のようなものか。ライプニッツ風モナドロジーが頭に浮かぶ。それは、副作用のない関数群という安定性に着目し、型の異なる関数を融合するという考え方である。モナドの構成要素は、以下の三つ。
  • コンテナになるものの型を変数に取る型構成子。コンテナとして使えるものは、変数やリストなど値を保持できるもので、ここに関数を収める。
  • 関数をラップしてコンテナに格納する return 関数。
  • 関数をラップするバインド関数(>>=)。関数を数珠つなぎにする。
そして、モナド m, 関数 f, 値 x に対して、以下の三つのルールを満たす必要があるという。
  • ラップした値はそのまま関数に渡すことができる。
    return x >>= f = f x
  • 情報を失うことなく値をアンラップおよびラップできる。
    monad >>= return = monad
  • バインドをネストした場合と、それらをシーケンシャルに呼び出した場合とで結果が同じ。
    (m >>= f) >>= g = m >>= (\x -> f x >>= g)
さらに、命令型を書くための do 記法を紹介してくれる。それは、モナドを記述するためのシンタックスシュガーである。
しかしながら、モナドが柔軟性が高いとはいえ、高度な知識が必要という意味では融通が利かない。

6. おまけ... 強い型付けと静的な型付けの混同
強い型付けと静的な型付けの混同しないように!と注意を促される。実は、おいらもよく見失う。
大雑把に言うと、強い型付けは、2つの型に互換性があるかどうかを検出し、互換性がなければエラーを投げるか、型の強制変換を行うという意味。
本書は、表面的には、Java と Ruby はどちらも強く型付けされているとしている。ただし、この見解は単純化しすぎると断りつつ。
一方、アセンブラや C言語は、弱く型付けされている。整数値か文字列かなどは、コンパイラは意識しない。だから、書き手が意識することになる。
静的な型付けと動的な型付けは、また別の問題である。静的型付けでは、型の構造体に基いてポリモーフィズムが行われるという。つまり、遺伝的な青写真によってアヒルかどうかを判定するのが静的型付けで、鳴き声や歩き方によってアヒルかどうかを判定するのが動的型付けであると。
静的型付けは、コンパイラとツールがコードに関する情報を保持し、エラーを捕捉したり、コードを強調表示したり、リファクタリングしたりできる点では有利だが、そのために作業量が増え、制約が生まれる。このトレードオフをどのように感じるかは、プログラマの経験やセンス、あるいは好みや設計分野にも左右されるだろう。

2015-12-20

"プログラミング作法" Brian Kernighan & Rob Pike 著

次のような経験をしたことはないだろうか... と、いきなり問いかけてくる。見透かされたかのように。どうせ、おいらはすべて経験済みさ!
  • 間違ったアルゴリズムでコーディングしてやたらと時間を無駄にした
  • 使用するデータ構造が死ぬほど複雑になった
  • プログラムをテストしたのに明白な問題点を見落としていた
  • 5分もあれば見つかるはずのバグを1日がかりで探し回った
  • プログラムを3倍速くしメモリ使用量も減らしたいと思った
  • ワークステーションとPCの間でプログラムを移植するのに苦労した
  • 他人のプログラムに少々変更を加えようとした
  • さっぱり理解できないプログラムを書き直した

問題解決のための手段の一つに言語があるが、その選択は目的次第。おそらく、すべての問題を同時に、効率よく、解決できる言語は存在しないだろう。なんでもやれることを望めば、低水準へ向かうことになる。だがそれでは、ソフトウェアの本質である簡潔性、効率性、移植性が維持できるはずもない。相対的な価値観しか持ち得ない知的生命体が、万能な言語を編み出すことなど不可能であろうから。それでもなお、ソフトウェア工学に普遍観念なるものを求めるとすれば...
「どんな言語で書くにせよ、プログラマとしての読者の任務は手もとのツールを使ってベストを尽くすことだ。良きプログラマは貧弱な言語や使いづらいオペレーティングシステムを克服できるが、悪しきプログラマを救うのはたとえ最高のプログラミング環境だろうと不可能だ。読者の現在の経験や実力がどの程度であれ、本書を参考にして実力を向上させ、プログラミングの楽しみをもっと感じられるようになれば幸いだ。」

本書で紹介されるコード事例は、C言語族が中心で、やや古臭さを感じないではない。現在では、メモリ容量やプロセッサ性能など豊富なリソースを前提にした慣習が根付いている。しかし、哲学的な作法はあまり変わらない。ガベージコレクションのような自動化機構の性能がいくら高まっても、完全に頼るわけにはいかないだろう。ここには、数々の教訓が鏤められる。とりあえず、気に入ったものを三つ挙げておこう...
「悪いコードにコメントをつけるな、書き直せ!」
「最適化の第一の原則は最適化するな!」
「簡潔性と明瞭性は何よりも重要だ。これ以外のものはすべてここから派生すると言っても過言ではない。」

これは、C言語や UNIX の開発で知られるブライアン・カーニハンとロブ・パイクのベル研コンビが綴ったプログラミングの王道を問う物語である。

「人が歴史から学ぶことができたなら、歴史は我々にいかなる教訓を与えてくれるだろうか。だが、我々の目は感情と利害に覆われ、経験のもたらす光明も船尾にともるカンデラにすぎず、我々の背後に遠ざかる波を照らすだけなのだ。」
... Samuel Taylor Coleridge 「Recollections」

さて、本書の内容を大まかに拾うと...
  • 良きプログラミングには、良きスタイルが不可欠。美しく書けば間違いも少なくなり、デバッグや修正も楽になり、最初からスタイルを意識することになる。
  • 単純なアルゴリズムと単純なデータ構造を選択せよ。
  • 簡潔性と関連することの多い概念に一般性があり、その次に進化がある。
  • インターフェイスは、プログラミングにおける戦いのかなりの部分を占める。その最も当たり前のケースはライブラリだ。
  • 自動化は過小評価されている概念である。テストを系統的に整理し、自動化せよ。テストやデバッグだけでなく、コードの自動生成も含めて検討する価値がある。
  • 記法も過小評価されている。記法は、単にプログラマがコンピュータに作業を指示する方法ではなく、様々な種類のツールを実装するための有機的な枠組をもたらし、プログラムを記述するプログラムの構造を導き出す。
しかしながら、内容よりも数々の名文句に目を奪われる。こちらは、ちと細かく拾ってみよう...

1. スタイルとデータ構造について
スタイルとは、プログラミング哲学を意味し、これが本書の骨格を成している。アルゴリズムの美しさやデータ構造の単純さは、設計哲学の投影というわけか。

「昔から言われるように、最高の書き手は時にレトリックのルールを無視することがある。ただしそうした場合には、ルール違反を補ってあまりあるメリットがその文を通して読者に伝わるのが通例だ。それに確信が持てない限り、おそらく書き手はできる限りルールに従おうとするだろう。」
... William Strunk & E. B. White 「The Elements of Style」

「結局のところ、具体的な問題に適正に対処する方策はこの分野のツールとテクニックに馴染むこと以外に存在しないだろうし、クオリティの高い成果が一貫して得られるようになるには一定の経験を積む以外に手はないだろう。」
... Raymond Fielding 「The Technique of Special Effects Cinematography」

「私にフローチャートを見せてテーブルを隠しておいたなら、私はずっと誤魔化され続けるだろう。しかしテーブルを見せてくれればたいていはフローチャートなどいらない。一目瞭然だからだ。」
... Frederick P.Brooks,Jr 「The Mythical Man Month」

2. インターフェイスと実装について
「壁を築く前に私はよく自問した。何を壁の内に閉じ込め何を外に閉め出そうとしているのか、自分が誰を傷つけようとしているのか、と。どこかに壁を愛さないものがいる。壁を倒したがっているものが。」
... Robert Frost 「Mending Wall」

「設計の真髄は、競合する目標や制約をバランスさせることにある。小規模な自立したシステムを書いているときにもトレードオフを迫られることは何度もあるだろうが、個々の選択によって生じる影響はそのシステムの中にとどまるし、そのプログラマにしか及ばない。しかし他人に使われるコードの場合には、自分の判断がもっと広範な影響を及ぼす。」

「ライブラリやインターフェイスを一発で正しく設計できる可能性は低い。Fred Brooks がかつて言ったように、"捨てるつもりでいること。どうせ捨てることになるのだから"。Brooks が言ったのは大規模なシステムについてだが、この考え方は実用的なソフトウェアすべてに通用する。実際にプログラムを作成して使ってみるまでは、正しく設計するのに必要な課題を十分に認識できないのが普通だ。」

3. テストとデバッグについて
テストとデバッグはまとめて扱われることが多いが、両者をごっちゃにしてはならないという。大まかに言えば、デバッグは問題があると分かっている時の作業で、テストは正常に動作していると思われるプログラムを破綻させようとする確信犯的でシステマチックな作業... といったところか。

「テストによってバグの存在は証明できるが、バグの不在は証明できないという Edsger Dijkstra の有名な言葉がある。」

自分のコードを他人に説明することも、第三者の目を要請する効果的な方法となろう。コードレビューにしても、共通な書き方を求めるよりも、哲学の共有の方がはるかに重要である。そのために、しばしば雑談会となるが、仕事が楽しめればそれでいい。
例えば、技術問題で悩んでいるメンバーに、ちょっと説明してみてよ!と持ちかけると... ホワイトボードの前で自信なさそうに喋っているうちに、いつの間にか問題の根幹に気づき、解決法を自信満々に語り始める... といったこともよくある。
バグは確実に再現できる時は、恐れるに足らん!問題は再現できない時で、頻度が少なくても、深刻な問題を抱えていることが多い。

「打つ前に読め!効果的なわりに過小評価されているデバッグテクニックのひとつに、"コードを舐めるように読んで、変更を施さずにしばらくよく考えてみること" がある。... 早くキーボードを触りたいという気持ちを抑えること。思考はそれに勝るとも劣らない行為だ。」

「コードを最初から上手に書けばその分バグも少なくなるし、徹底したテストを実行していることに確信が持てるようになる。コーディング時に境界条件のテストを記述することは、くだらないちょっとしたバグを大幅に減らす手段として効果的だ。系統的なテストは潜在的な問題発生箇所を順序正しく調査する方法だが、この場合もやはり境界部分で間違いが見つかることがもっとも多く、手やプログラムでそれを検証できる。
テストはできるだけ自動化することが望ましい。回帰テストはプログラムが以前と同じ答えを出すことをチェックする。小さな変更を施すたびにテストを実行するやり方は、問題の発生源を絞り込むのに有効なテクニックとなる。新しいバグは、新しいコードで発生することが多いからだ。」

4. 慣習と標準化について
「最後に、慣習と同様に標準化も強制に近い形で立ち現れることがある。しかし慣習と違って標準化は近代建築においては現在のテクノロジーの凝縮された結果として是認されてきたが、一方でその潜在的な支配力と非人間性が懸念されている。」
... Robert Venturi 「Complexity and Contradiction in Architecture」

「おそらく人間によるあらゆる創造物の中でもっとも驚くべきものは言語である。」
... Giles Lytton Strachey 「Words and Poetry」

2015-12-13

"高速アルゴリズムと並列信号処理" 谷萩隆嗣 著

十年来、引き戻され続ける書がある。いつも悩まされている事は、ありきたりではあるが、いかに効率よく近似するか、いかに高速処理を実装するか。酔いどれ数学オンチは、この分野で永遠に赤点を取り続けるわけだ。そういえば、鏡の向こうの住人も、いつも顔が赤い!

デジタル信号処理の礎となる数学の概念に、サンプリング定理と直交関数系がある。サンプリング定理とは、再現性の限界を定めたもので、ナイキスト周波数とも呼ばれ慣れ親しんできた。そして、その周波数から生じる位相を数学的にどう扱うかが問題となる。
一方、複雑な演算処理では乗算回数や加算回数が問題視され、アルゴリズムの効率性が問われる。そこで重宝されるのが直交関数系である。直交とは、幾何学で言うところの直角を代数的に抽象化した概念である。これを、加法や乗法で定義された多項式で考察する時、正則性や転置性といった行列式の性質を利用できるように仕組むと、演算量を大幅に減らすことができる。その際、2乗可積分関数の列として捉え、ノルムの収束性が、すなわち平均収束ってやつが正規直交系へ、さらには完備(完全)な正規直交系へと、より甘美な世界へいざなってくれる。ただし、確率論的ではあるのだが...
本書に紹介される数々の方法論もまた、直交の概念に支えられている。解析学にも、任意の物理現象を直交関係にある関数成分に分解することが、基本的な思考としてある。こいつは、線形代数における真理であろうか。やはり、バーへ向かうベクトルとクラブへ向かうベクトルも、ある次元空間上において直交関係にあるに違いない。その証拠に、今宵もまた完備(甘美)な夜の社交場へ直行するのであった...

本書はまず、離散フーリエ変換(DFT)、離散コサイン変換(DCT)、離散ハートレー変換(DHT)、ウォルシュ・アダマール変換(WFT)、カルーネン・レーベ変換(KLT)が紹介され、線形性、対称性、周期性、推移則、合成積則(巡回畳み込み計算)、相関則などの性質から離散型アルゴリズムの有用性を語ってくれる。
また、高速フーリエ変換(FFT)や高速コサイン変換(FCT)などの高速バージョンに加え、高速数論変換や高速多項式変換も興味深い。
そして、並列アルゴリズムでは、多次元FFT、遺伝的アルゴリズム、シストリックアルゴリズムが紹介され、さらに、アレイ信号処理における配置の仕方では、空間スペクトルの非線形性や分解能の考察、そしてパワースペクトルの推定にまで議論が及ぶ。
特に、高速演算を実装するプロセッサの設計において、パイプライン処理の時間的単位と並列処理の空間的配置の組合せは、幾度となくお世話になってきた概念である。シストリックアレイでは、畳込み演算、行列積和演算、IIRフィルタ、多項式除算、逐次最小2乗法に適した構造が紹介され、これらを眺めるだけでも、幸せな気分にさせてくれる...

1. 収束条件
関数列の直交展開において、基底関数に三角関数が選ばれる理由は、区間 (-π, π) において完備な正規直交系であることで、フーリエ級数は平均収束することが知られている。尚、フーリエ級数 f(x) は、よくこの形で表される。

f(x) = a0/2 + ∑(an cos nx + bn sin nx)

これの部分和、fk(x), (1 ≦ n ≦ k) において...

fk(x) = a0/2 +  k

n = 1
(an cos nx + bn sin nx)

任意のε>0 と x に無関係な m を適当に選ぶ。この時、k > m を満足するすべての k と任意の x に対して、|f(x) - fk(x)| < ε が成り立てば、fk(x) は、f(x) に一様収束するという。
ここで、有名な二つの判定条件をメモっておこう。

[Jordan の判定条件]
点 x0 ∈ (-π, π) のある近傍で f(x) が有界変動ならば、f(x) のフーリエ級数は、x = x0 で、{f(x0 + 0) + f(x0 - 0)}/2 に収束する。さらに f(x) が連続ならば、任意のε>0 に対して、区間 (a + ε, b - ε) で一様収束する。

[Dini の判定条件]
Φx(t) = f(x + t) + f(x - t) -2f(x) の時、点 x0 ∈ (-π, π) において、

π
0
   |Φx(t)|

 t 
 dt < ∞

が成立すれば、フーリエ級数は x = x0 で f(x) に収束する。

2. 高速フーリエ変換(FFT)と間引き型アルゴリズム
FFTのアルゴリズムでは、データを間引いて DFT を施し、演算数を大幅に減らすという考え方がある。代表的な Cooley - Tukey アルゴリズムもその一つ。
本書は、時間間引き型と周波数間引き型のアルゴリズムを紹介している。それは、時間方向で間引きするか、空間方向で間引きするかの違いで、基本的な演算方法は同じ。
DFTは次式で定義される。

X(k) =  N - 1

n = 0
x(n)exp ( -j   2πnk

 N 
) , k = 0, 1, ..., N - 1

W = exp(-j2πk/N) とおくと、




そして、時間間引き型と周波数間引き型のバタフライ計算は、こんな感じ...






3. 高速数論変換(FNTT: fast number theoretic transform)
FFTを利用して巡回畳込み計算をする時、次のような問題があるという。
まず、FFTの変換核 WN は、複素数の三角関数で、事前計算や WNn の保存などが必要。また、FFTの計算にはある程度の誤差が生じるという。ただし、複素数体上で巡回畳込み特性を持つ変換は、DFT だけだとか。
そこで、複素数体以外の代数体を調べた結果、整数の mod M での剰余類環 ZM 上に、DFTの構造に似たような性質があることが発見されたという。これが、「数論変換」と呼ばれる。
数論の基本では、整数と素数の関係や、最大公約数と最小公倍数の考察があり、モジュロ演算が重要な役割を果たす。大雑把に言えば、整数を、mod M で同値とみなす思考法だ。オイラーの定理やフェルマーの定理(小定理)が重要な基本定理として君臨する世界とも言えよう。
数論変換は、正の整数 M に対し、mod M での整数環 ZM 上に、次のように定義される...

長さ N の信号系列 {x(n)} (n = 0, 1, ..., N - 1) に対して、{x(n)} ∈ ZM, a ∈ ZM と仮定する。
{x(n)} を変換行列 T




で変換すると、次式が得られる。

X(k) ≡  N - 1

n = 0
x(n)αnk (mod M), (k = 0, 1, ..., N - 1)

逆変換は、次式。

x(n) ≡ 1/N  N - 1

k = 0
X(k)α-nk (mod M), (n = 0, 1, ..., N - 1)

なるほど、FFTと同型であるが、それだけでなく、巡回畳込み特性を持っていることが特徴だという。尚、物理的な意味の薄いアルゴリズムで、応用例は少ないのだそうな。古書なので今はどうか知らんが、興味深い形をしている。

4. 高速多項式変換(FPT: fast polynomical transform)
M(z) を有理数体上の多項式とし、{Pm(z)} (m = 0, 1, ..., N - 1) を有理数体上の多項式の列とすると、次式で定義される。


_
Pl(z)
 ≡  N - 1

m = 0
Pm(z)(αzd)ml   mod M(z), (l = 0, 1, ..., N - 1)

ただし、α は定数、d は正の整数。
また、次の逆変換が存在する場合、可逆多項式変換と呼ばれる。


Pm(z) ≡ 1/N  N - 1

l = 0
_
Pl(z)
(αzd)-ml   mod M(z), (m = 0, 1, ..., N - 1)

可逆多項式変換は、巡回畳込み特性を持つという。尚、本書では有理数体で記述されるが、複素数体に拡張できるようだ。
また、可逆多項式変換であるための必要十分条件は、

St = 1/N  N - 1

m = 0
(αzd)mt

とすると、次のようになるという。

St ≡ 1  mod M(z), t ≡ 0 (mod N)
St ≡ 0  mod M(z), t ≠ 0 (mod N)

5. シストリックアレイ
systolic とは、心臓の収縮を意味する。ホストコンピュータが心臓の鼓動のように規則正しくデータを演算器に供給し、データは演算器の間を血流のように脈動することから、その名が付けられたという。この言葉だけで、高度なパイプライン構造を匂わせ、演算器の配置がアルゴリズムの効率性に関わることを想像させる。ノイマン型コンピュータは、記憶部から読み出した命令コードやデータを演算器で処理し、その出力結果をメモリに戻す、といった工程を踏む。
したがって、演算器の計算能力だけが高くても、メモリとの入出力バンド幅の制限によって、システム全体の性能を引き出すことができない。いわゆる、「フォン・ノイマン・ボトルネック」ってやつだ。
そこで、複数の演算器を直列に配置し、それぞれの出力結果を記憶部に戻すのではなく、次の演算器に伝搬させながら、末端の演算器からすべての結果をまとめてメモリへ戻したり、あるいは、並列に配置して見かけ上の入出力バンド幅を大きくしたり、さらには、演算器と補助メモリを一組で配置するなど、様々な工夫が施される。こうした演算器の配置では、それぞれの処理時間を固定し、順序正しく同期的に処理することで効率を高めるなど、プロセッサの設計では、だいたい時分割処理と並列処理がセットで計画される。近年、マルチプロセッサが搭載されるケースも多く、CPU の数に比例した処理速度を引き出すために、時間的な配置と空間的な配置が重視される。
本書は、一次元シストリックアレイと二次元シストリックアレイの事例を紹介してくれる。
一次元シストリックアレイは、演算器を直列接続した構成で、畳込み演算、FIR/IIR フィルタ、行列ベクトル乗算などに向いているという。そして、演算器にローカルメモリを配置する構造も示している。
二次元シストリックアレイは、直交接続、三角接続、六角接続などが紹介され、行列積和演算には直交接続、逐次最小2乗法には三角接続、LU 分解には六角接続が、ぞれぞれ向いているという。二次元アレイ構造では、高速な処理能力を持つ反面、大規模になるほどクロックスキューや接続数の増加が深刻になり、コストも高くなる。
尚、畳込み演算用、行列積和演算用、IIRフィルタ、多項式除算、逐次最小2乗法の構成イメージは、こんな感じ... これらを眺めているだけでも、構造上のヒントを与えてくれる。












2015-12-06

"自己増殖オートマトンの理論" John von Neumann 著

ジョン・フォン・ノイマン... このプログラム内蔵方式電子計算機の創案者は、情報工学の歴史において最初のページに登場するクロード・シャノンやノーバート・ウィーナーと並び評される。1949年、彼はイリノイ大学で「複雑なオートマトンの理論と構成」と題して、5回の講義を行ったそうな。その概要は、次の3行で始まる。
  • 高速デジタル計算機の論理的構成と限界
  • 計算機やその他の自然オートマトンおよび人工オートマトンの比較
  • 自然に見出される神経系の比較からの推測
本書は、この講義をアーサー・W・バークスが編纂したものである。
「計算機と自然の有機体との間の重要な類似点と、そしてそのような異なるが関係のあるシステムを比較することの発見的な意義とを意識して、彼は、その両者を含む理論を求めた。彼はこのこれからつくる体系的理論を、オートマトンの理論と呼んだ。」

コンピュータ工学を論ずる時、論理学や情報理論が中心的な話題となるのが普通であろうが、ここでは熱力学や確率論といった不確定な性質の方に目が向けられる。特に注目したいのは、生物学との融合を唱えている点である。
「オートマトンの形式的研究は、論理学、通信理論、生理学の中間領域に属する問題である。それはこの3分野のどれか一つだけにとらわれた立場で見たのでは片輪なものになってしまうような抽象化を内包している。」
ここに題される自己増殖とは、神経系の自己複製や自己修復をも含む自立性や自律性といった機能を持つ有機体としての存在である。コンピュータ構造を論理的に記述しようとすれば、λ定義の可能性や一般帰納性との等価性、あるいはチューリングマシンの計算限界性を問うことになろう。
一方で、純粋に神経細胞モデルを構築しようとする研究の立場がある。プロセスを公理化するのではなく、基本細胞をモデル化するだけで、あとは細胞間の振る舞いと自己能力によって機能を進化させようという目論みである。単純系から複雑系への自発的移行、もっと言えば、有限チューリングマシンから無限増殖マシンへの進化とでもしておこうか。複雑な精神構造が、もともと純粋精神の原型なるものから始まったとすれば、プラトン流イデア論にも通ずる。はたして理想化された神経細胞の集合体が、どんな解を弾き出してくれるのか?これは、ノイマン流進化論である。ただし、導かれる帰結が進化か?退化か?はたまた神の創成か?悪魔の創成かは知らん...

オートマトンの理論には、複雑系に立ちはだかる二つの問題を抱えている。それは信頼性と自己増殖性の問題で、両者はトレードオフの関係にある。信頼性が複雑度の限界を決定することになるが、自己増殖性の機能を有するにはかなり複雑なオートマトンを要する。その構成には、必要最小限の器官組織と適切なサイズというものがありそうだ。人体の大きさや複雑さ、あるいは人口においても、地上で人間社会を営む上で、しかも秩序の維持と犯罪の発生確率との均衡において、適切な規模を保とうとしている。おそらく民主主義が機能しやすい規模や限界というものがあるのだろう。それが、地表面積や重力との関係から決定されるのかは知らん。
本書では、信頼度については、確率性の観点から有機体の組み立て可能性を論じ、自己増殖については、論理性の観点から最小単位である細胞構造を論じている。さらに、細胞組織の議論に論理的万能性の追求があり、こう結論づけている。
「したがって、von Neumann の 29 状態細胞構造中に、万能 Turing 機械の計算を行うことができ、かつまたそれ自身を増殖できるようなオートマトンを埋め込むことができる。」
進歩には自己触媒的な側面を持つわけだが、論理的にたった 29 の状態で万能細胞を構築できるとは、にわかに信じがたい。数学的には、非線型の問題と特異点の問題に着目し、非線型偏微分方程式に大きな役割を与えている。
実際、連続解だけが存在すべきとされる中で、突然、不連続解に重要な役割を与えることがある。生物学で言うところの突然変異ってやつだ。連続した意志エネルギーの蓄積から生じる開眼のような。連続性と離散性の協調にこそ、その真意が内包されていそうである...

1. お馴染みのコンピュータ構造
基本的な考察は、お馴染みの...
構成要素については、高速記憶装置、中央演算装置、外部記憶媒体、入出力装置、および中央制御。プログラミングについては、高度に帰納的な手続きと再帰的手続きのコード化、そしてサブルーチン化やライブラリ化といった構造的方法、及び言語系の階層構造。設計については、回路素子を速度、寸法、信頼度、エネルギー消費の面から考察し、インダクタンスやコンダクタンスが生み出す非線型な物理特性を数学的にどう扱うか。
...といったところであろうか。
本書は、理想化された計算素子を採用することに、二つの利点があるとしている。一つは、設計者が計算機の論理設計を回路設計から分離できること。二つは、オートマトン理論の方向への第一歩、つまり、理想的な神経細胞、記憶器官の採用にほかならないこと。人間がいかに自分自身を論理的に設計できるか?これが自然オートマトンの投げかける問いである。
とはいえ、オートマトンの理論には、素子の故障確率までも含まれる。数理論理学では、理想化されたスイッチと遅延素子の完全性、すなわち決定論的な操作しか扱わないが、現実世界では、故障や誤動作への対処の方が重要となる。
したがって、連続的数学と離散的数学の双方を扱うことになり、解析学的にならざるをえない。具体的には、アナログ制御とデジタル制御の協調、そして、複雑な連立非線型偏微分方程式を解く能力を自己に問うこと。今日、デジタル時代と言われながら、設計現場では、微小信号の検知、高周波制御、省電力設計などで高度なアナログ技術が要求される。すべてをイエスかノーかの二項対立というビット概念で制御できればいいが、しばしば回路素子の遅延が問題となる。プラグラミングとは、スイッチの関数表を構築するようなもので、遅延は厄介な問題だ。位相の小さい信号に対しては、制御が容易であっても、一旦発振が始まると、高度な安定発振の状態に陥り、制御不能となる。ただこれを、神経系の応答時間としてモデル化することはできそうか...

2. 五つの自己増殖モデル
ノイマンは、オートマトンモデルを論理の側面と組立の側面から追求している。そして、論理的万能性、組立可能性、組立万能性、自己増殖性、進化性の面から論じ、五つのモデルを考案している。

[運動学的モデル]
プロセスやアルゴリズムなどの処理手順の観点から、運動、接触、位置決め、融合、切断などの幾何学的運動を扱う。尚、力やエネルギーの問題は無視。その基本構造は、感覚的要素(知覚のような)、運動的要素(筋肉のような)、論理的要素(分岐)、記憶要素(遅延)などで構成され、情報を蓄えて処理する。

[細胞モデル]
論理学的、数学的に扱うには、運動学に着目するよりも、細胞に着目した方が構成がイメージしやすい。全く同じ有限オートマトンが各細胞に組み込まれ、無限空間において自己増殖を促し、次世代の生成を促す。各細胞は 29 の状態を持つ有限オートマトンで構成され、隣接する四方の細胞と直接に1単位時間か、それ以上の遅延を伴って通信し合う。数学的には、行列でモデリング。

[刺激 - 閾 - 疲労モデル]
細胞モデルを基礎とする。無限構造の細胞モデルに 29 状態のオートマトンを採用し、疲労と閾値の機構を追加。より現実組織に近い神経細胞モデルとして、絶対不応期と相対不応期の概念を組み込む。神経系に、ある刺激によって活動電位が一度発生すると、二度目の刺激では反応が低下し、興奮も和らぐ。この時期が不応期であるが、全く興奮しない時期が絶対不応期で、多少の興奮をともなう時期が相対不応期である。相対不応期の活動電位は、振幅が小さく、伝達速度も遅い。疲労度によって興奮する閾値が変化し、抑制能力も変化するという仕掛け。スイッチ作用、出力の遅延、作用を制御するための内部記憶、そしてフィードバック作用を組み合わせた構成。

[連続モデル]
まだ未完成のモデルだが、液体中の拡散過程を示す連立非線型偏微分方程式を採用する予定だったようである。解析学の技法を用いて、自己増殖の連立偏微分方程式を、刺激 - 閾 - 疲労モデルと結びつける構想だったとか。数学的な問題は、神経細胞の興奮作用、閾作用、疲労作用を記述する偏微分方程式を定式化すること。神経細胞は、他の神経細胞からの入力によって刺激され、これら入力刺激の合計が神経細胞の閾値に達すると、細胞体の外から内へナトリウムイオンが流れて興奮させる。イオンの流れ、すなわち拡散によって細胞体が脱分極される。この拡散と脱分極が軸索、すなわち神経繊維を伝わって神経細胞の発火となる。発火後、カリウムイオンが神経細胞の内から外に拡散して、神経細胞を再び分極する。ナトリウムとカリウムの化学平衡は、やがて回復する。化学的な拡散が基本的な役割を演じるという仕掛け。ノイマンは、連続モデルと称しながらも、非線型な拡散型偏微分方程式を選んだという。
それは、離散性から連続性への回帰という道筋が示されるかのような。あるいは、連続系の微分方程式を離散系の差分方程式で置き換え、デジタル計算機によって近似解を求める道筋とも言えようか。いずれにせよ、偏微分方程式の境界条件が重要な役割を演じることになる。連続モデルと細胞モデルの対比は、アナログ計算機とデジタル計算機の協調という見方もできよう。

[確率的モデル]
ノイマンは、生涯を通じて確率論の応用に興味を持っていたという。状態遷移が決定論的に決まるのではなく、確率的であるようなオートマトンとは?自己増殖、すなわち進化を論じるからには、やはり突然変異を無視するわけにはいかない。とはいえ、自然淘汰説の定量化とは途轍もない構想と言わねばなるまい。状態の考察では、論理学では真と偽、神経細胞では興奮と静穏、そして、入出力、刺激と応答、枝分かれ... といった具合に展開され、こららの論理積、論理和、否定などの基本操作で、単純なステートマシンを構築するイメージ。静穏検出では、興奮可能性と興奮不能性を区別し、機能不全をも含み、さらに潜像状態が考察される。潜像を持ち出すのは、幻想や幻覚の類いまでもモデル化しようという魂胆か?そして、効率の悪い単純で弱いオートマトンが、効率の良い複雑で強力なオートマトンにいかにして進化できるかを問う。

3. 29状態オートマトンの雰囲気を記述してみよう...
まず、単純な二次元正方格子から、状態の関係を時間と空間において定式化する。座標 θ = (i, j) によって指定される領域を、ベクトル空間上で加法的量として捉える。その最近隣は、(i±1, j), (i, j±1) の4点と、斜め隣りの (i±1, j±1) の4点。状態遷移は、この二次元空間を無限に動き回る。

  ν0 = (1, 0)
  ν1 = (0, 1)
  ν2 = -ν0 = (-1, 0)
  ν3 = -ν1 = (0, -1)
  ν4 = (1, 1)
  ν5 = (-1, 1)
  ν6 = -ν4 = (-1, -1)
  ν7 = -ν5 = (1, -1)




しかしながら、細胞構造の論理的万能性を、ひたすら二次元空間に求めている点は、ちと抵抗を感じないではない。各細胞の連結を三次元空間で構想すれば、遷移の方向を立体交差で考察でき、より細胞器官モデルに近づけられるはずだが。あるいは、伝達関数を簡略化するための戦略であろうか?ノイマンは、どうやら自己増殖オートマトンを二次元で構成したかったようである。

次に、普通刺激を T0、特別刺激を T1 といった具合に記述し、伝達状態、合流状態、興奮不能状態、潜像状態を定義する。

伝達状態 Tuae
  u = 0, 1 : 普通刺激と特別刺激
  a = 0, 1, 2, 3 : 右、上、左、下
  e = 0, 1 : 静穏状態と興奮状態

合流状態 Cee'
  e = 0, 1 : 静穏状態と興奮状態
  e' = 0, 1 : 次に続く静穏状態と興奮状態

興奮不能状態 U

潜像状態 S
  ∑ = θ, 0, 1, 00, 01, 10, 11, 000




さらに、これに加えて次の∑に対する S が定義される。
  ∑ = 0000, 0001, 001, 010, 011, 100, 101, 110, 111
尚、これは、Tua0 と C00 を T000, T010, T020, T030, T100, T110, T120, T130, C00 の順にとったものと同じ。




そして、全部で、伝達状態 16(2 x 4 x 2)、合流状態 4(2 x 2)、興奮不能状態 1、潜像状態 8 の 29個になるというのである。へ~...

4. 遷移規則の雰囲気を記述してみよう...
有限オートマトンは、前述のように 29 状態を持つとされる。無限オートマトンは、この有限性に初期状態を与え、その後は、単位時間 t における細胞状態と4つの直隣りの細胞状態への遷移だけで拡張されていく。そして、時刻 t+1 における細胞状態は、遷移規則によって決定している。その遷移の概略はこんな感じ...

種類名称記号個数遷移規則の概略
興奮不能U1 直接過程は U を潜像状態に変えて、その後、Tua0 か C00 へ。
逆過程は、Tuae や Cee' を殺して U へ。
普通刺激合流Cee'4 自分に向いた T0ae から論理積で受け、自分に向いていないすべての Tuae へ2倍の遅延で発信。
自分に向いた T1a1 によって殺されて U へ。殺す作用は受信より優先。
伝達T0ae8 自分に向いた T0ae から及び Cee' から論理和で受け、出力方向へ。
  a) 自分に向いていない T0ae へ、および Cee' へ、
  b) U または潜像状態へ、直接過程として、
  c) T1ae へ、逆過程で殺すために、
単一の遅延で発信。
自分に向いた T1ae によって殺されて U へ。殺す作用は受信より優先。
特別刺激T1ae8 自分に向いた T1ae から及び Cee' から論理和で受け、出力方向へ。
  a) 自分に向いていない T1ae へ、
  b) U または潜像状態へ、直接過程として、
  c) T0ae または Cee' へ、逆過程で殺すために、
単一の遅延で発信。
自分に向いた T0ae によって殺されて U へ。殺す作用は受信より優先。
潜像S8 これは直接過程の中間状態(参照図:中間状態における遷移)。
U に向いた Tua1 は Sθ へ。その後、S は、
  a) 一つでも Tua1 が自分に向いていれば、S∑1 へ。
  b) それ以外は、S∑0 へ。
そして、Tua0 または C00 になることによって直接過程は終了(参照図:直接過程における遷移)。