26
表現系工学特論第3回 (1)逐次プログラムの正当性(3)ホーア論理 それでは始めます。今日は逐次プログラムの正当性というテーマの第3回目で、実は今 日が最終回になります。第1回目と第2回目で話した内容で大体良いのですけれども、今 日はもうちょっと科学的に洗練された内容の話をします。副題が付いていますが、ホーア 論理です。ホーアという有名なコンピュータ・サイエンスの科学者がいます。その人が考 えたもので、その人の名前にちなんでホーア論理と呼ばれていますけれども、それについ て話をします。 (2)1.構造化定理(1/5)スパゲティ・プログラム それで最初にまず準備運動というか事前の知識として構造化定理、構造化プログラミン グについて知識を確認したいと思います。これは学部でも習うようなことですので、簡単 に話をしますけれども、この構造化プログラミングというものに対してホーア論理という 理論が構築されているのです。それでこれをちょっと話しておきます。 コンピュータというのは内部的にはすごく細かい命令がたくさん、機械語というのはほ んのちょっとの仕事しかしないです。そういうのを組み合わせてプログラムを作る訳なの ですけども、当初、1950年代とかそれ以前のすごく古い時代にはこういう流れ図、フ ローチャートというものを書いてソフトウェアを設計していたのです。現在でもそういう ことはある程度やっています。それでそれをやり出すと、コンピュータの機能をフルにこ ういうフローチャートで利用できるのです。こういうところが1つ1つの命令なのですけ ども、何々をやって次何々をやる、菱形のところは判定です。何かを判定して真だったら、 yes だったらこっち、偽或いは no だったらこっちに行くという枝分かれがあります。それ でこの飛び先を後ろの方にするとここでループを構成できたりとか、それからこの条件に 応じて、もし、 if then else のようなものを作れたりとか、この長方形の普通のボックスと、 菱形の枝分かれのボックスを組み合わせると、コンピュータができることなら何でもでき る、というようなことでこういう設計がなされていたのですけども、どんどんソフトウェ アが大規模になると、こういう絵を描いていくと何が何だか分からなくなる。これは授業 で作ったスライドなのでこれは単純な方ですけども、それでも全体として把握できないで す。どこで何をやってこのループがいつまで回るのかとか、そういうことの全体が把握で きない。それから線が交差したりして見難くなったりとかしています。こういうような流 れ図、或いはプログラムをスパゲティ・プログラムという風に呼ぶようになったのです。 スパゲティというのは、皆さん方知っているようにイタリアの食べ物です。パスタの一 種です。あれで食べるとスパゲティがいろいろ絡まっています。わざとフォークに絡めて

表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

表現系工学特論第3回 (1)逐次プログラムの正当性(3)ホーア論理 それでは始めます。今日は逐次プログラムの正当性というテーマの第3回目で、実は今

日が最終回になります。第1回目と第2回目で話した内容で大体良いのですけれども、今

日はもうちょっと科学的に洗練された内容の話をします。副題が付いていますが、ホーア

論理です。ホーアという有名なコンピュータ・サイエンスの科学者がいます。その人が考

えたもので、その人の名前にちなんでホーア論理と呼ばれていますけれども、それについ

て話をします。 (2)1.構造化定理(1/5)スパゲティ・プログラム それで最初にまず準備運動というか事前の知識として構造化定理、構造化プログラミン

グについて知識を確認したいと思います。これは学部でも習うようなことですので、簡単

に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

理論が構築されているのです。それでこれをちょっと話しておきます。 コンピュータというのは内部的にはすごく細かい命令がたくさん、機械語というのはほ

んのちょっとの仕事しかしないです。そういうのを組み合わせてプログラムを作る訳なの

ですけども、当初、1950年代とかそれ以前のすごく古い時代にはこういう流れ図、フ

ローチャートというものを書いてソフトウェアを設計していたのです。現在でもそういう

ことはある程度やっています。それでそれをやり出すと、コンピュータの機能をフルにこ

ういうフローチャートで利用できるのです。こういうところが1つ1つの命令なのですけ

ども、何々をやって次何々をやる、菱形のところは判定です。何かを判定して真だったら、

yes だったらこっち、偽或いは no だったらこっちに行くという枝分かれがあります。それ

でこの飛び先を後ろの方にするとここでループを構成できたりとか、それからこの条件に

応じて、もし、if then else のようなものを作れたりとか、この長方形の普通のボックスと、

菱形の枝分かれのボックスを組み合わせると、コンピュータができることなら何でもでき

る、というようなことでこういう設計がなされていたのですけども、どんどんソフトウェ

アが大規模になると、こういう絵を描いていくと何が何だか分からなくなる。これは授業

で作ったスライドなのでこれは単純な方ですけども、それでも全体として把握できないで

す。どこで何をやってこのループがいつまで回るのかとか、そういうことの全体が把握で

きない。それから線が交差したりして見難くなったりとかしています。こういうような流

れ図、或いはプログラムをスパゲティ・プログラムという風に呼ぶようになったのです。 スパゲティというのは、皆さん方知っているようにイタリアの食べ物です。パスタの一

種です。あれで食べるとスパゲティがいろいろ絡まっています。わざとフォークに絡めて

Page 2: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

食べたりする訳です。そういう状態からそういうことをスパゲティ・プログラムという風

に言われています。これはあまり良くないという概念で言われています。こういうプログ

ラムは良くない。スパゲティのように線がぐちゃぐちゃになっていて、何が何だか全体が

よく分からないようなものは良くない。自分がプログラムを書くうちはまだ全体を把握し

ているのでしょうけれども、3ヶ月も経って機能をバージョンアップするとか、バグがあ

ったのでどこか直さないといけないとか、そういう時、自分が書いたプログラムでも2、

3ヶ月経てばもう何が何だか分からなくなる。ましてや他の人に見せるともっと分からな

い。他の人というのは、例えば自分のチームを組んで、そのチームの人にここを直して、

こういうところを直しなさいとか、こういう機能を付け足してくださいという風に自分の

ソフトを新人の人に見せたりするかもしれないです。そういう時に他人から見るともう全

然分からないということで、プログラムがうまく、正しく作れなくなる。一旦正しく作っ

たプログラムでも、バージョンアップが正しくできないとか、正しくできたにしても非常

に時間が掛かる。ソフトを作るのに時間が掛かるということは人件費が掛かるので、その

ソフトは値段を高くして売らないといけませんので、他の似たようなソフトとの価格競争

で負けます。ですからビジネス的にはあまり良くない訳です。そういうようなことで、こ

ういうことはソフトウェア工学上良くないという風にされています。英語で Spaghetti program と言います。

それで、こういう状況を論文に書いたのが、Dijkstra という人です。これはオランダの

コンピュータ・サイエンスのプログラミングを研究していた人で、5、6年前か10年前

かそれくらいに亡くなった人なのですけども、この人は非常に有名なのでいろいろな論文

を書いていますけれども、今回これに関する論文として、Go To Statement Considered Harmful という論文を書いています。アメリカの ACM というコンピュータ関係の学会の

論文誌に出しているものですけれども、これを直訳すると、Go To Statement というのは、

go to 文ということです。何々文、IF 文とか何とかという文を Statement と言います。go to文。これは皆さん方は C 言語とか習っているから go to 文なんかは見たことないかもしれな

いですけども、一昔前のプログラミング言語には必ず go to 文というのがあったのです。 私が学生の時に習ったプログラミング言語は FORTRAN という、今でも使われています

けれども主に数値計算の分野で使われています FORTRAN です。その後パソコンが普及し

だすとパソコンに最初からただで入っているプログラミング言語で、BASIC というのがあ

ったのです。その後 BASIC は高校の数学の中の、受験勉強用の数学ではないのですけれど

も、高校でもう卒業するような人の数学の部分にコンピュータのことも教えるということ

で、ここで BASIC を教えることになっていました。というようなところ、そういう

FORTRAN とか BASIC とか、そういう古いプログラミング言語には必ず go to 文というの

があったのです。それは何なのかというと、go to 何々、例えば go to 10とか数字で書く

場合もあるし、ラベルを自分で付けて go to START とか、どこそこへ行けという命令なの

です。それをこういうところに書くと、要するに矢印はどこにでも行けるのです。go to ど

Page 3: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

こそこというと、どこそこという場所に矢印を結べというようなことなので、それさえ使

えばこういうスパゲティ・プログラムは容易に作れるのです。 それでこの Dijkstra が言ったのは、こういうスパゲティ・プログラムになるのは、そも

そも Go To Statement、go to 文があるからなのだと。それと Considered Harmful。Harmfulというのは有害だということです。害がある。Considered というのは何々と見做すという

意味なので、go to 文は有害だと見做される、ということで、go to 文有害説という風に言わ

れています。これは今から思えば大したことではないように思う、今は常識なのですけれ

ども、その当時は非常に画期的なと言いますか、本当にそうなのかという議論を呼ぶよう

な論文だったのです。何故かというと、その当時のプログラミング言語、さっき言ったよ

うに BASIC とか FORTRAN とか普通の人が使っているプログラムに go to 文があって、

go to 文を使わないとまともなプログラムが書けなかったからです。枝分かれしないような

一本道、上から下までただバーっと流れていくプログラムは当然書けますけども、それで

はまともなプログラムが書けないです。ですから条件に応じて枝分かれをして、場合によ

