\chapter{Logo でみる認知科学}

前の章で認知科学のあらましについてみましたが、実際にLogoを使ってその古典的な作品をパソコン上に実現してみましょう。

 

\section{スキナー型ティーティングマシン}

スキナー型\index{すきなーかた@スキナー型}は単純にあらかじめ決められたフレームを次々に出していくものですから作りやすいように思えますが、9割以上は利用者が正答できるようなものを丹念にしつこいほどに繰り返し、条件反射を形成させる必要があります。

 

問題とフレームを次々にだすカラクリとは別のページとして作ります。他の話題にも同じカラクリが使えますから別の話題についてのものを作るときには、問題の内容だけを考えればいいのです。\verb+gettools ファイル名をあらわすワード + でそのページに記されている命令が読み込まれて、プリミティブのように使えるようになります。こうして読み込まれた命令は裏のページを見ても見ることができません。このようなクイズのネタが裏のページでばれてしまうなどということを防げます。\index{gettools@gettools}

 

\begin{center}

\bmpfile(9cm,4cm){skinner.bmp}

\end{center}

 

以下にカラクリを実現するプログラムを記します。

 

{\small

\begin{verbatim}

 

 

=================================================

 

to Skinner

    make "F_Names pagelist

    cleartext

    print "================================

    print "話題は次のものが用意されています

    print "================================

    print ".

    print :F_Names

    print ".

    print "何番目の話題を選びますか?数で答えて下さい。

    print "終わるときには、0を入れて下さい。

    make "K readnum

    if :K < 1 [ stop ]

    gettools item :K :F_Names

    make "i 0

    make "Seitou 0

    make "M      0

    make "R_Ans ""

    showques

    print ".

    print ".

    print ( list "問題数は :M "、正答数は :Seitou "でした。 )

    print ".

    print "お疲れ様でした。他の話題を選んで下さい。

    print "3秒間待って下さいね。

    repeat 3 [

         wait 60

         insert "#_

    ]

    Skinner

end

 

to readnum

    local "memo

    make "memo first readlist

    if ( count :F_Names ) >= :memo [ output :memo ]

    print "数を入力するのですよ。もう一度お願いします。

    output readnum

end

 

to Showques

    print ".

    print "------------------------------.

    make "R_Ans run word "Q :i

    print ".

    make "i :i + 1

    if :i = 1 [

       print  "何かキーを押して下さい。

       print readchar

       Showques

       stop

    ]

    print ".

    print "さあ、答えをどうぞ。

    print ".

    print ".

    print ( list "あなたの答えは readlist )

    print ( list "正答は     :R_Ans "でした。)

    print [あっているようでしたら Y を押してください。]

    print [間違っているようでしたら、N を押してください。]

    print [リターンキーは押さないで下さいね。]

    print [なお、間違えが続くようでしたら係の先生を呼びましょう。]

    make "Sw readchar

    if not ( ( rank :Sw [ y Y ] ) = [ ] )

           [ make "Seitou :Seitou + 1 ]

    show ( list ":i= :i ":m= :m )

    if :i > :M [ stop ]

    Showques

end

 

==================================================

 

 

\end{verbatim}

}%----- end of \small

 

このカラクリを実現するためには、次のような仕様をみたすページで問題の内容が記されている必要があります。\\

\begin{enumerate}

\item \verb+Q0,Q1,Q2,Q3,... + と提示する順に番号が付けられ、しかも飛びなく命令がそのページに記されている。

\item 命令 \verb+ Q0 + は、「○○のコースへようこそ。」と、まずその話題について記し、この \verb+ Q0 + 以外のフレームの数を変数 \verb+ :M + へ入れる。

\item 他の命令は問を \verb+print +によって画面に提示し、その答えを \verb+output +によって出力する Logoの「関数」の形で記されている。

\end{enumerate}

 

では、問題の内容を記したページはどのようにするのでしょう。例えば次のようなものが、スキナー型のTMの特徴について記したものであることがわかるようにページの名前を付けて保存されているとします。

 

{\small

\begin{verbatim}

 

 

====================================================

 

 

to Q0

   print "|ようこそ、このページへ (^_^)|

   print ".

   print "スキナー型のティーティングマシンの特徴について

   print "の学習を行ないます。

   print ".

   make "M 3

   output []

end

 

to Q1

   print "スキナー型のティーティングマシンは一定の順番で問題を

   print "提示していくことから、直線型ティーティングマシンとも

   print "呼ばれています。

   print "

   print "さて、問題です。スキナー型ティーティングマシンの別名

   print "は、何々型と呼ばれているでしょうか。

   output [直線型]

end

 

to Q2

   print "ティーティングマシンはまず、スキナーによって熱心に研

   print "究されました。

   print "スキナーは条件反射の研究者として有名な心理学者です。

   print "条件反射の人間の学習への応用としてティーティング

   print "マシンを考えました。

   print "ティーティングマシンの特徴として次の3つが指摘されて

   print "いますが、条件反射からの知見としてはうなずけるものと

   print "なっています。

   print "1.小ステップの原理

   print "2.積極的反応の原理

   print "3.即時確認の原理

   print "さて、問題です。スキナーがティーティングマシンの開発

   print "に際して参考にしたのは、何々反射の研究でしょうか?

   output [条件反射]

end

 

to Q3

   print "さて、ティーティングマシンの第1の特徴である小ステップ

   print "の原理について考えましょう。

   print "条件反射はある行動をした被験者に、ほうびを与えるなどし

   print "てその行動を強化するとそれ以降その行動をとる確率が

   print "ますこととされますが、このことを学習に応用します。

   print "しかし、学習課題があまりに大きすぎると条件反射の形成が

   print "なされにくいので、初めは画面に出ていることをなぞったり

   print "3択問題にしたり、空所穴埋めにしたりして、その反応すべ

   print "き語句に関する習慣を形成させてからその語句を問うなどを

   print "ステップを細かくします。

   print ".

   print "さて、ここで問題です。ティーティングマシンの第1の特徴

   print "は、形成するべき反応を細かく分けてそのそれぞれをひとつ

   print "習慣の形成をさせていくことにあります。この原理を、何

   print "ステップの原理と言うでしょうか。

   output [小ステップ]

end

 

 

================================================================

 

 

\end{verbatim}

}%--- end of \small

 

調子にのって最後まで載せてしまうとかなりの紙面を食いますから途中でやめておきます。

 

\section{クラウダ型ティーティングマシン}

 

スキナー型は利用者が誤答する前提にたたないものですが、クラウダ型\index{くらうたーかた@クラウダー型}は利用者の反応によって制御の枝分れをします。ある場合は「その通りです。よくわかりましたね」とほめて、ある場合は、その間違えかたに即した説明をするなどをするのです。

%スキナー型が直線型というのに対して、分岐型とか枝分れ型とか言われることもありま%す。

 

ここでは、利用者の反応が3択問題のように有限で、しかも、ひとつのキーであらわされる場合について小問を提示していくカラクリを Logo で作ってみましょう。初めの小問は \verb+ Q + であるとして、次々ある小問で反応されたキーをその小問名の文字列につなげていくことにします。例えば、小問 \verb+ Q132 +での利用者の反応が、\verb+ 3 +であったとすると、次に \verb+ Q1323 +で定義された画面があらわれるようにするのです。

 

\begin{center}

\bmpfile(9cm,4cm){crowder.bmp}

\end{center}

 

しかし、用意するべきフレームの数は、スキナー型ではステップ数だけであったのに、クラウダ型では放っておくとステップ数の指数関数となってしまいます。誤答に対するフォローが済んだら元の問題に戻るなどの枝の刈込みを行なうことにします。いまの小問名を \verb+:NowQues +、次の小問名を関数の値として出力することにしましょう。そして、通常の反応されたキーを文字列につなげて行く次の小問名を関数\verb+ Nxt +で得ることにします。

 

{\small

\begin{verbatim}

 

==================================================

 

 

to Crowder

    cleartext

    make "F_Names pagelist

    print "================================

    print "話題は次のものが用意されています

    print "================================

    print ".

    print :F_Names

    print ".

    print "何番目の話題を選びますか?数で答えて下さい。

    print "終わるときには、0を入れて下さい。

    make "K Readnum

    if :K < 1 [ stop ]

    gettools item :K :F_Names

    print ".

    make "NowQues "Q

    make "History []

    Showques

    print ".

    print ".

    print "お疲れ様でした。他の話題を選んで下さい。3秒待って下さい。

    repeat 3

       [ insert "#_

         wait 60

       ]

    Crowder

end

 

to Showques

    print ".

    print "--------------------------

    print ".

    make "History lput :NowQues :History

    if :NowQues = [stop] [ stop ]

    make "NowQues ( run :NowQues )

    print ".

    Showques

end

 

to Nxt

   print ".

   print "選択肢の番号を答えてください。リターンキーを押す必要はありません。

   output ( word :NowQues Readalt )

end

 

to Readnum

   output first readlist

end

to Readalt

   local "memo

   make "memo readchar

   if ( and ( :memo > 0 ) ( :memo < 5 ) ) [ output :memo ]

   print ".

   print "おやおや?

   print "これは4択なので、1,2,3,4のうちのいずれかで答えてくださいね。

   output Readalt

end

 

to waitkey

   local "dummy

   print "なにかキーを押して下さい。

   make "dummy readchar

end

 

==================================================

 

 

\end{verbatim}

}%----- end of \small

 

さて、問題の内容を記したページですが、例えば次のようにすればよいのです。これも、内容、「運転免許試験のお勉強、駐停車篇」であることがわかるようにページの名前がつけられていることとします。

 

{\small

\begin{verbatim}

 

========================================================

 

 

to Q

   print "==============================================

   print ".

   print "|       策っ!!|

   print ".

   print "|             (駐 停 車 篇)|

   print "==============================================

   print "|ようこそ、このページへ ^_^)|

   print ".

   print "車を駐車、停車させるためのいろいろな法令による

   print "取り決めについて学びます。

   print ".

   waitkey

   output "Q1

end

 

to Q1

   print "車は、信号に従う等法令の規定、警察官の命令または危険防止

   print "のため一時停止する場合を除いて、その駐車によって他の車両

   print "の通行の邪魔になったり、他の業務の支障となったりする場合

   print "駐車、あるいは、駐車および停車が禁止されています。

   print "例えば、運行時間中のバス停の前後何メートル以内は駐停車禁

   print "止になっていますか?

   print "| 次のなかから選んで下さい。|

   print "|   1.)1m。    2.)3m。|

   print "|   3.)5m。    4.)10m。|

   output Nxt

end

 

to Q11

   print "バス停の前後1mに車が止っていると、バスはその停留所に

   print "横付けにできますか?もう一度考えてみて下さい。

   output "Q1

end

 

to Q12

   print "バス停の前後3mに車が止っていると停留所に止る余地は6m

   print "しかありません。バスってどれくらいの長さがありますか?

   print "もう一度考えてみて下さい。

   output "Q1

end

 

to Q13

   print "バス停の前後5mに車が止っていると停留所に止る余地は

   print "10mですが、実際にとめるにはバスの長さよりも余裕をもった

   print "スペースが必要です。バス停に止めるのに切りかえしって

   print "ことは避けたいですからね。

   print "もう一度考えてみて下さい。

   output "Q1

end

 

to Q14

   print "|ピンポーン! ^_^)!!|

   print ".

   print "当たりです。

   print ".

   print "バスの運転手さんの立場になって考えると、止っている車を追

   print "い越してさらに前後に止っている車にぶつけないようにバス停

   print "につけるためには、やっぱり前後10mの余地は欲しいですね。

   print "=============================================

   print "1を押して下さい。

   output Nxt

end

 

to Q141

   print ".

   print "では、次の問題です。

   print "火災報知器から何メートル以内は駐車禁止でしょうか?

   print "

   print "| 次のなかから選んで下さい。|

   print "|   1.)1m。    2.)3m。|

   print "|   3.)5m。    4.)10m。|

   output Nxt

end

 

to Q142

   print "1を押してくださいって言った

   print "のですが、まあ良いでしょう。

   output "Q141

end

 

to Q143

   output "Q142

end

 

to Q144

   output "Q142

end 

 

to Q1411

   print "あたりです。

   print ".

   print "もっとこの例示を続けたいところですが、あまりノンベンダラリ

   print "と続けていると紙面がもったいないので、ここらで終わりにする

   print "例にしてしまいましょう。

   output [stop]

end

 

to Q1412

   print "火災報知器ってのは、火事だっ!て駆込んでボタンを押すた

   print "めのものですよね。あなたはどれくらいの余地があればその間を

   print "駆け抜けることができますか?

   print "本当は次に消防水利の前後は?って問題を挿入したいところです

   print "が、すなおにもとに戻りましょう。

   output "Q141

end

 

to Q1413

   output Q1412

end

 

to Q1414

   output Q1412

end

 

=======================================================

 

 

\end{verbatim}

}%----end of \small

 

\Toi{%{\bf (問19−1)}

 あまり考えてない利用者は、表示をいい加減にみて適当に答えるので、同じ箇所を5回通ってしまうことがあるかもしれません。履歴をあらわすリスト\verb+:History+ を使って、このようなときに、「係の先生を呼んで下さい。」の表示を出すように改造してください。}

 

\section{系統的試行錯誤}

 

系統的試行錯誤の例として、スタインハウス~キューブを扱いましょう。

まず、系統的試行錯誤って何かという説明をしなければなりませんね。

因数定理を用いて高次方程式を解くという話題を\pageref{insut}ページ

に扱っていますが、人間は何となく解だと思われる数$ x_1 $を代入してみて

方程式を満たせば、それは本当に解なのですね。ですから、その方程式は

$(左辺)-(右辺)$$(x-x_1)$の約数。そこで、$x_1$ と、

$$\displaystyle \frac{(左辺)-(右辺)}{x - x_1} = 0 $$

の解とがもとの方程式の解である。このような手順で次々ひとつ次数が低い

方程式を考えていくことができるので、最終的には2次方程式の解の公式に

帰着させることができるというものです。

 

でも、どうでしょう。人間は何となく解だという台詞を言えるでしょうが、

コンピュータには、どのようなものを何となく解だと思えと教えてやらな

ければこの場合いけなさそうです。コンピュータは{\bf 機械的}計算力が

ありますから、有限でありさえすれば当たらずも八卦で、やたらと候補を

作る方法を教えてあげれば、ともあれかたっぱしから試行してみるでしょう。

もっとも、必ず本当の解がこの候補のなかに入っていないと解けませんが。

もう一言付け加えれば、分母が最高次の係数の絶対値の約数、分子が定数項の

絶対値の約数

であるすべての分数、および、それらの符号を変えたものを解の候補とすれば

よいのです。解の候補をリストに並べて、左から順に確かめて、リストの要素が

なくなったら文句をいう。ざっとこのような手順になるでしょう。

 

リストの要素をかたっぱしから確かめるということは、試行錯誤に他なりません。

しかし、リストの要素は有限で解が必ず含まれているというのは、同じ試行錯誤でも

解けることが保証されています。このような「保証」の意味を「系統的」に込めた

のです。人間にとってもこれはちょっと教訓的で、迷路などの試行錯誤では、場合に

よってはうっかりすると解を見逃してしまっていていつまでも出られないという

ことがありえます。しかし、右へ曲がるか左へかと系統的に選んでいけば長くは

あっても有限の時間で出られる

保証はあるのです。やってみて、駄目なら他の手を選ぶのですが。

他の手といっても迷路などは、一手先を読むだけでは駄目だという

ことがわかりません。将棋とかオセロ、チェスとなると他の工夫も必要になるでしょう。

ともあれ、左右に分かれる選択肢を全部右、右と選んでいって、どん詰まりになったら、さっき選んだ分かれ道

に戻ってそこだけ左を選んで、それから先はさっきまでと同じく、全部右、右と選択肢

を選んでいくのです。分かれ道が2通りでなくとも適当な順番をつけて、その順に選べば

よいでしょう。\vspace{2zh}

 

{\small

$

\begin{array}{ccccccccc}

 &       &        & &              &入口      &        &        & \\

 &       &        & &\swarrow      &          &\searrow&        & \\

 &       &        &分岐(1)&        &          &        &分岐(3) & \\

 &       &\swarrow&       &\searrow&          &\swarrow&        &\searrow\\

 &分岐(2)&        &       &変なオジサン& &出口  &        &美女\\

\swarrow& &\searrow&      &        &            &      &        &  \\

& &        &タヌキ&        &            &      &        & 

\end{array}

$

}%end of \small

\vspace{2zh}

 

ここで、熊にであってしまったら食べられちゃって一巻のおしまいなどと

いうことは考えずに、どん詰まりではあるが入り込んでも人畜無害であると

すると、上から下に向かってまず右を選ぶという戦略をたてれば、

 

$$入口 \longrightarrow 分岐(1) \longrightarrow 分岐(2) \longrightarrow

$$

$$ \longrightarrow 分岐(2) \longrightarrow タヌキ \longrightarrow

分岐(2) \longrightarrow 分岐(1)

$$

$$\longrightarrow 変なオジサン \longrightarrow 分岐(1)

\longrightarrow 入口 \longrightarrow 分岐(3)$$

$$ \longrightarrow 出口

$$

 

の順に歩むことになりますね。つまり、変なオジサンには会うけど、美女には

会えないのです。

 

さて、前置きが長くなりました。スタインハウス~キューブとは、スタインハウス

がその著書『数学スナップショット』(紀伊国屋)で紹介したことからこのような

名で、高木茂男『Play Puzzle』(平凡社)、『実験数学のすすめ』(数学教室誌別冊:

国土社)などに記されています。

6つのデコボコな木片をぴったり合わせて立方体を作るパズルです。

さて、デコボコな木片とはできる予定の立方体の$\dfrac{1}{3}$の辺の長さの

小立方体を付けたものです。このプログラムを全部紹介するだけの紙面はありませんが、

はじめの一部分を次に紹介します。

 

\vfil

 

\begin{center}

\bmpfile(10cm,8.67cm){stein.bmp}

\end{center}

 

\newpage

 

{\small

\begin{verbatim}

 

=====================================================

 

to Stein

   make "Solu []

   make "Block

     [ [ [0 0 0][0 0 1][1 0 0][1 1 0][2 0 0] ]

       [ [0 0 0][1 0 0][1 0 1][1 1 1][2 1 1] ]

       [ [0 0 0][1 0 0][2 0 0][2 1 0][2 1 1] ]

       [ [0 0 0][1 0 0][1 1 0][1 1 1]        ]

       [ [0 0 0][1 0 0][1 0 1][1 1 1]        ]

       [ [0 0 0][0 1 0][1 0 0][2 0 0]        ]

     ]

   make "NumOfRotPat 24

   make "NumOfBlocks count :Block

   make "Space [ [ [0 0 0][0 0 0][0 0 0] ]

                 [ [0 0 0][0 0 0][0 0 0] ]

                 [ [0 0 0][0 0 0][0 0 0] ]

               ]

   TryAndError 1 1 [1 1 1] []

   print :Solu

end

to TryAndError :BlockNum :RotPat :Posi :History

   print (list "##_TryAndError :BlockNum :RotPat :Posi )

   if ( :Posi = [CarryUp] )

      [ TryAndError :BlockNum ( :RotPat + 1 ) [1 1 1] ]

   if ( :RotPat > :NumOfRotPat )

      [ BackTrack  :BlockNum ]

   if CanInsert?

      [ make "History ( lput :Posi :History )

        if :BlockNum = :NumOfBlocks

           [ make "Solu ( lput :History :Solu ) ]

        TryAndError

            ( :BlockNum + 1 ) 1 [1 1 1]

            (lput :Posi :History)

      ]

   TryAndError :BlockNum :RotPat ( Nxt :Posi ) :History

end

 

====================================================

 

\end{verbatim}

}%end of \small

 

\verb+Block + という名前が付けられるリストがデコボコな木片の

形をあらわしています。このリストは6つの要素がありますが、それぞれが

6つの木片をあらわしています。

それぞれの木片は5個か4個の小立方体からなっています。

これらの小立方体のうち、ひとつの位置を\verb+ [ 0 0 0 ] +

として、その右隣を \verb+ [ 1 0 0 ] +、そのすぐ上を \verb+ [ 0 0 1 ] +

というように、3次元の座標としてあらわしています。

木片をあらわす要素は、さらに5つか4つの要素を持っていますが、このそれぞれの

要素が小立方体が占めるべき位置

なのです。

 

\verb+Space + としては、木片を入れるべき空間の状態をあらわす変数です。

うまく入れば、$3 \times 3 \times 3 $ の立方体になりますから、その中の

小立方体の位置がリストとして表現されています。今は何も入っていませんから

0 が入っていますが、

その場所が木片に占められたら、木片が何番目のものかという数(\verb+BlockNum +)

をリストの

中の要素であるワードに入れてあらわします。ですから、この \verb+ Space +

3つのワードが要素であるリスト要素となっている3つのリストが、さらに要素と

なっているリストというデータ構造となっています。

 

さて、この場合の試行錯誤とは何でしょう。コンピュータの中のデータ構造には

重力にかかわりがありませんから無理な入れ方もできます。できあがった図をとり

あえず作っておけば、その処方箋に従って重ねていけばいいのです。

ですから、1番目にかいてある木片から順に置いていくことにしましょう。

では、どこにどの向きで置きましょうか。

 

場所は、$3 \times 3 \times 3 = 27 $ 個のうちでまだ木片が入っていないもの、

つまり、\verb+Space + の要素のうち値が 0 であるところなら全部取り得ることに

しましょう(\verb+ :Posi +)。向きは、色分けされた立方体の向きを考えると、どれが上に行くか

6通り、さらに側面となっている4つのうちどれが手前に来るかで決まりますから

都合 24通りを考えることができます(\verb+ :RotPat +)6つの木片のこの2つの要因に関して系統的

試行錯誤を行なっていけば良いのです。

 

まず、向きによって木片の中の小立方体の位置を翻訳して、端の小立方体の位置に

よっても、木片の中のそれぞれの小立方体の位置を平行移動して、それぞれを

入れることができるか判断します。この場合、対応する \verb+Space +の要素が

0 かどうかで判定できます。駄目ならこの木片に関して他の占めうる位置、向き

で確かめていき、入るなら \verb+ Space +の値をそれに応じて変えて、次の

木片を手にするのです。

 

次々に入れていけば、途中でこれ以上入らないことがでてきます。そのような

ときには、前に入れた木片をどけるという後戻り(\verb+ BackTrack + )をしましょう。

これには、\verb+ Space + の要素のうち、値が \verb+ ( :BlockNum - 1 ) +のものの

値を 0 にして、その位置、向きに関する次の可能性以降を系統的試行錯誤

をしていくのです。

 

かなり長いプログラムになりますし、実行時間もかかります。ですからいまどのような

状態か順次、画面へレポートさせるようにしなければ、何も変化がない時間が長くなって

故障かと思われるかも知れません。その表示の仕方を工夫しましょう。

 

ところで、このパズルの場合、上下左右、手前奥の6面に関する隣がどれも他の小立方体によって占められていればこれ以上他の木片を入れようと思っても無理です。

私が途中経過をあらわす画面をみて気が付いた判定条件です。

   

  

 

\section{三段論法を理解する会話}

 

三段論法\index{さんたんろんほう@三段論法}ってご存知ですよね。「ソクラテスは人間である。」「人間はいつかは死ぬ。」よって、「ソクラテスはいつかは死ぬ。」ってことができれば、つぎのような「会話」ができるはずです。(『』は人間、「」はコンピュータの台詞です。)\vspace{2zh}\\

『酒井法子は 歌手』\\

「はいそうですか。」\\

『酒井法子は ノリピー』\\

「はいそうですか。」\\

『パイレーツは 2人組み』\\

「はいそうですか。」\\

『ノリピーは かわいい』\\

「はいそうですか。」\\

『歌手は CDを出す』\\

「はいそうですか。」\\

『酒井法子は CDを出す か』\\

「ええと、ちょっと待って下さい\\

 酒井法子は 歌手\\

 歌手は CDを出す\\

 だから\\

 はい、酒井法子は CDを出す」\vspace{2zh}

 

これは、\verb+:酒井法子 +という変数に \verb+[歌手 ノリピー] +をいれて、\verb+:歌手 +という変数に \verb+[CDを出す]+をいれ

られるようにすると実現できます。

 

これは、「主語+は」の後に必ず空白を入れる。「かわいいです」などの「です」「ます」などを入れずに言いきりにする。疑問の場合は文末に空白+「か」を入れる。などなどの特殊なフォーマットで入力をする必要がありますが、次の手順で判断がなされるでしょう。

\begin{enumerate}

\item 入力された『酒井法子は CDを出す か』というリストの最後が「か」であることから「疑問に対して答える」部分を起動する。

\item 変数\verb+ :酒井法子 +に、「CDを出す」が含まれているかどうか調べる。含まれていれば、すぐに「はい 酒井法子は CDを出す のです」と答え、含まれていないときだけ次の処理に入る。

\item 変数\verb+ :酒井法子 +に含まれている要素のうち変数名ともなっているものを選び出す。

\item 前項の変数それぞれについて、その要素に「CDを出す」があるかどうか調べる。

\item その結果によって、

「ええと、ちょっと待って下さい\\

 酒井法子は 歌手\\

 歌手は CDを出す\\

 だから 酒井法子は CDを出す」\\

などの返事をする。

\end{enumerate}

%\vfil

 

\begin{center}

\bmpfile(10cm,4.44cm){syllo.bmp}

\end{center}

 

%\newpage

 

さて、このようなプログラムを考えてみましょう。

 

{\small

\begin{verbatim}

 

=================================

 

to Syllogium

   clearnames

   cleartext

   print "こんにちは、なにかお話してください。

   ToldSomething

   print "いやあ、お話しできて楽しいときを過ごせました。ごきげんよう。

end

 

to ToldSomething

   local "L

   make "L readlist

   if (count :L) = 1

     [ if :L = [じゃあまた]

           [stop]

       Alarm :L

     ]

   if (count :L) = 2 [ GetKnowledge :L ]

   if (count :L) = 3 [ AnswerQues   :L ]

   if (count :L) > 3 [ Alarm        :L ]

   ToldSomething

end

 

to Alarm :L

   print "あなたが、入力してくださった

   print :L

   print "は、分かち書きがわたしにとって、分かりにくい

   print "ものです。恐れ入りますが、書き直して下さいませんか?

   ToldSomething

end

 

to GetKnowledge :L

   if not ( last first :L ) = " [Alarm]

   print "|Now I will do GetKnowledge|

   print "============================

   printnames

   print "---1

   if ( not name? Subj ) [ make Subj [] ]

   printnames

   print "---2

   if ( not member? Zokusei thing Subj)

      [ make Subj lput Zokusei thing Subj]   printnames

   print "============================

   print "###はいそうですか。###

end

 

to Subj

   output butlast first :L

end

 

to Zokusei

   output last :L

end

 

to AnswerQues :L

   make "L butlast :L

   if Yes? Subj Zokusei

      [ print (word "###はい、 :L "### )

        stop

      ]

   print word "###いいえ、 :L "でないです。 "### )

end

 

to Yes? :S :Z

   print (list "|doing Yes?| :S :Z )

   if (not name? :S )

      [ output 0 = 1]

   print count ( rank  :Z  thing :S )

   if ( count rank :Z thing :S ) > 0

      [ output 1 = 1  ]

   print "ちょっとまってくださいね。

   if ( CanSearch? :S  thing :S :Z )

      [ output 1 = 1 ]

   output 0 = 1

end

 

to CanSearch? :A :B :C

   print (list "CanSearch :A :B :C )

   if ( count :B ) = 0 [ output 0 = 1 ]

   print ( word :A "は、 first :B "ですね。)

   if ( not name? first :B )

      [ print "でも、関係ないですね。]

   if ( name? first :B )

      [ if ( Yes? first :B :C )

           [ output 1 = 1

             stop

           ]

      ]

   print "また、ちょっとまってくださいね。

   output CanSearch? :A butfirst :B :C

end

 

===========================================

 

 

\end{verbatim}

 

}% end of \small

 

{\bf 出力例 } 「会話」の例を紹介します。本来の出力には、###

で括って、途中の変数の状態などを記しています。

 

{\small

 

\begin{verbatim}

 

--------------------------------------

 

 

こんにちは、なにかお話してください。

みけは ねこ

Now I will do GetKnowledge

============================

なまえは "L [みけは ねこ]

---1

なまえは "L [みけは ねこ]

なまえは "みけ []

---2

なまえは "L [みけは ねこ]

なまえは "みけ [ねこ]

============================

###はいそうですか。###

ねこは さかなすき

Now I will do GetKnowledge

============================

なまえは "L [ねこは さかなすき]

なまえは "みけ [ねこ]

---1

なまえは "L [ねこは さかなすき]

なまえは "ねこ []

なまえは "みけ [ねこ]

---2

なまえは "L [ねこは さかなすき]

なまえは "ねこ [さかなすき]

なまえは "みけ [ねこ]

============================

###はいそうですか。###

みけは さかなすき

doing Yes? みけ さかなすき

0

ちょっとまってくださいね。

CanSearch みけ [ねこ] さかなすき

みけは、ねこですね。

doing Yes? ねこ さかなすき

1

###はい、みけは さかなすき###

みけは うちの

Now I will do GetKnowledge

============================

なまえは "L [みけは うちの]

なまえは "ねこ [さかなすき]

なまえは "みけ [ねこ]

---1

なまえは "L [みけは うちの]

なまえは "ねこ [さかなすき]

なまえは "みけ [ねこ]

---2

なまえは "L [みけは うちの]

なまえは "ねこ [さかなすき]

なまえは "みけ [ねこ うちの]

============================

###はいそうですか。###

ねこは けもの

Now I will do GetKnowledge

============================

なまえは "L [ねこは けもの]

なまえは "ねこ [さかなすき]

なまえは "みけ [ねこ うちの]

---1

なまえは "L [ねこは けもの]

なまえは "ねこ [さかなすき]

なまえは "みけ [ねこ うちの]

---2

なまえは "L [ねこは けもの]

なまえは "ねこ [さかなすき けもの]

なまえは "みけ [ねこ うちの]

============================

###はいそうですか。###

みけは けもの

doing Yes? みけ けもの

0

ちょっとまってくださいね。

CanSearch みけ [ねこ うちの] けもの

みけは、ねこですね。

doing Yes? ねこ けもの

1

###はい、みけは けもの###

みけは にゃーとなく

doing Yes? みけ にゃーとなく

0

ちょっとまってくださいね。

CanSearch みけ [ねこ うちの] にゃーとなく

みけは、ねこですね。

doing Yes? ねこ にゃーとなく

0

ちょっとまってくださいね。

CanSearch ねこ [さかなすき けもの] にゃーとなく

ねこは、さかなすきですね。

でも、関係ないですね。

また、ちょっとまってくださいね。

CanSearch ねこ [けもの] にゃーとなく

ねこは、けものですね。

でも、関係ないですね。

また、ちょっとまってくださいね。

CanSearch ねこ [] にゃーとなく

また、ちょっとまってくださいね。

CanSearch みけ [うちの] にゃーとなく

みけは、うちのですね。

でも、関係ないですね。

また、ちょっとまってくださいね。

CanSearch みけ [] にゃーとなく

###いいえ、みけは にゃーとなくでないです。###

じゃあまた

いやあ、お話しできて楽しいときを過ごせました。ごきげんよう。

 

-----------------------------------------------

 

\end{verbatim}

 

}%---end of \small

 

\noindent

\Toi{%{\bf (問19−2)}

「歌手」を「歌手です」などと入れてもうまくいくようにするためはどのような工夫をすればよいでしょうか。}%\\

\Toi{%{\bf (問19−3)}

「ミケは猫。猫は哺乳類。哺乳類は肺を持っている。さて、ミケは肺を持っているか」という「三段」以上の処理をこのプログラムは行なうことができるでしょうか。

}

 

\section{英語の発音の学習}

 

英語の綴りを読んで発音をすることは、我々外国人にとっては難しいものです。一見不規則でありながら、規則性もあります。英語の単語を入力されたら、その発音のローマ字表示を初めは当てずっぽで、すでに経験のある部分が綴りにある場合はそれから類推して出力する。それがあっていたか利用者に聞いて、その結果に応じて学習していくプログラムを作ってみましょう。次のような問答になるでしょう。

 

\begin{verbatim}

「英単語を入力して下さい。読んでみます。」

cat

kat  あってますか?」

n』(いいえ)

「では、どう発音するのですか?」

kaet

「英単語を入力して下さい。読んでみます。」

cap

kaep  あってますか?」

y』(はい)

「英単語を入力して下さい。読んでみます。」

car

kaer  あってますか?」

n

「では、どう発音するのですか?」

kahr』         などなど。

 

\end{verbatim}

漢字変換の学習機能も大雑把に言えばこのようなカラクリによるものでしょう。

さて、このようなプログラムは英語のネイティブをする幼児が字を学んで行く過程をシミュレイトすることになります。どのような学習、すなわち、あてずっぽの答えをどのように生成すれば効率がよいでしょうか。また、学習をさせる側、つまり例語を与える側はどのような語をどの順番に与えるとよいでしょうか。また、実際の学習と異なる部分はどのようなところにあるでしょうか。\\

{\bf 【参考文献】 }James R. Slagle,1971/南雲仁一他,1972『人工知能----発見的プログラム』(産業図書)第12

 

\section{計算間違えのシミュレーション}

 

計算間違え\index{けいさんまちかえ@計算間違え}には、いろいろなものがあります。例えば、$4 \times 7 = 26 $ \verb+!?+などという九九をうっかり言い違えるとか、すでに1回繰り上がりをしているのに、もう1回同じ繰り上がりをしてしまうとか。うっかり間違えなら同じような計算を行なって10回中9回はマトモな結果になるでしょう。しかし、アルゴリズムを誤解している場合、ほとんどすべての計算がうまくいかないはずですが、計算のタイプがまれにしか起こらない場合、うっかり間違えとして扱われて指導者が気付かないまま、不注意な子だと思われてしまうことになりかねません。

 

Brown\footnote{Brown and VanLehnTowards a Generative Theory of bugs’” in Carpenter et al. ed.,1982Addition and SubstractionA Cognitive Perspective(Lawrence Erlbaum Associates,Publishers)}は次のような「バグ」を想定しています。

\begin{enumerate}

\item いつも左端の位から繰り下がりの借りを作ってしまう。

$$733-216=427$$

\item 繰り下がりが必要になるとそこを空欄にして次の作業に飛んでしまう。

 

\item ゼロから借りるべきときのみ前項のバグが起こる。

\item それぞれの位で、上から下ではなく大きい方から小さい方を引いてしまう。

$$ \cdots \cdots $$

などです。

\end{enumerate}

%\vspace{1.5zh}\\

\begin{center}

$

\begin{array}{llllllllll}

  (1)& &7&3&3& (2)& &4&2&5\\

     &-&2&1&6&    &-&2&8&3\\

  \cline{2-5} \cline{7-10}  

     & &4&2&7&    & &2& &2\\[1.5zh]

 (3)& &5&1&2& (4)& &5&1&3\\

    &-&2&4&5&    &-&2&6&8\\

\cline{2-5} \cline{7-10}

    & &3& &7&    & &3&5&5\vspace{1.5zh}

\end{array}$

\end{center}

Buggy \index{はきー@バギー}というプログラムは、学生に次のようなバグの提示をしてどのようなバグかをあてされるものです。『人工知能ハンドブック』\footnote{Avron Barr, Edward A. Feigenbaum ed.,1982/田中幸吉,淵 一博(監訳),1983(共立)}に引用されている様子の大要を記します。 \\[2zh]

{%\small

「次のような計算は、何等かのバグを含んでいます。\\

   17+5=13\\

これと同じようなバグが出る問題を私に出して下さい」\\

『 18+6=』\\

「       15\\

もうひとつ出して下さい。\\

『 43+79=』\\

「       23\\

 どのようなバグかわかりましたか?では、このバグでは次の計算\\

結果はどうなるでしょう?\\

   21+39=」\\

『51』\\

「いいえ、違います。このバグによれば、\\

答えは 15になるはずです。\\

これと同じようなバグが出る問題を私に出して下さい」(以下繰り返し)

\\[2zh]

=========================================

\\[2zh]

}%---end of \small

念の為ですが、ここに設定されていたバグは「位に関係なくすべての数字を足してしまっている」です。

 

さて、このようなプログラムを実現してみましょう。筆算形式に計算の表示するように工夫してみましょう。また、バグを含んだ結果を出力する関数を、PsudoCal とでもして、いくつかのページでそれぞれのバグを含んだ PsudoCal を定義することにします。このページをティーティングマシンの節でも使ったように \verb+gettools+ で読み込むことにしましょう。このページを乱数を使って選ぶことにすれば、バグをあてるクイズになりえるでしょう。

 

 

\section{アニマル}

さて、この章の最後は、前に紹介したアニマル\index{あにまる@アニマル}を扱います。

{\small

\begin{verbatim}

 

==============================

 

to Animal

   make "World [ひとみちゃん]

   Stop_or_Continue

end

to Stop_or_Continue

   insert "パパがだれのことかんがえているかあててあげようか?

   if YesOrNo [ Guess :World stop ]

   insert "じゃあ、またあとであそうぼうね。これおぼえとく?

   if YesOrNo [ savename "World ( word AskFile ".nam ) ]

end

to AskFile

   print "どのファイルへセーブしますか?

   output first readlist

end

to Guess :Scope

   local [ RightAns Ques ]

   if ( count :Scope ) = 1

     [ insert ( sentence :Scope "でしょ? )

       if YesOrNo

         [ print "ひとみちゃんおりこうでしょ。じゃあいまね

           Stop_Or_Continue

         ]

       print "まちがえちゃった。じゃあだあれ?

       make "RightAns readlist

       print ( sentence :RightAns "がyで、

               :Scope "nになる質問なあに? )

       make "Ques readlist

       GetSmarter :Scope :Ques :RightAns

       Stop_Or_Continue

     ]

   insert ( sentence ( first butfirst :Scope ) "? )

   if YesOrNo [ Guess last :Scope ]

   Guess first :Scope

end

to YesOrNo

   local "C

   make "C readchar

   print ( word "|     |  :C )

   if :C = "y [ output 1 = 1 ]

   if :C = "n [ output 0 = 1 ]

   print [ y n じゃないとやだ! ]

   output YesOrNo

end

to GetSmarter :WrongAns :Ques :RightAns

  make "World Swap ( list :WrongAns :Ques :RightAns ) :WrongAns :World

  print ( list "$$$__ :World )

end

to Swap :New :Old :In

  local "Genkou

  print ( list "###_Doing__Swap :New :Old :In )

  if empty? :In [ output P [] ]

  if word? first :In

    [ if :In = :Old

       [  output P :New  ]

       output P :In

    ]

  make "Genkou fput ( Swap :New :Old ( first :In ) )

                 ( Swap :New :Old ( butfirst :In ) )

  output P :Genkou

end

to P :L

  print ( list "###_output_is :L )

  output :L

end

 

========================================

\end{verbatim}

 

 

 

}%-----end of \small

 

この意外に短いプログラムで重要な役割をしているのが、\verb+GetSmarter Swap +

です。この働きがやや難解に思われますので途中経過を、\verb+###,$$$ +などを

前置して出すようにしています。もっとも私が作る途中、デバッキング\index{てはっきんく@デバッキング}のために

付けたものをそのままにしてあるだけですが。

 

\input ume3.tex

%\input ume4.tex