2010年11月27日 コメントを残す
大学初年級の数学計算までならば、大多数を配布しているデフォルトの Python sf ワンライナー計算式で書ける。それを具体例で示す。たまたま面白そうな未定係数法に関連する問題が 大学数学のラグランジェ未定数乗数法が分かりません」で質問されていた。これを題材に使って Pythn sf one-liner 数式の実用性を例示する。
以下は私自身の問題を解く過程での思考過程を、誤った小道に入り込んで戻る過程も含めて示す。人間の思考手順とワンライナー計算が互いに影響しあう様子を示せるからだ。同時にこれが Python sf の short tour にもなっている。
# 半径 1 の球および それと接する平面がと原点が作る様子を図示する
dct={}; for idx,(φ,θ) in enmitr(klsp(0,2pi), klsp(0,pi)):dct[idx]=[sin(θ) cos(φ),sin(θ) sin(φ), cos(θ)];tempDct1:= dct
dct={}; vx,vy,vz = sqrt(3) kzrs([3,3])^0; prm=klsp(0,1);for idx,(u,v) in enmitr(prm, prm):dct[idx]=u vx + v vy + (1-u-v) vz;tempDct2:=dct
=:tempDct1, tempDct2; renderFaces(tempDct1, blMeshOnly=True); renderFaces(tempDct2, blMeshOnly=True, meshColor=red);drawAxis(2)
球または三角形の板を表示するだけならば、一つの Python sf on-liner で表示させられる。でも球と三角の二つを一つの one-liner で表示させるのはできるけれど、 one-liner とは言いにくい長さになってくる。なので下の三つの one-liner で一つの図を表示させるようにした。One-liner として扱うのはディスプレーの一行の範囲で表示できる範疇までだと思う。
- 球のデータを作る one-liner
- 三角データを作る one-liner
- 球と三角と x,y,z 軸を表示する one-liner
この oneliner で klsp(0,pi) は下のようなベクトルデータを作っている。ようは [0,pi] の範囲を 50 等分するベクトルだ。0 と pi の両端を含む長さが 51 のベクトルデータなのwで、図示するときに端が欠けることがなくて便利だ。
Python sf expression
klsp(0,pi)
===============================
[ 0. 0.06411414 0.12822827 0.19234241 0.25645654 0.32057068
0.38468481 0.44879895 0.51291309 0.57702722 0.64114136 0.70525549
0.76936963 0.83348377 0.8975979 0.96171204 1.02582617 1.08994031
1.15405444 1.21816858 1.28228272 1.34639685 1.41051099 1.47462512
1.53873926 1.60285339 1.66696753 1.73108167 1.7951958 1.85930994
1.92342407 1.98753821 2.05165235 2.11576648 2.17988062 2.24399475
2.30810889 2.37222302 2.43633716 2.5004513 2.56456543 2.62867957
2.6927937 2.75690784 2.82102197 2.88513611 2.94925025 3.01336438
3.07747852 3.14159265]
---- ClTensor ----
二つの klsp(..) ベクトルを引数とする enmitr(..) 関数は Python sf が用意している下のような複数ループを一つで済ますための generator 関数だ。行列のための整数インデックスも組で返しており、今回のような三次元に分布する二次元データを作るのに便利だ。Python sf では変数にギリシャ文字が使えるので、リスト内包表記が分かっている理数系の Python 使いならば「for idx,(φ,θ) in enmitr(klsp(0,2pi), klsp(0,pi)):dct[idx]=[sin(θ) cos(φ),sin(θ) sin(φ), cos(θ)]」が球面データを生成していることが読み取れるはずだ。数学では、このような単純な多重ループが頻発する。多重の for ループは Python one-liner で書けない。enumitr(..) 関数のような小さな仕掛けを使うことで多重ループでも One-liner が使え、また可読性を保てる。
Python sf expression
sc.source(enmitr)
""" 列挙インデックス付きの多次元繰り返しイタレータ
multiple dimentional iterator with enumerate index
e.g.
s=set(['a','b']);list(enmitr(s,s))
===============================
[((0, 0), ('a', 'a')), ((0, 1), ('a', 'b')), ((1, 0), ('b', 'a')), ((1, 1), ('b', 'b'))]
s=set([1,2]);list(enmitr(s,s,s))
===============================
[((0, 0, 0), (1, 1, 1)), ((0, 0, 1), (1, 1, 2)), ((0, 1, 0), (1, 2, 1)),
((0, 1, 1), (1, 2, 2)), ((1, 0, 0), (2, 1, 1)), ((1, 0, 1), (2, 1, 2)),
((1, 1, 0), (2, 2, 1)), ((1, 1, 1), (2, 2, 2))]
'"""
head, tail = args[0], args[1:]
if 'index' in kwarg.keys():
index = kwarg['index']
else:
index = ()
if type(head) in [int, long, float]:
head = range(int(head))
if tail:
if len(tail) == 1 and hasattr(tail[0],'next'):
# to avoid multiple use of one iterator
tailAt = (tuple(tail[0]), )
else:
tailAt = tail
for idxI, i in enumerate(head):
for idxJ, j in enmitr(index=index, *tailAt):
if len(tail) == 1:
yield index + (idxI,idxJ), (i, j)
else:
yield index+(idxI,)+idxJ, (i,)+j
else:
for idxI, i in enumerate(head):
yield idxI, i
===============================
None
Python sf expression
上の Python sf 式で、 sc.source(..) 関数は、引数に与えた関数やクラスまたはモジュールなどの Python ソース・コード文字列を返す関数だ。Python sf では 90% 以上のソースを公開しており、分からない関数などがあったら、そのソース・コードを sc.source(..) を使うことで用意に覗ける。
なお Python sf ては sc ラベルに numpy モジュールを割り振っている。だから sc.source は numpy モジュールが備える関数を呼び出しているだけだ。この sc を経由することで numpy の全てを Python sf 式に記述できる。numpy の info(..) 関数を下のように使えば、下のようにソースを含まない enmitr の introspection 部分を取り出せる。
Python sf expression
sc.info(enmitr)
In file: D:\my\vc7\mtCm\pysf\basicFnctns.py
def enmitr( *args, **kwarg):
python -u sfPP.py "sc.info(enmitr)"
enmitr(*args, **kwarg)
列挙インデックス付きの多次元繰り返しイタレータ
multiple dimentional iterator with enumerate index
e.g.
s=set(['a','b']);list(enmitr(s,s))
===============================
[((0, 0), ('a', 'a')), ((0, 1), ('a', 'b')), ((1, 0), ('b', 'a')), ((1, 1), ('b', 'b'))]
s=set([1,2]);list(enmitr(s,s,s))
===============================
[((0, 0, 0), (1, 1, 1)), ((0, 0, 1), (1, 1, 2)), ((0, 1, 0), (1, 2, 1)),
((0, 1, 1), (1, 2, 2)), ((1, 0, 0), (2, 1, 1)), ((1, 0, 1), (2, 1, 2)),
((1, 1, 0), (2, 2, 1)), ((1, 1, 1), (2, 2, 2))]
'
===============================
None
sc.source や sc.info 関数が扱える対象は Python の全てだ。 Python sf 数式だけに限らない。Python sf が Python に対して upper-compatible だからだ。下のように wx モジュールの関数の関数のソースを覗くこともできる。
Python sf expression
import wx; sc.source(wx.Slider.SetTickFreq)
In file: D:\lng\Python26\lib\site-packages\wx\_controls.py
def SetTickFreq(*args, **kwargs):
"""SetTickFreq(self, int n, int pos=1)"""
return _controls_.Slider_SetTickFreq(*args, **kwargs)
import wx; help(wx.Slider.SetTickFreq)
SetTickFreq(*args, **kwargs) unbound wx._controls.Slider method
SetTickFreq(self, int n, int pos=1)
===============================
None
下のような動作に自身を持てない Python コードを one-liner で簡単に試すこともできる。print 分を書かなくても、勝手に Python sf 式の最終式の値をコンソールに打ち出すので便利だ。実際に Python sf を使っていると、print debug では追いつかなくなったときに限って Python debugger は余り立ち上げるようになる。
Python sf expression
(1,2,3) == [1,2,3]
===============================
False
(1,2,3) == (1,2,1+2)
===============================
True
これらの使用例で分かるように Python sf の one-liner 式は Python sf 数式だけに限らず、Python コード一般に役立つ。
「tempDct1:= dct」のように Python には存在しない「:=」記号を使っている。これは Python sf one-liner 数式特有の記号であり、dct データでtempDct1 ファイル変数を作ることを意味する。実際にこの Python sf 式により tempDct1.pvl ファイルが作られている。 tempDct1, tmpDct2 ファイル変数は「=:」記号により Python sf 式内で読み戻され、Python オブジェクトとして扱える。すなわち Python sf 式の対象として扱える。「読み出されたファイル変数は「=:tempDct1, tempDct2; renderFaces(tempDct1…);…」のように表面描画関数 renderFaces(..) のデータとして与えられ、球や三角形のメッシュ図形が描かれる。
DOS command
dir tempDct1.pvl
ドライブ D のボリューム ラベルがありません。
ボリューム シリアル番号は 5C35-A5B7 です
D:\my\vc7\mtCm のディレクトリ
2010/11/26 10:17 552,235 tempDct1.pvl
1 個のファイル 552,235 バイト
0 個のディレクトリ 80,429,912,064 バイトの空き領域