っては上に戻って行ってループを構成したりとか、そういうことをやるには go to 文を使わ

ないとできなかったのです。ですから go to 文が有害だと言われてもしょうがないではない

かと、それ無しではプログラムが書けないのです。ですからこれは非常に大変なものだっ

たのです。 それで私もこの論文を読みましたけれども、発表した当時は当然学生だから見ていなか

ったのですけども、10年くらいしてから見ましたけども、ページ数は1ページくらいな

のです。左右2段にはなっていますけども、1ページではそういう意味でなかったかもし

れないです。或いは1.1ページくらいだったかもしれない。2ページはとにかくなかっ

たです。1ページくらいの論文なのです。ですからその中に圧縮してその人の考えが詰ま

っているので、すごい短く書いているので、読んだ人もよく理解できなかったのかもしれ

ないです。でも私もはっきり言ってあまりよく理解できなかったです。というような、今

から思えばすごい影響力のある論文だった。そこでそういうことを言っているのです。 それでそれを確かにその通りだと思った人がある意味では偉くて、ではどうすれば良い

のかというので、go to 文がなくてもプログラムを書けるようなプログラミング言語とかこ

ういうものが発明され出しまして、C 言語がそうなのです。go to 文というのを皆さんが仮

に知らなくても、プログラムを書けます。という風に今はなっているのです。そういうも

のを構造化プログラミングという風に言っています。 (3)1.構造化定理(2/5)構造化定理 その基礎となるのが構造化定理という数学的な定理で、これは Dijkstra が証明した定理

なのですけども、これはこういうものです。任意の流れ図、任意のフローチャートを考え

ます。どんなフローチャートでも良いから持ってきてください。どんな複雑でも良いです。

Page 4: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

それでこれから説明する3つの基本構造というのがあるのです。これは今ここに3つ後で

書きますけど、今スキップしておいて、その3つを組み合わせることによって、それと等

価な、equivalent と言います、それと同じ動作をする構造化流れ図、structured flowchartというものを作ることができます。これはスパゲティではない流れ図です。線が重なった

りしないのです。今から思えば当たり前の、C 言語を知っている世代にとっては当たり前の

ものなのですけど、そういうものを作ることができるということを、経験則ではなくて数

学的に証明したのです。 その3つの基本構造というのは普通学部で習うことですので、皆さん方ご存知かと思い

ますが、concatenation、日本語で連接と言ったり、或いは他の和訳が与えられることもあ

ります。2つの文をただセミコロンでくっつけるというのです。これをやってからこれを

やるという順番を、シーケンスを表すものです。 それから selection、選択という。これは今の言葉で言うと IF 文なのです。もしこうだっ

たらこっちを実行して、そうでなければ ELSE の後ろを実行しなさい。それなのです。そ

れを選択、selection と言います。 それから repetition、反復。これはループなのですけども、ループの中でも前判定反復と

いってループの入り口で判定して、そこで条件に合えばもう1周するのですけども、条件

に合わなければすぐ出てしまう。そういう単純な、特別なループです。一番単純なループ

です。後でもう1回説明します。 この3つだけを組み合わせると、どんな流れ図でもどんなスパゲティ状態のプログラム

でも、整然としたフローチャートにすることができると言っているのです。それをもうち

ょっと詳しく説明します。それでこの定理に基づいて、この3つの中には go to 文が入って

いないのです。これによって、要するに go to 文がなくても、go to 文だらけのすごいぐち

ゃぐちゃなフローチャートでも、この3つを使った go to 文のないプログラムにできるとい

うことを証明したということです。そういう訳で go to 文を使わないでこの3つを使ったプ

ログラミングを、構造化プログラミングという訳です。そしてこの構造化プログラミング

をサポートする構造化プログラミング言語というのがいろいろできまして、そのうちの1

つが皆さん方の知っている C 言語です。C 言語だけがそうだという訳ではなくて、たくさ

んあるのです。現代的なプログラミング言語は皆構造化プログラミング言語です。 ただし、この3つだけを使うと、確かに数学的にはできるのですけど、人間の感覚とし

て何となくプログラミングしにくいということがあるのです。ですので、あまり厳格的に

こればっかりやると、ちょっと実際上能率が落ちるということがあるので、現実的には

return と break くらいは許しているのかと思います。この return と break というのは C言語向きの言葉で書いています。return というのは、go to 文でどこか突然ぴょんと飛んで

しまうのですけども、今定義している関数とか手続きがあります。そこから抜け出て行く

という go to 文です。どこに行っても良いという go to 文ではないです。特別なところに出

て行く go to 文です。

Page 5: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

それから break というのは、ループの中から抜け出る go to 文なのです。これもどこに飛

んでも良いのではなくて、ループの中から抜け出るだけの go to 文です。そういう特別な go to 文だけは許しているのかな、というのが現状なのです。これだと充分 return とか breakとか入れたからすごいプログラムが分かりにくくなったという話はあまりないです。これ

は現実的な考え方だと思います。 しかし今日は return、break は考えないで、あくまでも原理に沿ってこの3つだけを使

ったプログラムだけを扱います。

(4)1.構造化定理(3/5)3つの基本構造 それでもうちょっと分かりやすい例なのですけども、この連接というのは、よく S1とい

う文、Statement、S2という Statement があるとそれをセミコロンで間を区切ることがあ

りますけど、こういう書き方をすることが多いです。概念としては、何かをやった後何か

をやる、順番通りシーケンスに沿って何かをやるという、そういう構造です。 今ここに SF と書いてあるのは、Structured flowchart、構造化流れ図というのですけど

も、S1というのはすごくぐちゃぐちゃの流れ図、スパゲティ状態の流れ図で表されるもの

だとします。それをこれから今説明する方法で、構造化流れ図にするのです。そしてその

後ろに S2を構造化流れ図にしたものを繋げば良いということです。こういうものはこうい

う風にすれば構造化流れ図というきちんとした流れ図になりますという、具体的な方法を

今これから示すのですが、その1つ目がこれです。ただこれを見てもまだピンとは来ない

と思うのです。最後まで行くとピンと来ます。 それから次選択という2つ目の構造は、if C then S1 else S2 end。C 言語は then とか

書かないで C の周りにかっこを付けたりとか、文法はプログラミング言語によっていろい

ろ違いますけど、これは実際のプログラミング言語でいえば Pascal というのに似てたり、

或いは Modula とか、いろいろなプログラミング言語に見掛けはいろいろ違うのですけど

も、要するに C という条件を判断して、真か偽かを判断して、真だったら S1を実行してお

しまいと、偽だったら S2を実行しておしまいと。そういう、皆さんご承知の IF 文です。

それを選択と言います。これが C のところとか S1、S2のところがすごいぐちゃぐちゃにな

っているとします。スパゲティ状態になっているとします。それをどうやってスパゲティ

状態ではなくするか、綺麗なものにするかというと、こういう流れ図にしなさいというの

です。まず C であることを判定します。そして真だったら S1を今説明中の方法で構造化流

れ図にしなさい。ここにいろいろなスパゲティ状態ではない綺麗な流れ図を作ります。そ

れでこっち側は S2を綺麗な流れ図にしなさい。それで出口の物をまた1つに繋ぎなさいと

いうようなことをすれば良い。これは皆さん方からすれば当たり前だと思うのですけど、

そういうようにします。 さっき言いましたように、私が学生の頃は IF 文はなかったのです。IF 文はあったのだけ

Page 6: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

ど、こういう then if then else というのはなかったのです。例えば FORTRAN とか BASICだったら、if C まではあったのです。then くらいまではあったのですけど、then S1までは

書けたけど else if 以下は書けなかったのです。私が学生の頃は。そういう場合どう書いた

かというと、if C then、then の後に go to 文を書いたのです。もし C が成り立ったら then go to どこそこ、どこか他のところに行ってしまいなさいと、そこに S1が書かれています。

else がないものですから C が成り立たない時はそのまま真下に来るのです。その真下のと

ころに S2を書いているのです。だからこの IF 文のすぐに S2を書くのでそこは読みやすい

のですけども、C が成り立った時の S1がどこにあるか分からないのです。どこか離れたと

ころに書いてあります。ですので結構読むのが大変です。何ページもあるプログラムだっ

たらこうひっくり返しながら読まないと、読めなかったのです。ですから私が確か大学院

生くらいの時に、if then else というのが、そういうものがあるのだなということが分かっ

て、すごく衝撃的な事実だったのです。 それでこれの良い点は、ここが終わった後また一緒になるところが画期的なのです。終

わった後です。ここを見ても当たり前なのです。選択というと if C then 何々だから、枝分

かれするところだけ強調されます。条件に応じて処理の流れを変えられます。枝分かれが

何か重要そうに見えるというところですけども、それは当たり前なのです。コンピュータ

はそれができるのが当たり前なのです。ですからここは別に大した重要なことではなくて、

それぞれの処理が終わった後、また一緒に合流することが重要なのです。つまり私が学生

の頃の go to 文というのは、こんなことはなかったのです。ここから枝分かれした後、どん

どん発散してどこに行っても良い訳です。どういうようなプログラムでも書けたのです。

でもこの IF 文を使うということは、それぞれ何かやった後絶対にまた一緒になれという、

そういう強制力が働いています。ですから自在にプログラムを書けないのです。ですから

そういう強制力を働かせることによって、何でも書ける訳ではないという風にしているの

