lispでapplicationを作成する場合、まず、行わなければならないことは、「データの表現をどうするか」ということです。
具体的には、ここで、扱いたい、行列やベクトルを、lispで扱える形式( S-式: listとatom )の、どのように形に対応させるかという問題です。
ベクトル、すなわち、数の並びは、それほど悩む必要はありません。すなわち、数のlistで表現すればよいからです。
しかし、厳密に考えると、縦ベクトルと横ベクトルでは、本来、異なるわけですから、一方を、単なるlistにするのであれば、他方を、これとは(区別可能な.. )異なる形にする必要があります。
こでは、あまり厳密には考えずに、原則として、縦ベクトルだけを考え、これを数のlistとする(37)ことにします。
(vadd '(1 2 3) '(4 5 6))
ベクトルのスカラー倍を計算するsprodを定義しなさい。
(sprod 3 '(3 5 9) )の結果は、(9 15 27)
もし、縦ベクトルと横ベクトルを、それぞれ( v x1 x2 x3 ), ( h x1 x2 x3 )のように、先頭の要素で区別した形で、表現するとしたとき、それに対応したベクトルの和を計算するvvadd, hvaddをそれぞれ作成しなさい。
(vvadd '( v 1 2 3 ) '( v 4 5 6 ) )の値は( v 5 7 9 )
(hvadd '( h 1 2 3 ) '( h 4 5 6 ) )の値は( h 5 7 9 )
縦ベクトルと横ベクトルを区別して扱いたい場合は、何らかの表現が必要になります。ここで、重要なことは、それを表現する規則を自分なりに決めて統一的に扱うことです。
例えば、三つの要素が3, 4, 9の三次元縦ベクトルを(v 3 4 9)で表し、同じ要素をもつ横ベクトルを、(h 3 4 9)で表す(つまり、最初の要素がvなら縦、hなら横と考えます)とします。そうすれば、縦ベクトルと横ベクトルは、異なる表現になるので、区別して扱うことが可能になるわけです。
m行n列の行列は、lispで、どのように扱えば良いでしょうか。ここでも、様々な形を考えることができます。例えば、3行2列の行列で、各要素が、x11, x12, x13, x21, x22, x23である行列を、( 3 2 x11 x12 x13 x21 x22 x23 )と表現してもかまいませんし、また、列ベクトル(縦ベクトル)を、前節のルールに従って、(x11 x21), (x12 x22), (x13 x23)と表現し、そのlist ((x11 x21) (x12 x22) (x13 x23))を、行列と考えることも可能でしょう。
しかし、ここでは、ちょっと、奇妙に感じるかもしれませんが、行ベクトルのlistすなわち、( (x11 x12 x13) (x21 x22 x23) )で表現することにします。
これは、行列と、縦ベクトルの積が簡単に定義できるようにするためです。
行列の和を計算するmaddを考え、定義しなさい(ヒント: vaddを利用)。
(madd '( (1 2 3) (4 5 6) (7 8 9) ) '( (1 -1 2) (2 1 -2) (-3 0 2) ))の値は((2 1 5) (6 6 4) (4 8 11))
行列と縦ベクトルの積を計算するmvprodを考え、定義しなさい(ヒント: vprodを利用)。
(mvprod '((1 2 3)(4 5 6)(2 2 2) '(1 -1 2))の値は(5 11 4)
listのlistが与えられたときに、各要素のcar部だけを集めて作られるlistを返す関数carlistを定義しなさい。
(carlist '( (1 2 3) (4 5 6) (7 8 9)))の結果は、(1 4 7)この関数は、行列の最初の縦ベクトルを求めることに、注意しなさい。
listのlistが与えられたときに、各要素のcdr部だけを集めて作られるlistを返す関数cdrlistを定義しなさい。
(cdrlist '( (1 2 3) (4 5 6) (7 8 9)))の結果は、((2 3) (5 6) (8 9))この関数は、行列の最初の縦ベクトル取り除いた行列を求めることに、注意しなさい。
上記のcarlist, cdrlistを利用して、transを実現しなさい。
(trans '( (1 2 3) (4 5 6) (7 8 9)))の結果は、((1 4 7) (2 5 8) (3 6 9))
transを二回適用するとどうなるかを考えなさい。
(trans (trans '( (1 2 3) (4 5 6) (7 8 9))))
の結果は、どうなるだろうか?
最初の引数が、行ベクトルのlist,二つ目の引数が、列ベクトルのlistで表現されている二つ行列の積を列ベクトルのlistの形で求める関数mprodsubを考えなさい(ヒント: mvprodを利用)。
(mprodsub '( (1 2) (3 1) ) '((5 6) (-1 1)))の結果は、((17 21) (1 -2))
mprodsubとtransを組み合わせれば、mprodが完成できる。実際にmprodを定義しなさい。
(mprod '( (1 2) (3 1) ) '( (5 -1) ( 6 1 ) ) )の値は、((17 1) (21 -2))