1.3 属性の宣言と属性値
1.3.5 atvalue 函数による函数値の設定
(%i9) properties(mike);
(%o9) [value, [user properties, value_check], special]
(%i10) mike:15;
(%o10) 15
(%i10) :lisp (get ’$mike ’assign) NIL
(%i10) :lisp (put ’$mike ’assign-mode-check ’assign) ASSIGN-MODE-CHECK
(%i10) mike:15;
15 is not prime!!
#0: ptest(y=15)
-- an error. Quitting. To debug this try debugmode(true);
この例では,最初に素数でなければエラーを返す述語函数ptestを定義し,それから, define variable 函数で大域変数tamaに初期値5を与えて整数変数として宣言します.それから,qput函数を用い てcheck value属性にptestを与えます.この時, 変数mikeに15を設定しようとすれば,15は素数 ではないのでエラーになっています.
ここまでの動作をもう少し詳しく解説しましょう.先ず,define variable函数による宣言で,変数 の型をintegerと宣言しています.define variable函数は, 変数の型をany以外に指定していれば, 宣言する大域変数のassign属性に内部函数のassign-mode-check函数を割当てます.この内部函数
は変数のvalue check属性に設定された函数を用いて変数の評価を実行する函数です.次に,この
value check属性の設定でqput函数を用いています.ここでの例では,大域変数tamaのvalue check
属性にptest函数を割当てていますね.すると,大域変数tama
に値を割当てる時に,assign-mode-check函数が,大域変数tamaのcheck value属性に割当てられた述語函数で割当てようとする値を
評価します.この例では,ptest函数に15が引渡されます.この例では15が素数でない為にfalseと なり,変数に15が割当てられません.
次の例では, 大域変数mikeの型を any とした場合です. この場合,変数 mikeの value check 属性に値を設定しても,先程の様にmike:15を実行した場合にエラーも何も出ません.この場合, 大域変数mikeのassign属性にassign-mode-checkが設定されていない為です.これはLISPで
(get ’$mike ’assign) を実行すれば, NILが返されるので判ります.
そこで, :lisp (put ’$mike ’assign-mode-check ’assign) として見ましょう.これによって,属性 as-signの値としてassign-mode-checkを設定されます.すると,割当の際に検証が実行される様になり ます.
atvalue函数
¶ ³
atvalue(⟨式⟩,⟨点リスト⟩,⟨境界値⟩) at(⟨式⟩,⟨点リスト⟩)
µ ´
atvalue函数による境界値の設定では,函数や式に対して点をリストで指定し,そのリストに対応
する境界値を設定します.
このatvalue函数で値を指定すると,atvalue属性に座標と函数値が対応付けられ,⟨式⟩の prop-ertiesリストにatvalue属性が追加されます.
尚,引数の⟨式⟩には函数f(⟨v1⟩,· · ·,⟨vn⟩)やその微分が指定可能ですが,その場合には変数の 従属性が明確になる様に指定しなければなりません.
⟨リスト⟩は ⟨変数1⟩=⟨式⟩の様に変数と値を演算子=で繋ぎ合せた式のリストになります.
atvalue(f(x),x=xˆ2+x+1,0)とした場合,x=xˆ2+x+1の左辺は函数f(x)で用いた疑似変数であ り,=も方程式で用いる演算子=とは意味が異なっています. その為,xˆ2+x+1で用いている変数x とは関係ありません.この事から,x2+ 1 = 0の解x=±iを函数f に代入しても函数f は零にな らない事に注意して下さい.函数f が零になるのはf(x2+x+ 1)の時です.
(%i1) atvalue(f(x),x=x^2+x+1,0);
(%o1) 0
(%i2) f(x^2+1);
2
(%o2) f(x + 1)
(%i3) f(x^2+x+1);
(%o3) 0
atvalue函数で設定された値をprintprops函数を使って表示する際に,函数の疑似変数を表記す
る為に,記号@1,@2,· · · が用いられます.
(%i35) atvalue(h(x,y,z),[x=1,y=0,z=0],10);
(%o35) 10
(%i36) atvalue(diff(h(x,y,w),w),[x=1,y=0,w=0],0);
(%o36) 0
(%i37) printprops(h,atvalue);
!
d !
--- (h(@1, @2, @3))! = 0
d@3 !
!@1 = 1, @2 = 0, @3 = 0
h(1, 0, 0) = 10
但し,atvalue函数で設定した函数の値はget函数で取出せず,削除もrem函数では出来ません.
(%i1) put(f,C-inf,type);
(%o1) C - inf
(%i2) atvalue(f(x),x=0,0);
(%o2) 0
(%i3) properties(f);
(%o3) [atvalue, [user properties, type]]
(%i4) get(f,type);
(%o4) C - inf
(%i5) rem(f,atvalue);
(%o5) false
(%i6) remove(f,atvalue);
(%o6) done
(%i7) properties(f);
(%o7) [[user properties, type]]
しかし,atvalueで設定した属性値は他のものと同様にprintprops函数で函数名と属性を指定す る事で表示されます.
(%i19) atvalue(f(x),x=0,0);
(%o19) 0
(%i20) atvalue(g(x),x=0,1);
(%o20) 1
(%i21) atvalue(g(x),x=1,2);
(%o21) 2
(%i22) printprops(all,atvalue);
f(0) = 0
g(0) = 1
g(1) = 2
(%o22) done
次のat函数はatvalue函数と対で用います. ⟨式⟩をatvalue函数に対して与えられるものと同 じ方程式のリスト,方程式中に含まれる変数に対し, atvalue函数で指定した値を入れて評価します.
部分式がatvalue函数で指定された値を持たない為に,評価出来ない場合,その部分式に作用する
at函数の名詞型が返されます.又,その部分式は二次元的書式で表示されます.
勾配と従属性の設定
¶ ³
gradef(⟨函数名⟩(⟨変数1⟩,· · ·,⟨変数m⟩),⟨式1⟩,· · ·,⟨式n⟩) gradef(⟨アトム⟩,⟨変数⟩,⟨式⟩)
depends(⟨函数⟩,⟨変数1⟩,· · ·, ⟨函数n⟩,⟨変数n⟩)
µ ´
gradef函数は ⟨函数⟩のn個の引数に対する微分を ddx⟨f⟩
i =⟨式i⟩で定めます. 尚,gradef函数 で勾配を定義すると,大域変数gradefsに函数名が蓄えられます.更に,指定した函数にはgradef属 性が付与されます.
引数が変数の総数m ·n個の勾配nよりも少ない場合,最初の⟨函数⟩のi番目の引数が参照さ れます.xi は函数定義で用いる疑似変数と同類で,函数⟨函数⟩の i番目の変数を指定する為に用 います.
最初の引数を除く全てのgradef函数の引数は⟨式⟩が定義された函数ならばその函数が呼出さ れて結果が用いられます.勾配は函数が第一階微分を除いて正確に判らない場合で,より高階の微 分を得たい時に必要となります.
gradef(⟨アトム⟩,⟨変数⟩,⟨式⟩)で変数 ⟨変数⟩による⟨函数⟩の微分が⟨式⟩となる事を宣 言します.この場合,大域変数gradefsには登録されず,属性もatomgrad属性になります.
この時, depends(⟨f⟩,⟨x⟩)も実行されるので, depends函数によって属性dependencyが付加さ れ, 同時に大域変数dependenciesにも⟨函数⟩が追加されます.
gradef函数はMaximaの既に定義された函数の微分を再定義する事にも使えますが,添字された
函数に対してgradef函数は使えません.
depends函数で,函数の変数に対する従属を宣言します.例えば, depends(f,x) で函数fが変数x に従属する性質を付加します.尚,depends函数による従属性の宣言にて,函数自体を予め定義する 必要はありません.
(%i41) depends(neko,[tama,mike]);
(%o41) [neko(tama, mike)]
(%i42) diff(neko,tama);
dneko
(%o42)
---dtama (%i43) diff(diff(neko,tama),tama);
2 d neko
(%o43)
---2 dtama (%i44) depends([rat1,rat2],[cheese,milk]);
(%o44) [rat1(cheese, milk), rat2(cheese, milk)]
(%i45) depends([rat1,rat2],[cheese,milk],neko,[tama,mike]);
(%o45) [rat1(cheese, milk), rat2(cheese, milk), neko(tama, mike)]
勿論,depends函数を実行していなければ,diff函数を実行した時点で0になります. depends函数 でnekoが変数tamaとmikeに従属する函数と宣言した為に,微分を行っても零になりません.最 初の例では函数nekoが1成分しかない為に,リストの大括弧を外しています.
函数の変数に対する従属性は大域変数dependenciesに登録された函数の情報から調べられます.
gradefとdependsに関連する大域変数
¶ ³
変数名 初期値 概要
gradefs [] 勾配を定義された函数名リスト
dependencies [] 従属性を宣言された函数名リスト
µ ´
gradef函数で勾配を定義すると,大域変数gradefsに函数名が蓄えられます.
大域変数dependenciesには,dependsやgradefで指定された函数名が蓄えられます.
これらの変数は共にデフォルト値が空のリスト[]です.
(%i4) gradef(f(x,y),y,x);
(%o4) f(x, y)
(%i5) gradefs;
(%o5) [f(x, y)]
(%i6) diff(f(x,y),x);
(%o6) y
(%i7) diff(f(x,y),y);
(%o7) x
(%i8) dependencies;
(%o8) []
(%i9) depends(g,x,y,z);
(%o9) [g(x), y(z)]
(%i10) dependencies;
(%o10) [g(x), y(z)]
(%i11) gradefs;
(%o11) [f(x, y)]
(%i12) gradef(h,x,x^2);
(%o12) h
(%i13) dependencies;
(%o13) [g(x), y(z), h(x)]
この例で示す様に,gradefやdepends函数を用いる事で,gradefsやdependenciesに函数名が蓄積 されます.尚,gradefを用いてdependenciesに函数を追加する為には, gradef(⟨アトム⟩ ,⟨変数⟩ ,⟨式⟩)の形式に限定されます.