です。でも理論的には頑張れば何でも書けます。それが選択というのです。 それから3つ目は反復というループなのですけども、ここで言っているループはこうい

うタイプのループだけです。よく知られているプログラミング言語では While 文と呼ばれ

るのですけども、While の後に何か条件が書いてあります。真か偽かなのですけども、真だ

ったらその後のループの本体と言われるものを1回だけ実行するのです。そしてまたここ

の C の判定に戻ります。この C の判定結果が偽、no だったら、この While 文は終了する、

そういうものです。ですから絵で書くとこういうもので、上からこうやって来たらまず Cという判定をします。それで真、true だったら S を実行するのですけども、ここは S とい

うのはすごいスパゲティ状態の流れ図だったら、Structured flowchart にします。構造化流

れ図にします。そして出口から C の頭にまた戻ってくる、こういうループです。そして Cが false だったらここで出て行く、これでループが終了しますので、この次に、while 文の

次に書かれているところに進む。ですからこのループの特徴は、ループに外側から入って

来たらいきなり C の判定があるということと、成り立ったら中を1回実行するのだけど、

Page 7: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

ここからまた手足が出て行っていないということです。この辺からまた矢印が出ていてど

こか飛んで行っているということがないです。この範囲内に留まっていて、そこからまた

こう出て行く。出入り口が1ヶ所しかない訳です。入口はここです。出口はここ。出口も

入口も1ヶ所しかない。そういう特別なループなのです。ここでは反復と言います。或い

は前判定反復という風にわざわざ言うことがあります。このループの本体を実行する前に

判定します。前判定反復とも言います。 この3つだけ組み合わせれば、どんなぐちゃぐちゃの流れ図も整然と書けるというもの

なのです。それは証明しませんけれどもほとんど明らかかと思います。これに着目してく

ださい。この構造化流れ図というのは出入り口はそれぞれ1ヶ所だということです。それ

から流れを表す線が絶対交差していないのです。まずここなのですけども、この四角が一

番単純な代入文とか何とか、非常に単純なものは出入り口が1ヶ所なのは当たり前です。

そういうのをこういう風にどんどん組み合わせて行っても必ずそうなるということなので

す。 それでまず連接の場合なのですけども、ここで S1というのはそういう単純な代入文では

なくてもっとすごく複雑なものだとします。S1自身が While 文とか IF 文かもしれないで

す。そういう複雑なものでも、数学的帰納法のような考え方をしてほしいのですけども、

数学的帰納法の過程として、S1の文がちゃんとこの条件を満たす、S2の文も結構複雑なの

ですけどこの条件を満たすと、それを数学的帰納法の帰納法の過程とます。n=k の時に成

り立つこととかというあれです。そうやった時にもっと複雑にしてセミコロンで繋いだ、

もっと複雑なプログラムもこれを満たす。つまり n=k+1の時も満たすと、そういう数学

的帰納法のような考え方で考えてください。そうするとここの部分は、その数学的帰納法

の過程によって出入り口はそれぞれ1ヶ所です。それから流れを表す線はこの中では交差

してないとします。スパゲティ状態にぶつかってないとします。これもそうだとします。

そうすると、この2つをこういう風に縦に並べて線で繋いだものもこれを満たしているの

は明らかです。出入り口はまず1ヶ所です。入口は1ヶ所、出口は1ヶ所です。それから

ここが、線が交差してなくてここも線が交差してないので、全体としても線が交差してな

いです。ですからこれは明らかです。 それから今度こっちの選択の方ですけども、ここのところも出入り口が1ヶ所です。こ

れも出入り口が1ヶ所。内部は線が交差してないとします。そうする時にこういう構造を

作った時に、全体としてやはりこれが成り立ちます。まず入り口が1ヶ所です。出口が1

ヶ所です。それからこことここが線が交差してないし、新たに線を引いたところも線が交

差していませんので、全体として線が交差していないです。それからこのループもそうな

のですけども、ここも出入り口が1ヶ所になっています。この四角の中に線が交差してな

いとします。その時にこういう菱形とかこんな矢印をくっつけて、より複雑な絵を描いた

時にも、出入り口は1ヶ所です。入口はここ1ヶ所で、出口はここ1ヶ所。ループのこん

なところから出て行ったりしません。それからここの中に線が交差してなくて、後から付

Page 8: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

け加えたところでも線が交差していませんので、全体として線が交差してないです。それ

で Dijkstra が後証明したことは実際にこの3つの構造だけでどんな流れ図でも表現できる

と言っているので、その2つのことから、そっちの方はちょっと証明が難しいのですけど

も、どんな複雑なスパゲティ状態の流れ図でもこの3つで必ず書き直すことができて、全

体として出入り口が確実に1ヶ所ずつで、線がどこでも交差していないということが、数

学的に証明できたということになります。

(5)1.構造化定理(4/5)前判定反復への変換 それでその Dijkstra が言った、どんなものでもこの3つで表せるというところがその証

明が難しいところですけども、今ここで証明してもしょうがないので、ヒント、こんなよ

うな考え方をするのだということだけを、例題でもって説明します。 これはよくあるものなのですけども、何かデータを入力して、その入力を見て終わりの

印というのがあって、これで終了かということを判定します。データは正の数であって最

後に0を入れるとかよくあります。これが終了だったら終わる。終了でなかったら、今入

力したデータを何か処理して、また次のデータを入力する。これはよくありますよね。こ

れは今説明したループではないです。上から入ってきていきなり菱形にならないと駄目で

すから、これです。上から入ってきて、いきなり菱形があるものだけを言っているのです。

そうではないのは、さっきの Dijkstra の考えているループではないです。ですからこれを

さっきのように変形しないといけないのですけども、これはこうやれば良いです。 まずループの外に入力の部分を作ります。その後終了かと判定して、yes だったら抜ける

のは同じです。No の時は処理をするのは同じなのですけども、その次に無駄のような気が

しますけど、もう1回同じようなことをわざわざここに書く、コピーしてここに書く。そ

れから戻れば良いのです。そうすると、見掛けはちょっと違いますけどやっていることは

同じです。入力・終了・処理、入力・終了・処理、これをずっと繰り返していつかは終了

する。こういうループです。こっちも入力・終了・処理、入力・終了・処理、入力・終了・

処理、こういうループを繰り返していつかは終了します。ですから同じことなのです。そ

うするとこっち側のループは Dijkstra の言っていた前判定反復にちゃんとなっている訳で、

さっき言った3つの構造だけでちゃんと書き直したことになります。ちなみにここは1個

だけしかなかったのが、ここは1つ目の連接、シーケンスを表すものに直しています。そ

れからこの何だか分からないループはきちんとした反復に直しています。

(6)1.構造化定理(5/5)変換の例 それから今度はこういう奴です。これはあまりこんなプログラムは最近あるかどうか分

からない、ないことはないか。上から来たら C1という判定をします。Yes か No かで分か

Page 9: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

れるのですけども、Yes だったら D をやった後下りておしまい。No だったら A という処理

をやってまた C2という判定をします。Yes だったらいきなりこれで終わりです。No だっ

たら何か B という処理をやってここに戻ります。ですからここでループが加わるのです。

このループは入ってきていきなり菱形があると言えば良いのですけども、この中からまた

出口が出てくる。このループの出口が2か所あります。こういうのは駄目なのです。 それでさっきのようなものに直せるかどうかということなのですけども、それはこうい

う風にします。2ヶ所から出ていっているのですけども、こっち側は良い訳です。さっき

の入り口のところの菱形から出口が出ているのでこれは許すとして、これはどう考えても

許せないです。ですので、ここから抜け出たいのはやまやまなのだけれども、こういう風

に抜け出させないのです。抜け出ることをやめさせるのです。その代わり抜け出る条件は

整ったということで、フラグ、F という変数です。フラグ、旗という風に呼びますけど、旗

は最初降ろしておく、false にしておくのですけども、C2が Yes になることによって抜け

出る条件が整ったら、そのフラグを立てる、F を true にする。これが No だった場合はま

だ抜け出られないということでフラグは false のままです。こういうような印を付けておい

て、ぐるっと我慢させておいてここに来た時に抜け出る判定をちょっと変えて、C1でも抜

け出て良いのだけども、フラグが true の時、旗が立っている時も抜け出て良いということ

で、C1が成り立つか又はフラグが true の時は抜け出て良いと、そういう風に直します。

この内部はここと同じです。抜け出るのですけども、同じ抜け出たのでも C1で抜け出たの

なら D をやらないといけない。C2で抜け出たのなら D はやらなくて良いのです。それを

書かないといけないので、抜け出た後フラグが true かどうかを判定します。C1で抜け出

た時は、こっち側からこう来てますのでフラグは false の筈です。最初も false ですし、下

から来た時も false です。それか C2で Yes だった時だけ true の筈なので、それを判断し

てフラグが false の場合は D を実行します。そして終わる。フラグが true の時はそのまま

終わる。こういう風にすれば良いのです。というようなことをいろいろ頑張れば、こうい

う風に書けます。こう書いた結果、ちゃんと構造化流れ図になっているということです。

これは IF 文です。C2が true だったらこれ、false だったらこれで、いずれにしても合流

しますという風に、きちんとした IF 文になっています。それからこのループ全体は入口に

菱形があって、何か条件が成り立ったら何かをやって、このループの本体全体は明らかに

