Powered by SmartDoc

データ表現

lispでapplicationを作成する場合、まず、行わなければならないことは、「データの表現をどうするか」ということです。

具体的には、ここで、扱いたい、行列やベクトルを、lispで扱える形式( S-式: listとatom )の、どのように形に対応させるかという問題です。

ベクトルの表現

ベクトル、すなわち、数の並びは、それほど悩む必要はありません。すなわち、数のlistで表現すればよいからです。

しかし、厳密に考えると、縦ベクトルと横ベクトルでは、本来、異なるわけですから、一方を、単なるlistにするのであれば、他方を、これとは(区別可能な.. )異なる形にする必要があります。

こでは、あまり厳密には考えずに、原則として、縦ベクトルだけを考え、これを数のlistとする(37)ことにします。

[演習3.1.1]
縦ベクトルの和を計算する関数vaddに関して、次の作業を行いなさい。
  1. vadd.txtに、vaddが定義されているので、loadを利用して、これを読み込みなさい。
  2. 二つの3次元縦ベクトル(1 2 3)と(4 5 6)の和をvaddを利用して計算しなさい。具体的には、次の式を入力しなさい。
    (vadd '(1 2 3) '(4 5 6))
    
[演習3.1.2]

ベクトルのスカラー倍を計算するsprodを定義しなさい。

(sprod 3 '(3 5 9) )の結果は、(9 15 27)

[演習3.1.3]

もし、縦ベクトルと横ベクトルを、それぞれ( 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 )

  1. 縦ベクトルと横ベクトルを区別して扱いたい場合は、何らかの表現が必要になります。ここで、重要なことは、それを表現する規則を自分なりに決めて統一的に扱うことです。

    例えば、三つの要素が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) )で表現することにします。

これは、行列と、縦ベクトルの積が簡単に定義できるようにするためです。

[演習3.1.4]

行列の和を計算する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))

[演習3.1.5]

行列と縦ベクトルの積を計算するmvprodを考え、定義しなさい(ヒント: vprodを利用)。

(mvprod '((1 2 3)(4 5 6)(2 2 2) '(1 -1 2))の値は(5 11 4)

[演習3.1.6]
行ベクトルのlistで表現されている行列を、列ベクトルのlistに変換するtransについて、次の問いに答えなさい。
  1. listのlistが与えられたときに、各要素のcar部だけを集めて作られるlistを返す関数carlistを定義しなさい。

    (carlist '( (1 2 3) (4 5 6) (7 8 9)))の結果は、(1 4 7)この関数は、行列の最初の縦ベクトルを求めることに、注意しなさい。

  2. listのlistが与えられたときに、各要素のcdr部だけを集めて作られるlistを返す関数cdrlistを定義しなさい。

    (cdrlist '( (1 2 3) (4 5 6) (7 8 9)))の結果は、((2 3) (5 6) (8 9))この関数は、行列の最初の縦ベクトル取り除いた行列を求めることに、注意しなさい。

  3. 上記のcarlist, cdrlistを利用して、transを実現しなさい。

    (trans '( (1 2 3) (4 5 6) (7 8 9)))の結果は、((1 4 7) (2 5 8) (3 6 9))

  4. transを二回適用するとどうなるかを考えなさい。

    (trans (trans '( (1 2 3) (4 5 6) (7 8 9))))

    の結果は、どうなるだろうか?

[演習3.1.7]
行列の掛け算を計算するmprodについて、次の問いに答えなさい。
  1. 最初の引数が、行ベクトルのlist,二つ目の引数が、列ベクトルのlistで表現されている二つ行列の積を列ベクトルのlistの形で求める関数mprodsubを考えなさい(ヒント: mvprodを利用)。

    (mprodsub '( (1 2) (3 1) ) '((5 6) (-1 1)))の結果は、((17 21) (1 -2))

  2. mprodsubとtransを組み合わせれば、mprodが完成できる。実際にmprodを定義しなさい。

    (mprod '( (1 2) (3 1) ) '( (5 -1) ( 6 1 ) ) )の値は、((17 1) (21 -2))