構造化流れ図で、IF 文と A を連接しています。連接したものもまた構造化流れ図です。で

すから菱形があって、何か本体がきちんとしたものがあって、またここに戻ってくるとい

う Dijkstra が言っている前判定反復のループになっています。それからここもきちんとし

た IF 文になっています。一旦枝分かれしますけれどまた合流しています。そして全体とし

てはこの前処理とこのループと後処理が、この3つが連接されている、上から順番に3つ

並んでいる形になっています。ですからこれは構造化流れ図になっています。最初説明し

ました3つの構造だけを使った流れ図になっています。 こういうことを頑張れば絶対にできるのです。それで Dijkstra の偉いところは、これが

Page 10: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

何でやっても必ずできると証明したことです。具体的に与えられれば我々プログラミング

が得意な人は一生懸命頑張ればこう直せるのですけども、Dijkstra はここは何でやっても

こういう風にすれば直るということを一般的に証明したので、天才的なところなのです。 (7)2.論理と推論 それでここからの今日の話ですけれども、そういう構造化プログラミングだけを今日は

考えます。先週は任意の流れ図を考えた時にプログラムが正しいかどうかをどうやって証

明するかという、機能的アサーション法というのを説明したのですけども、実際にはプロ

グラムは少なくとも理論的には構造化プログラミング、3つの構造だけやれば何でも書け

ることになっていますので、もっと単純な世界なのです。何でも書ける世界でなくて、こ

こまで書けることを限定しても何でも書ける訳です。そうすると理論はちょっとありがた

くて、いろんなことを考えなくて良いです。この3つだけを考えれば良いということです。

理論が単純化されるのでもっとスマートな理論ができるのです。それをやったのがホーア

です。そこではかなり数学的に定式化するのですけども、或いは論理学的に定式化するの

です。公理とか推論規則とかそういう言葉が出てくるのですけども、今この時間であまり

難しい数学の抽象的な、哲学的な数学の言葉を使うと分かりにくいかもしれないので、普

通のコンピュータの言葉を使うと、こういうことです。 最初から知識ベース、これはデータベースと思ってください、普通のコンピュータの言

葉でいえばデータベースなのですけども、最近の情報では知能、人工知能とか、知識とか

を扱うようになっています。そういう意味で知識が蓄えられているデータベースを知識ベ

ースと言います。そこに最初から入っている命題、これを公理と言います。ですから事前

知識です。システムが最初から分かっている情報、それを公理と言います。 その例はこういうものなのですけども、これは論理学で、分数ではなくて、横の線の上

に前提を書いて、こういう前提が成り立っていれば線の下のことが成り立つ、結論が成り

立つという、こういう書き方なのです。論理学で使う書き方です。 それで言うと、前提がなしでも成り立つことなのです。前提が最初から true、真になっ

ていますので、特に前提がなくても必ず成り立つことがこの下に書かれています。それが

公理です。例えば1が0より大きい。これは証明しようがないです。そういう風に決めて

ある訳です。それから A と A が同じだというのも証明しようがないと思います。当たり前

だと。矢印はならばという意味です。P ならば P、P が真ならばその P 自身も真である。こ

れも証明しようがない当たり前のことだと、こういうものです。こういう当たり前のもの

を公理という風に言います。幾何学でいえば2点間の、2点を結ぶ直線がただ1本ある、

ユークリッド幾何学とかです。そういうものがあります。そういうのを公理と言います。 それに対して推論規則というのは、こういうように前提が true ではなくて何かあるので

す。こういう前提が成り立ったらこの結論が成り立つ、というような規則です。これはコ

Page 11: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

ンピュータの言葉で使うと、知識ベース内の命題、前提の知識が知識ベースの中に入って

いる、探索した結果あったとします。知識ベースの中に P というのがあった。P ならば Qというのがあった。この2つの知識が見つかりましたという時には、Q という知識を作り

出して良い。そして知識ベースの中に蓄えて良い。というように、知識ベース内に既にあ

る命題、この場合は2個ですけども、そこから新たな知識を作り出す。これが Q です。そ

して新たな知識を知識ベース内に追加するアルゴリズムです。それを推論規則という風に

言います。 これは有名なものです。P ということが分かっていて P ならば Q ということも分かって

いれば、確かに Q が成り立ちそうです。それは我々人間にしてみれば当たり前なのだけど

も、理論としてはこういう推論規則として与えて始めてちゃんとアルゴリズムが動くので

す。そういう風な何かと何かから何かを作るというのを明確に指定したもの、それが推論

規則、これはアルゴリズムの一種です。 (8)3.ホーア論理(1/6) そこでホーア論理という、スライドで(1/6)と書いてありますので、スライド6枚

あります。それで説明をしますけれども、ホーア論理では、まずやりたいことはプログラ

ムの部分正当性を証明したいのです。部分正当性というのは、停止性は証明しなくても良

いのですけども、プログラムがもし停止すると、ちゃんと思っていたような動作をしてい

ますと、ちゃんと正しい結果が出ていますよと、そういうことです。それを証明したいの

です。それを表現する命題を{P}S{Q}という3つの組で表現します。これが命題なの

です。これ自体が真だったり偽だったりする命題です。 これはどういう風に解釈するかというと、まず S は sentence、プログラムの文のことで

す。ここにプログラムをプログラミング言語で書くのです。それで後中かっこの中はプロ

グラミング言語の言葉で言うとコメントなのですけども、こっちのコメントは precondition、事前条件です。プログラム S を実行する前に事前に P が成り立っていますということをコ

メントとして書く。これも命題です。真か偽かです。P が成り立っている、成り立っていな

いということを言うのに充分なことだけが書かれている。真か偽かを表す内容です。A が Bより大きいとか、そういう命題が書かれているのです。それが事前条件です。それから Qの方は postcondition というので、S の実行が終わった時に成り立っている筈のことを書き

ます。これも condition、条件ですので、真か偽かです。 それでこの全体の意味なのですけれども、P が真の状態から文 S を実行します。プログ

ラムが停止することは今部分正当性なので気にしないです。停止しないかもしれないこと

は許すとして、もし停止すれば S の実行が終わる訳です。その時にここに書かれている

postcondition、Q が真となる、と読んでください。判りやすいですね。これもプログラミ

ング言語だと思えば良いのです。P と Q がコメントだと思えば、P が成り立っている状態

Page 12: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

を仮定して、そこから S を実行しました。実行が終わると Q が成り立っています。という

ことを主張している命題であります。本当にそうかどうかは分からないです。バグがあれ

ばそうではないかもしれないのだけど、プログラムが正しく書かれていれば実際そうなの

です。 この意味自体がちょっと長い2行にわたった日本語の文章ですけども、これは命題であ

るのは確かです。P が真の状態から文 S を実行すると、その時点で Q が真となるというこ

とを主張しているのですけども、本当にそうだったら真だし、いやこれは嘘だと思ったら

偽なのです。ですからこれ自体はちゃんと命題になっている訳です。それをいちいち日本

語で2行で書くのが面倒臭いので、ホーアはこう書くことにしたのです。ですからこれは

命題だと思ってください。実際命題なのです。普通の数学では現れない命題です。こうい

うプログラミングの理論だけで出てくる命題です。 それでこれをまず基本として、ホーアがやったのは構文ごとの意味、構文と言ってもさ

っき言いました連接、選択、反復という3つの構文しかない訳です。構造化プログラミン

グ言語ですから、そういうプログラミング言語しか考えないのです。その構文ごとの意味、

IF 文とは何なのか、While 文とは何なのか、セミコロンというのは何なのか、というその

意味を、さっき言いました公理や推論規則で表現した、そういう仕事をしたのです。それ

をこれから1つずつ構文ごとに説明をしていきます。 まずは言っておきますけども、この3行の文を読んだからと言って急には何のことか分

からないと思います。これからスライド何枚かでこういうことを説明していきます。 結論から前提に向けて推論を進めていくという話をします。プログラミングというのは

結論から設計して行くのです。つまりプログラムが実行し終わるとこういうことを成り立

たせたい。例えば n!が y という変数に入っているようにしたいというなら、y=n!です。こ

ういう風なことにしたいというここから始まるのです。これを成り立たせるにはどういう

プログラムを実行すれば良いかというように、基本的には後ろから前に向かって設計して

行くのです。ですから、結論からスタートして前提の方に向けていろいろ考えを進めてい

くのです。そういうことをやっていくと、最終的にはこの3つ組というのはなくなります。

これを成り立たせるにはどうするかと、いろいろなことをやっていくとこれはなくなって、

普通の数学に出てくる論理式の証明に帰着されます。つまり数学の時間に習うような、こ

れを証明しなさいとか、そういうような普通の数学の話に帰着されます。プログラミング

の話ですから、これがある限り普通の数学ではない訳です。これがなくなれば普通の数学

になります。 それでこれから1つ1つスライドで説明して行きますけども、それをずっとそういう

ような考え方を進めていくと、最終的にプログラムが正しい正しくないというのは普通の

数学の話になってしまうという、そういう作戦で理論が構築されています。

Page 13: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

(9)3.ホーア論理(2/6)空文 まずウォーミングアップ。さっき3つというのは連接、選択、反復と言いましたけれど

も、それをこの次からそれを説明します。 ウォーミングアップで skip 命令というのがあるとします。これは何もやらない命令です。

機械語でも NOP 命令、no operation、というのがあったりしますけれども、何もやらない

機械語というのがあります。何もやらないと言っても NOP という命令はあるので、時間だ

けがちょっと経過する。ですから通信とか機械とかが制御する時に、もうちょっと待たな

いといけないということがあります。待つために時間を浪費しないといけないのです。そ

ういう時に使う命令とかありますけれども、例えばそんなようなものです。 何もしないという skip という命令があったとします。そして、これは今説明した3つ組

になっているのですけども、skip という命令を実行する前は P という事柄が成り立ってい

たとします。skip が終わったら Q が成り立っているとします。これはそういうことを主張

しているのです。P が成り立っている時に skip 命令を実行し終わると Q が成り立つと言っ

ている、そういう結論なのですけども、本当にそうかどうかということなのですが、いつ

でもそういうことは成り立たなくて、前提としてこれが成り立つならばそれが成り立つの

です。それが P ならば Q という普通の数学の命令です。ですからこの P が成り立っている

時には Q も成り立っているということが数学的に証明されれば、P が成り立っている時に

skip 命令をし終わると Q が成り立っているという点で、当たり前というような気がすると

思います。skip は事実上何もしないのですから、skip 命令の前の P が成り立っている時点

で既に Q が成り立っているしかないのです。ですからそのためにはもう P が成り立ってい

る時点で Q が成り立っていないといけないので、P ならば Q でないといけないと、こうい

うように読めば良いのです。ですからこれはちょっと順方向と逆方向で読んでいますけど

も、順方向で読むと、こっちが前提でこっちが結論ですので、前提として P ならば Q が成

り立っているとしましょう。そしたら結論としてこういうことが言えます。P が成り立って

いる時に skip 命令が実行し終わると Q が成り立っているということを言う。そういうプロ

グラムの正しさが、こういうプログラムが正しいことが証明できるのです。 例えば逆方向の読み方はさっき言ったように、プログラミングというのは結論からスタ

ートして設計していくものなので、逆に読んだ方がプログラムは作りやすいです。P が成り

立っているという入力の条件から skip 命令を実行すると、自分がやりたかったこと、Q と

いうことが本当に成り立っているだろうか、これを確認したい。これを確認するにはこう

いう前提を確認すれば良いということです。P ならば Q ということを確認せよと、それが

確認できたなら、このプログラムはお前の思った通り、P の時に実行するとちゃんと Q に

なって終わるという風に設計されているということが確認できたということです。そうい

うようなことを表しています。 これはちょっとしたウォーミングアップです。skip というのは空文です。何もしない。

Page 14: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

逆にいえば skip とは何なのかということを定義しているのです。つまりプログラミング言

語の中に skip という命令があったとします。それが何なのかを定義しているということも

また言えるのです。つまり私が最初ちょっと分かりやすくするために、skip というのはコ

ンピュータの NOP 命令、no operation という命令が普通あるので、それを実行することで

すと言ったのですけど、それは嘘かもしれないです。これをコンパイラに通すと NOP 命令

にはコンパイルされないで本当に何もしないものに、単に無視される、if then else の elseの後ろに skip と書いたら、実際には NOP 命令を実行しないで何もしないで次の命令に行

くかもしれないです。或いは NOP 命令を1個ではなくて10個くらいここに書いてあるか

もしれない。そういうことを考え出すと、skip 命令は何なのかというのがすごく怪しくな

っているのです。特にコンパイラというのを作る人にとってみれば、「何かプログラミング

言語をあいつが何か設計してきて、俺にコンパイラを作れと言ったのだけど、skip 命令を

どうコンパイルして良いか分からない。あいつは何も言ってくれなかった。NOP を10個

くらい入れれば良いのかな」とか、非常に曖昧性があります。それでこれが言っているこ

とは、skip を完全に定義している。skip というのは中は完全にブラックボックスなのだけ

ど、P という事前条件からスタートして skip が終わったら Q ということを成り立たせるよ

うにしたいと、そういうプログラムが本当にその人の思った通りかどうかを確かめるには、

P ならば Q ということを確かめなさい、その時には必ずそうなるように skip をコンパイル

せよと言っています。逆にこの推論規則を満たすように skip をコンパイルしてくれるのな

ら、どうでも良いと言っているのです。それによって逆に skip を定義しているのです。そ

れに頼ってプログラマはこういうルールを使って自分の書いたプログラムを正しいかどう

かを確認できる訳です。ですからプログラマはこれがどうコンパイルされるかを知らなく

ても、自分のプログラムが正しいかどうかを確認できることになります。それで充分だと

いうことになります。 それから今ここに出てきた吹き出しなのですけども、P とか Q とかいうのの中には、コ

メントですのでもうプログラムの skip とか IF 文とかを書いていないのです。ですので普

通の数学の命題が書いてあるので、上に書いてあるのはそれをならばで結んで行っている。

普通の数学とか論理学とかそこで出てくる命題なのです。ということで、これはこれを証

明するためにこの前提を証明しないといけないのですが、その前提の中には既にプログラ

ミング言語がないというような状態になっています。そういうようなことをやれという、

これがその一例です。 例なのですけども、ここに書いてあるのは、まず P というのが a=1かつ b=2、これを

P だと思ってください。それで Q という命題は a+b=3だと思ってください。これは成り

立ちますよね。a=1かつ b=2でしたら、a+b=3です。これはプログラミング言語と全

く無関係な数学の世界です。これが成り立つ。つまりこの前提が成り立つことが分かった

ので、故にこのアルゴリズムによってこれを結論して良い。つまり a=1で b=2という状

態からプログラムをスタートさせます。このプログラムは単に skip 命令なだけです。で、

Page 15: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

そのプログラムが終了した時には a+b=3になっています。これはスペックです。こうい

う入力に対してこういう出力が得られるということを表す、非常に単純なプログラムです。

これが確かに正しいことがこれで証明されているのです。我々にとってみれば当たり前で

すけど。a=1で b=2で、その状態からスタートして何もしなければ a+b=3になってい

ます。ですから非常に当たり前のことなのですけども、さっき言いましたように skip 命令

とは一体何をするのか分からない、どうコンパイルされているか我々は分からない訳です。

それでも確かにそうだと言えるのは、この推論規則があるためです。そしてそのコンパイ

ルを作った人はちゃんとこの推論規則通りにコンパイルしてくれているという風に言える

と思います。ですからこれは非常に単純なのだけど、哲学的に重要な例なので、まず最初

にウォーミングアップとして挙げました。 後、これから1つ1つまた説明していきますけども、さっき言いましたようにプログラ

ミングというのは Q から始まる、こういうことを成り立たせたいということからスタート

するのです。その時にプログラムをこう書けば良いのではないかとか、この辺は薄々分か

るのです。Q は与えられるという感じです。このプログラムの部分は自分で設計するので

す。その時に、今度ここがどうなるかということを求めないと、さらにこの左側のプログ

ラムを設計していけないことになります。ですから、Q とプログラムが与えられた時にこ

こをどうするかという問題があるのです。それも1つ1つ考えていかないといけないので

すけども、この skip の場合は P=Q にすれば良いのです。この前提が成り立つようにすれ

ば良いのです。ここが分からなければ、この Q と同じものをここに書けば良いのです。Q skip と。そうすると、ここも Q ですから、Q ならば Q というのはさっき説明した公理です。

それ以上説明しなくても true なのです。ですので、Q skip Q としておけば、前提が真です

からこれは確実に正しいプログラムになっています。というような事柄を述べています。

自明なことです。ですので、Q ということを成り立たせるプログラムを作りたいと言った

時に、skip 命令を書けば良いのかと思うかもしれないのですけど、skip 命令をもし書くの

だったら、それ以前にここで Q を成り立たせるようにしておかないといけない。ちょっと

どうしようもない、これでは駄目だと分かると思います。 (10)3.ホーア論理(3/6)代入

ここからはまともなスライドです。3/6まで来ましたので、後3、4、5、6と4枚

スライドがあります。その1枚目は代入文とは何なのかという説明をします。残りの3枚

はさっき言った3つです。連接・選択・反復のことを説明します。 まず代入文なのですけども、代入文というのは実は一番難しいのです。これが代入文で

す。C 言語でしたら x=E と書くのですけども、他のプログラミング言語、ALGOL とか

Pascal とかいくつかあるのですけれども、割とコンピュータ・サイエンスの論文に出てく

るようなプログラミング言語は C 言語ではないです。この種のものが多いです。ホーアも

Page 16: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

この文法を採用しています。これが代入の記号です。これが代入の左辺、変数です。これ

が代入の右辺、長めの式を書いていい訳です。この代入文だけがこのプログラムの一部分

だとします。その事前条件が P で、事後条件が Q です。ですからこの横線の下の部分が言

っていることは、P が成り立つ条件からスタートして、x に E を代入するという代入文を実

行してやると、代入が終わった時点では Q が成り立っている、というプログラムです。そ

ういうプログラムにしたいと。それでこの上は、そういうプログラムにするにはこういう

前提が成り立っていないといけませんということを言っています。P ならば Q に、何か変

なことが書いてありますけれども、ここはここでホーアが発明した記号です。特別な記号

です。その意味は吹き出しのところに書いてありますけども、Q に出現する全ての x、Q と

いうのは postcondition です。この中に数式が文字で書かれている訳です。その中にこの代

入文の左辺にある x というのもここに書かれているかもしれないです。ですから Q に出現

する x が1つ2つとたくさんあると思うのですけども、全ての x を E、つまり代入文の右

辺の文字列で置き換える。そういう風にして作った、アサーションというのは命題、主張

ということです。ここでこの変な記号は、postcondition の Q の中の左辺の変数を全部右辺

の文字列で置き換えてしまいなさいと、それをここに書けと言っているのです。P ならばそ

れと。 これはプログラミング言語が一切含まれてないです。代入文だから、ここが一瞬プログ

ラミング言語のように見えるかもしれない。でも分かりやすくこれと同じものをただ書い

ただけで、ここに代入文が実際にある訳ではないです。Q というのは普通の命題です。プ

ログラミング言語と無関係な命題で、その中にある x というのを E という普通の数式で置

き換えてしまいなさいと言っているだけですので、できたものの中にはプログラミング言

語、IF とか While とか一切入ってないです。P ならばそれという普通の命題をちゃんと数

学的に証明しなさいと。そうするとさっき言っていたこの代入文の前に P が成り立ってい

たら、代入文が終わっていたら Q が成り立ちますということが保証されるということです。

そういう風にコンパイラを作ってやるということです。 これは非常に分かりにくいと思うので、また例題を出します。P というところが a=9だ

と思ってください。この Q というのは後で出てきますけども、こっちから見た方がいいか

な、Q を先に説明しないことにはこれを説明できないから、やっぱり下から行きましょう。

故にというこの結論から見てください。プログラムの代入文は、a:=a+1です。つまり

現在の a の値に1だけ足した数字を、また a というところに記憶し直しなさいと。これは

我々コンピュータの専門家にとってみれば当たり前なのですけども、中学生に言っても分

からないです。中学生は a+1くらいは分かるでしょうけれども、代入とかというコンピュ

ータのことは分かりません。コンピュータの仕組みは分からないのです。しかも C 言語で a=a+1と書いていたら大変なことになるのです。a と a+1が等しいなどというと両辺か

ら a を引くと0=1かという、そういう話になってしまいます。ですからこれはプログラ

ミング言語を知らない人にとってみれば、どんな意味を持っているかさっぱり分からない

Page 17: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

ものなのですけども、とにかく a=9の状態からこのプログラムを実行して、実行し終わる

と a=10になることを、コンピュータの分からない人は証明したいとします。それを証明

したいと思ったら、これに頼るしかないです。これを証明するにはこの前提が成り立つこ

とを証明すれば良いのです。 では前提は何と書いてあるかですけども、まず P ならばというのでこの P をそのまま持

ってくれば良いので、これです。a=9ならばというのを書きます。この後ろが複雑なとこ

ろですけど、まず Q というところに着目します。これは a=10です。その中に x という

のが何ヶ所か現れています。ここでいう x というのはこの代入文の左辺ですので、この例

では a です。a が1ヶ所あります。その a をこの E に置き換えてしまいなさいと言ってい

るのです。この E というのは a+1という文字列です。ですからこの a=10の a のところ

を a+1に置き換えたら、a+1=10になります。それがこれです。なのでこれはここに

なります。ですので、これを証明しなさいと言われてもプログラミング言語のこれが何か

分からない人がいた訳ですけども、それを証明するにはこれを証明すれば良いのだと、代

入文の規則が教えてくれたのでここまで来た訳です。これを証明するなら、ちょっと数学

ができればできる訳です。中学生でも証明できます。a=9だったら a+1=10ですとい

うのは、中学校1年くらいならできるでしょう。単なる計算問題です。これは確かに成り

立つので、故に a=9の時にこの代入文を実行すると、a=10になることが保証されたの

です。証明されたことになります。 …というものなのです。だからこれを初めて聞いた時には何だかよく分からないと思う

のですけども、これがその代入文というものの本質を捉えているという。つまりコンピュ

ータの仕組みを知らなくても代入が理解できたことになります。普通我々が習った時には、

コンピュータの仕組み、アーキテクチャを習って、CPU というのを命令を実行していくた

めプログラムカウンタというのがあって、2進数で番地が入っていてその番地から命令を

取り出してとか、命令にはちゃんとアドレスというのが入っていて、プログラミング言語

で a と書いたらそれは実際にコンパイルした時には1000番地というアドレスになるの

だとか習ったりして、右辺の a+1とかはその1000番地のアドレスの内容に1という実

際のデータを足すのだと言って、それを a という1000番地という場所にまた置き直し、

入れ直して記憶し直して、a に元々データがあったかもしれないですけど、それは消えるの

だと。これを正確に説明しようとするとコンピュータの知識がそれなりに要るのです。少

なくとも60分くらいは説明しないといけない。ですけどもホーアがやったことはそうい

う知識一切なしに、このプログラムが正しいことを、数学を知っている人なら証明できる

ようにした訳です。実際我々した訳です。そういうようなことをやったというのです。 だから一旦覚えればもう簡単です。とにかく代入文がこうなるということを説明するに

は、postcondition に代入すれば良いということです。これを証明したければ、この代入を

この右側にある事後条件に代入して、a の代わりに a+1にするということなのです。だか

ら変な感じがすると思うのですけど、そういう風なことを言っています。或いはじっくり

Page 18: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

考えれば分かるかもしれないのだけれども、a=9の時にその内容に1を足して10にした

い訳です。1を足したら10になるかということを言っているのですけれども、そのため

には a=9という最初の状態に置いて、既に a+1=10になっていないといけないと、当

たり前のことを言っています。a=9の時には a に1を足したら10になるので、a という

変数に実際に1を足すと a が10になるのです。という、分かったような分からないよう

な気がすると思いのですけど、そういうような考えからホーアが整理したものがこれなの

です。これが代入です。 それから後さっき説明した P が未知の場合どうやって求めるかです。Q というのが具体

的に与えられたとします。こういう条件が成り立つようなプログラムを書きたいと、それ

を成り立たせるにはこういう代入文にすれば良いのではなかったかと、この辺が分かって

いるとして、さらに左にいろいろなプログラムを書くためにPをどうするかというのです。

その時には、P はここで言っているこれにすれば良い。つまり事後条件にこの代入文を適用

して文字列を置き換えたものにすれば良い。これです。何故そうかというと、そうするこ

とによってこれとこれが同じになります。P をこれにしなさいと言っているのだから、これ

を P ならば P という風にやって、公理になりますのでそれ以上証明しなくても true になり

ます。ですからそういう風に選べば良いということが分かります。

(11)3.ホーア論理(4/6)連接 また後で例題で戻ってきます。 それで後3つなのですけども、次は連接です。ここからは割と簡単なのです。代入文が

一番難しい。連接です。 S1の後に S2を実行するという、こういうプログラムを書いたとします。事前に P が成り

立っている時に、このプログラムが終わったら R が成り立っているということを証明した

いとします。それを証明するには前提としてこれとこれ、2つ証明しなさいと言っている

のです。ですから1つのことを証明するのに、証明することが2つに増えてしまったので

すけど、それぞれがこれよりは単純な命題なので、そんなに仕事が大変になった訳ではな

い。で、S1と S2を分解しています。それで、ここに突然 Q と出てきますので、Q という

のは何か探さないといけないのです。ここから自動的に Q が出てくる訳ではないので、何

かうまく Q というのを探して、P が成り立っている時にまず S1だけを実行したら Q が成り

立つことを証明しなさい。今度は Q が成り立っているところからスタートして S2だけを実

行したら R が成り立つことを証明しなさい。その2つともできたら、S1;S2というちょっ

と複雑なプログラムの実行については、P からスタートしたらちゃんと R になってしまい

ますということです。これはほとんど当たり前だと思うのです。ただここで P が成り立っ

た後に S1を実行して、Q というのが成り立って、さらに S2を実行して R が成り立つ。Qを経由して行っているだけです。これは直感的に明らかだと。それでも理論的に重要なこ

Page 19: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

とは、より単純な構文の部分正当性に帰着させているということです。S1;S2というこの

プログラムよりも S1だけのプログラムの方が簡単です。S2だけのプログラムの方が簡単で

す。より単純な構文のプログラムの正しさに帰着させている訳です。 それから次、ここの P が未知の時はどうするかということです。R と S1、S2が与えられ

た時に、P1は分かりませんという時にどう設計するかということになりますから、まず再

帰的に Q を求めます。ここを見て R と S2は分かっているのですから、再帰的というと今

説明中の方法です。まだ説明し終わっていないのですけども、説明し終わると全貌が分か

りますので、全貌が分かったその方法で再帰的に、リカーシブに Q を求めます。そして Qが分かったのでまた再帰的に Q と S1から P を求めます。その P をここにするのです。と

いう風に求めます。 (12) ホーア論理 (5/6) 選択

次が if です。if C then S1 else S2 end とこう if 文があって、事前に P が成り立っている

時に、この if 文を実行し終わると Q が成り立つという事を証明したいとします。それには

この二つを証明しなさいと言っています。この if文というものが分解されて、S1の部分と S2

と、2つのより小さなプログラムに分解して、それに関することをひとつずつ証明するこ

とになっています。まず、こっちなのですけれども、P∧C。C というのは if 文の中の条件

なので、これは a が b より大きいとか、数学的に判定できる条件です。プログラムが一切

書かれていない。C 言語だと if 文の中に変なプログラムを書いたりできますけれども、入

力とか、いろいろな事なんでも書けますけれども、今ここで考えている if 文はもっと純粋

なやつで、純粋に数学的な条件しか書けないということになっています。P と C が両方成

り立つという記号です。P∧C。そういう状態で、S1というプログラムを実行をしてやると

実行が終わったときには、Qというpostconditionが成り立っていることを証明しなさいと、

これ自体また難しいかもしれないので、これを証明するには、またさらに何を証明と、ど

んどん上に行くかも知れないですが、そういうことを証明します。 もう一つは else の後ろの S2 なんですが、P が成り立っているのだけども、C は成り立

っていない。これ¬は Not という記号です。これ∧は And です。P∧¬C ですので、P は成

り立っているけれども、C は成り立っていない。そういう状態からスタートして、S2 とい

うプログラムを実行し終わると、やはり Q が成り立っているということを証明しなさい。

この二つの証明ができたあかつきには、この if 文が正しいことが証明できたと、いうこと

です。そういう推論規則を表わしています。これは後でどういう意味なのかもう一回説明

します。それでですね、今説明した方がいいかな。これはそんなに難しくないと思うので

すが。P が成り立っていて、もし C が成り立っていたら、P∧C が成り立っていたら、私た

ちの if 文の直感では、S1 を実行することになりますよね。最初、P がとにかく事前条件で

成り立っていると、C は成り立っているかどうか分からないのですけれども、プログラムを

Page 20: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

実行してみると、C が成り立っていることが分かったわけです。P∧C であることが分かっ

た。その時、私たちの学部の時に習った知識では、S1 をプログラムでは実行するわけです。

それで S1 と書いてあって、実行し終わるともう Q が成り立っていないことには、ここで

Q は成り立たないですよね。これ終わった後、ぴょんとこれ飛ぶのですが、S1 が終わった

直後に Q が成り立っていないことには仕方がない。それを言っているのです。今度こっち

の方は、事前条件で P が成り立っているのは、与えられているのだからいいとして、if 文

をちょっと実行したときに、C は成り立っていなかったとします。¬(not)C です。その

時には、私たちの学部で習った知識では、S2を実行することになるのです。ここに S2と書

いてあります。S2が終わった直後に、Q が成り立っていないことには、if 文が終わった後、

Q は成り立たないです。S2 が終わったら、すぐここに行ってしまいます。そういうような

ことを言っているのです。ですから、これは当たり前のことを言っているのです。そこで、

また P が未知のとき、この Q が分かっていて、if 文の C 、S1、S2が分かっているときに、

P を書きたい時にどうするかということなのですが、この上のほうを見て、S1と Q が分か

っているので、今説明中のテクニックを使うとここが、P と C に分かれては求められない

のですが、ここの部分 P1というものが求められます。それから Q と S2が分かっているの

で、今説明中の再帰的なテクニックを使うと、この部分 P2 というものが求められます。

P1と P2 が求まったら、その二つから P というものを作ることができます。それはこれな

のです。(C→P1)∧(¬C→P2)(C ならば P1、且つ Not C ならば P2)というこういう命

題を作りなさい、それが P ですよ、ということです。これはここでは証明しませんが、直

感的には、これを P と C に分けたいのですが、この P1をです。P1を P と C に分けると、

P2を P と¬C に分けたいのですが、それをこういう風に書きます。C が成り立ているのだっ

たら、こちらではない、ということかな。こっちは C が成り立たないものがあるので。Cが成り立っていたら、ここのところは P1だと。且つ、C が成り立っていないときは、ここ

は P2が成り立っていると。これが成り立っているということです。これは直感的には分か

りにくいのですけれども、ちゃんと証明しようと思ったら証明できます。ここに、これを

代入して、いろいろやったりすると出来るのです。こういうようなテクニックを使って、

とにかくここも求められます。実際には C か¬C かはプログラムを実行してみないと分か

らないので、どっちとも言えないです。もしプログラムを実行して、C が成り立っているの

だったら、もともとこっちが成り立っていたのでしょう。もし、プログラムを実行してみ

て、C が成り立っていないなら、もともとこっちの方が成り立っていたのでしょうというこ

とを、∧をつけるという意味です。 (13) ホーア論理 (6/6) 反復 最後の反復の部分です。

Page 21: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

While C do S というループの前に、P が成り立っている時に、もしループが終了す

れば、Q が成り立つ。これを証明したいという時に、また二つのことを証明しなさいとい

うことです。ひとつは P∧C の時に、プログラム S というループの本体を一回だけ実行す

る。そういうプログラムを実行すると、S が終わった時には P が成り立っていますという

ことです。これは二回前、第1回目の授業で説明したのですが、この P は Loop Invariantと言います。ループ不変関係。つまり、最初、こう左からプログラムを実行して、初めて

ここに到達したときも成り立つし、ループをこう一周だけ実行して戻ってきたときも成り

立つ。つまりループを何周しても成り立つという Loop Invariant というものを書くことに

するのです。まぁ、Loop Invariant なのだと。それで、P∧C というのはですね、最初 Pが成り立って、だからこの P はいいとして、C は成り立っているかどうか、実行してみな

いと分からないのですが、成り立っているとしましょう、ということです。P も成り立って

いるし、C も成り立っていたとしましょうということです。そうすると、私たちのプログラ

ミングの知識によりますと、S というのを一回だけ、とりあえずまず一回は実行してみるわ

けです。それで S というのを実行してみる。それが終わるとまたここに戻るので、その時

には P は Loop Invariant です、また P が成り立っていますと、それを証明しなさいと言っ

ているのです。それから、こっち側はもうプログラムは一切入っていない、普通の数学の

命題ですが、P が成り立っているとしましょうと、ここですから。だけども、C は成り立っ

ていないとしましょう。そうすると、そのプログラムを実行すると、C が成り立っていない

のだから、これで while 文が終了して、こっちに行ってしまいます。その時には、Q が成

り立っている。ということが、もし証明できれば良いということです。ですから、P が成り

立っているときに、C が成り立っていれば、まだまだ S を実行すればいいのですが、P が

成り立っているときに、実は C は成り立っていないと言うときには、その時には、既に Qは成り立っているということでないと、こういうことは言えません、ということを言って

いるわけです。 この P は今言った Loop Invariant、ループ不変条件になっています。絵で書くとこうい

うことです。この while 文と言うのはこういうものです。C を判定して、true だったら Sを一回実行してまたループを戻ると、C が成り立たない時はもうこれで終了。この C が終

了した時には、Q が成り立つはずだと言っているのです。事前に P が成り立っているとい

うことで、これを絵に描くとこういう事なのです。このプログラムが本当に正しいかどう

か。P という条件からスタートして、何周しても抜け出てきたら必ず Q が成り立っている

か、ということを証明したいわけなのです。そのためにはこの二つを証明しなさいと(い

うことです)。まず、P が成り立っていて、且つ C が成り立っているときには、S を実行す

るとまた P が成り立つ、これを証明しなさいと言っている。P が成り立つときに、C が成

り立っていないときには、その時には既に Q が成り立っていることを証明しなさいと、こ

の二つが証明できたらいいよ、というわけです。

Page 22: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

あとさっき説明したように、ここが、P が本当に Loop Invariant であることを証明して

ある部分です。そこでここが問題なのですが、さっきからやっていますように、このプロ

グラムと、この postcondition の Q が分かっているとして、この P を求めたいのです。で

すけれども、この P は、Loop Invariant は自動的には求められないのです。ですから、こ

れはソフトウェア設計の究極の大問題です。Loop Invariant は自動的に求められないとい

うことなので、プログラムを作った人が自分の頭の中に何かアイディアがあるはずです。

それをプログラマが自分で考えてソースコードに必ず書いて置く。ですから、プログラマ

はその程度頭が良くないとだめなのだということです。そういうような教育をちゃんと受

けなさいということです。これが自動的に求められたら、プログラマはコンピュータが自

動的に作れるのです。実際にはそれはできませんので、Loop Invariant は人間が作ってち

ゃんと入れておきなさいということです。 (14) 例題1 簡単な計算と代入 例題なのですが、まずウォーミングアップで、簡単な例題に行きます。代入文が二つだ

けあるプログラムです。x と y は、事前に値が入っているとします。例えば、x には a、yには b。こういう値が入っているとします。それを足したものを、x に入れ直します。それ

が終わったらもう一回 x と y を足すのですが、当然さっきの x と新たな x は違いますので、

この x+y の計算結果と、この x+y の計算結果は当然違うわけです。その違う x を使って、

また x+y を計算して、今度それで y を置き換えなさいという代入文をこの順番に実行する

と、終わったときには y には a+2b。最初に x に入っていた値と、最初に y に入っていた

値の 2 倍の和が y には入っています、ということを証明したいとします。これは、別に今

日習ったことを使わなくても、みんなだったら簡単に出来ると思います。a+b がここに入

ります。ここは a+b+b だから、a+2b です。だからそうなるのですが、今日の習った内

容を使って説明します。これが;(セミコロン)の内容になっていますので、連接の推論規

則を使います。これをクリックするとさっきのスライドに戻りますので、もうちょっとだ

け復習します。この形になっているのですが、これを S1と S2に分解して、R はここに、Pはここに引き継いでいくのですが、Q というところは考えないといけないと、こういう風

にします。 それで、これがここになって、これがここになって、これはこっちに行って、あれはこ

っちに行くとこうなります。ここのところはまだ分からないです。分からないのですが、

それをどうやって求めるかというと・・・ちょっと待ってください。スライドが進まなく

なったような気がします。さっきの続きからというと・・・他のアニメーションを作って

置いたような憶えがあるのですが・・・ちょっと違うかもしれないので・・・これはこれ

で説明します。

Page 23: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

ここを今度求めるのですが、これはさっき説明したように、これとこれからこれを作る

テクニック。代入文の場合は、postcondition にこの代入を行いなさいという言い方をしま

した。つまりここに書いてある y の代わりに、この右辺の x+y で置き換えるのです。です

から、この y を x+y で置き換えます。そうすると、x+y=a+2b になります。それをここ

に置いておきます。それと同じものをここに、さっき{Q}{Q}となっていましたが、同じもの

がここに来ます。それで、ここはもう最初からこれが書いてあるからいいのです。それで

この状態になります。次に、これとこれを証明しないといけないのですが、それはもう簡

単です。これを証明するにはどうするかというと、さっきの代入文の推論規則で、

postcondition にこれをまた代入します。これは y です。変数は y、右辺は x+y ですから、

この y の代わりに x+y と置き換えると、x+y=a+2b になります。ここの事前条件をその

ままこっち側にもってきて、「ならば」とつなげる。これがさっきの推論規則です。これを

証明しないといけないのですが、これはもう公理になっています。x+y=a+2b ならば、同

じことがここに書かれていますので、これはもう証明する必要はなくて、true だというこ

とで、こっち側は証明が終わったのです。こんどこっちですが、これを証明するには、ま

た代入文ですので、postcondition の x の代わりに x+y と置きます。それがこれです。こ

この x が x+y。あとは同じです。+y=a+2b。となって、代入文はなくなって、事前条件

をそのまま上にもって行きます。これを証明すればいいということです。これはもうプロ

グラミング言語の文が書かれていませんので、普通の数学の命題になっています。x=a、y=b ならば、x+y+y=a+2b であることを証明せよ。これは簡単です。ただ x と y に代入

して、左辺を計算すれば、左辺も右辺も a+2b になるとすぐ分かると思います。それで、

これは証明できたので、true と。これ以上、上に遡る必要はないです。ということで、こ

れで全体の証明が終わったことになりますので、このプログラムがそうだと、確かに正し

いということが分かったことになります。 (15)例題2 m と n の積(1/3)初期設定 次の例題2です。これは m と n の掛け算を行うというものです。m と n は自然数です。

ゼロ以上の整数です。掛け算を行うのですが、掛け算命令がないとして、足し算と引き算

だけを繰り返して、掛け算をやるという、そういうプログラムです。p というところには、

最終的には答えが求まります。c は counter で、decrement、1ずつ減っていきます。そう

いう counter です。最初は n を設定します。m×n のうちの、n です。これはコメントです

が、このうしろに while 文があるから、分かると思うのですが、これは while 文が正しい

ことを証明するための Loop Invariant のつもりです。これは、今は無視して、while 文に

行って、c が正である間、つまりゼロになるまで、次のループを繰り返しなさい。p は最初

ゼロなのですが、この中で m を一回だけ足し加えます。その代わり c から、カウント1回

減らします。これで m をどんどん何回も足していくということです。何回足したかを c で

Page 24: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

カウントする。1回、2回、3回と数えるのではなく、全部で m を n 回足したい訳です。

m×n です。残り n 回です、という残りの回数から1ずつ引いていっている。こういうふう

です。c がゼロになったら終わりで、抜け出たときは p=m×n になっていますというプロ

グラムです。そこでさっきも言いましたように、事前条件は、m と n はゼロ以上の整数。

事後条件は p=mn なのですが、Loop Invariant だけはプログラマが挿入しておかないとい

けないので、これは手で入れてあります。これは何を言っているかというと、p は途中経過

です。途中までの掛け算結果が求まっているのです。それは、m を n-c 回すでに足してあ

ります、ということを言っています。c はまだ負の数にはなっていません。ゼロ以上です。

c が負の数になっていたら無限ループになってしまう。違うかな。c がゼロだと何が起るか。

あまり大したことは起らないかもしれない。念のため、c はゼロ以上と書いてあります。そ

ういう事を書いておいて、さっきのテクニックを使います。まずここのところが簡単なの

で、これをやってみます。m、n がゼロ以上のとき、二つ代入文を実行すると、この Loop Invariant が成り立つかどうかということです。これを証明するために、これは、本当は、

代入文が2回あるので2回やらないといけないのですが、途中省略して2回分まとめてや

ってしまします。右側から。postcondition の c ところを n で置き換えるといっています。cは二ヶ所あります。それを n で置き換えます。こことここを n で置き換えたものを作りま

す。それがここに来るのです。何もスライドには書いていませんが、ここに来るのです。

それで、今度それが成り立つように、この p=0 という代入文を実行しています。そこで、

そこのところの p をゼロに置き換えるということをやります。実際には、ここが n になっ

たものがあるのですが、p はそのままになっているので、その p をゼロに置き換えたらこれ

になります。途中端折りましたけれど、2回分まとめてやったらこうなるのです。これで

この代入文を右から順番に処理し終わったので、その右側の事前条件をここに書いて、事

前条件が成り立っている時には、すでにこれが成り立っていないといけません、というそ

ういう命題に帰着するのです。これはもうプログラミング言語が入っていませんので、普

通の数学の問題です。これは簡単です。計算すると、n-n はゼロ、m×n はゼロですから、

0=0で成り立ちます。それから n はゼロ以上といっていますが、事前条件でも n はゼロ

以上だと言っていますので、当然成り立ちますので、証明が終わった。それでこれで終わ

り(になります)。次、ここからここまでです。 (16)例題2 m と n の積(2/3) ループの継続 ここからここへ行くには、さっき言ったように実際には二つのことをやらないといけな

いので、さっきのところに戻ります。こういうタイプの証明をするには、まず P∧C ならば、

S を1回だけ実行するとまた P が成り立つという Loop Invariant の証明というのをやりま

す。

Page 25: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

これが Loop Invariant です。それから今のスライドで一般的に c と書いてあるところが

この命題です。そしてループの本体は、この代入文二つですので、それをここに書いてあ

ります。代入文二つと、ループの本体があって、これが Loop Invariant です。それからこ

っち側にも Loop Invariant があって、且つこの条件がここに書かれています。こうですね。

これが Loop Invariant。これがこの c。それで代入文が二つ、ループの実行をしてやるとま

た Loop Invariant は成り立つ。今度これを証明するのですが、これはまた中身は単なる代

入文ですので、さっきの例題のテクニックを使って、postcondition でどんどん代入して行

きます。まず c というのが二ヶ所ありますので、その c を c-1 で置き換えます。そうする

とこれになります。そして更に今度は p。この p に着目して、p+m で置き換えます。これ

一箇所だけです。これを p+m で置き換えるとこれになります。これで二つの代入文の処理

が終わったので、この事前条件の下でこれが成り立っていないといけないという命題に帰

着されていって、これでプログラミング言語は一切なくなりました。これで証明できるか

どうかということなのですが、この括弧を展開すると m(n-c+1)となるのですが、これ

と似たものが出てきます。p=m(n-c)。この p に、これを代入すると、m(n-c+m)と

なって、m で括ったりすると、これになるのです。暗算では出来ないかもしれません。頭

のいい人だと暗算でできると思います。これは簡単な計算問題で、両辺が一致します。そ

れから、ここのところは、c-1 はゼロ以上かというのですが、もともとゼロ以上だという

ことが成り立っている。だけどゼロではない正の数。「且つ」ですね。ゼロ以上且つ正の数

といったら、正の数ですね。しかも整数なので、c は 1 以上の整数なのです。ですから c から1を引いたらゼロ以上だというので、これが証明できました。ですからこれは確かに Loop Invariant だということが証明できました。あともうひとつです。こっち側です。これはプ

ログラミング言語が一切含まれていない部分です。P∧¬C ならば Q。それを証明すると終

わるのです。 (17)例題2 m と n の積(3/3) ループの終了 これが Loop Invariant の p です。且つ∧¬c というのが、これです。これが c です。な

らば、postcondition です。ならば、これ。これが最終的に成り立つ、これです。ですから、

Loop Invariant が成り立っていて、ループを抜け出す条件が成り立ったときには、もう既

に postcondition が成り立っていないといけないのです。これを証明するのですが、これは

もうプログラミング言語は一切入っていないので、普通の数学の計算になります。これは、

c はゼロ以上だといっているのです。且つ、c は正の数ではないといっているのです。ゼロ

以上だけれど正の数ではないということは、ゼロということです。ですからこの二つのこ

とから、c=0 という結論が得られますので、この c にゼロを代入すると、p=mn になって

います。ですからこれが成り立つという証明を簡単にできます。なので、常に Loop

Page 26: 表現系工学特論第3回 (1)逐次プログラムの正当 …kussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/...に話をしますけれども、この構造化プログラミングというものに対してホーア論理という

Invariant が成り立っていて、最後抜け出たときには確かにこうなっているということが証

明できました。ということで、色々細かいことを沢山やりました。 (18)演習問題 演習問題というのは今と似たような問題です。n の階乗を求めているプログラムです。最

終的に p=n!になるのですが、それを今のような考え方で証明しなさいというのが演習問題

です。では、これはこれで今日は終わります。