mathjax

ラベル PEOPLE の投稿を表示しています。 すべての投稿を表示
ラベル PEOPLE の投稿を表示しています。 すべての投稿を表示

2013年9月10日火曜日

PEOPLE_2: 質点のクラス(part 1)

PEOPLE_2: 質点のクラス(part 1)

ソースファイル

前回、質点を「質量を持ち、その存在位置以外に自由度を持たない物体」と定義した。 今回からは、この定義をPythonのクラスとして表現する事を試みる。

「質量を持ち」について。

普通は、ある一定の質量を持ち、という意味である。つまり、これは質点の自由度ではなく、個々の質点に固有の値である。

この事を考慮した質点クラスの定義を行う。それにはプロパティを用いるのが良い。

質点クラスの定義

In [1]:
class PointMass(object):
    def __init__(self,sitsuryo=1.0):
        self.__mass=sitsuryo
    @property
    def mass(self):
        return self.__mass

クラス定義の解説

クラスの定義の仕方は、上記の様に

class クラス名(継承する元のクラス):

とする。この時、既存のクラスの定義を引き継いで再利用する場合には括弧内に引き継ぐ(継承する)元のクラス名を書くのだが、今回は特に無い。 その場合、括弧内にはobjectという最も基本となるクラスを継承する。

また、

@property

はデコレータと呼ばれる文で、これによって、直後の関数定義がこのクラスに属するオブジェクトのプロパティと呼ばれる変数になる。

今回の場合、直後に

def mass()

によってmassという関数が定義されているが、これは実際にはPointMassというクラスのmassというプロパティを定義している事になる。

オブジェクト指向プログラミングを知らない人の為に、 クラスの使用方法と、プロパティの使用例を以下に示す。

質点オブジェクトの生成

In [2]:
pm1=PointMass()
pm2=PointMass(2.0)

解説

pm1=PointMass()

これで、pm1という名前を持ち、PointMassというクラスに属するオブジェクトが作られる。具体的には、PointMassの定義の中にある、

__init__(self,sitsuryo=1.0)

が実行される。その際、sitsuryoという引数には1.0というデフォルトの数値が代入される。

pm2=PointMass(2.0)

こちらの方が一般的な方法で、この場合にはsitsuryo=2.0という数値を用いて、__init__()が実行される。

selfというのは、オブジェクト自身を表す引数で、__init__()の中身を見ると、

self.__mass=sitsuryo

とあるが、これは例えば、pm1というオブジェクトに__massという変数が定義され、そこに先ほどのsitsuryoという引数を代入せよという意味になる。

その後、この__massという値はpm1のプロパティであるmassという変数の呼び出し命令によって呼び出される事になる。

つまり、外部からみると、pm1はmassというプロパティを持っているが、内部では__massという名前の変数として扱っている。

その様子を以下で見てみる。

質量の読み出し(呼び出し)

In [3]:
print pm1.mass
print pm2.mass
1.0
2.0

In [4]:
print pm1.__mass
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-947959c917a9> in <module>()
----> 1 print pm1.__mass

AttributeError: 'PointMass' object has no attribute '__mass'

PointMassというクラスのオブジェクトは__massという変数を持っていない

というエラーメッセージが出るはずである。

* (「__massという変数にはアクセスできない」というメッセージでないのは一見不思議だが、pythonでは他の多くのプログラミング言語とは異なり、オブジェクト変数に対する本当の意味でのアクセス制限は行わない。その代わりに、オブジェクト変数の名前を自動的に複雑化する事でアクセスを難しくしている。 この手法を Name Manglingと呼んでいる。) *

このように、外部からは__massという変数は見えない。

また、sitsuryoという変数も見えない。 こちらは__init__という関数の内部でのみ使われているローカルな変数で、オブジェクトの変数ですらない。

In [5]:
pm1.sitsuryo
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-cf74258e4a57> in <module>()
----> 1 pm1.sitsuryo

AttributeError: 'PointMass' object has no attribute 'sitsuryo'

質量の不変性

質量の変更を試みる。

In [6]:
pm1.mass=3.0
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-9b92080ef8e1> in <module>()
----> 1 pm1.mass=3.0

AttributeError: can't set attribute

変更はできない。これによって、質点の質量は不変ということになる。

次に、質量というプロパティそのものを消してみる。

In [7]:
del pm1.mass
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-8c8d28d11d94> in <module>()
----> 1 del pm1.mass

AttributeError: can't delete attribute

これによって、質量を持たない質点は存在できない。

個々の質点そのものなら消すことができる。

In [8]:
del pm1

まとめ

プロパティというのはオブジェクトが持っている変数の一種だが、そのアクセス方法はクラス定義の内部の関数によって定義されている。 今回の場合、massというプロパティは読み出す(呼び出す)方法だけを定義したので、設定(つまり値を変更)したり、削除したりすることは出来ない。

このような性質は一定の質量を持つ質点の定義方法として適切であろう。

2013年8月26日月曜日

PEOPLE_1: 質点の定義と運動の記述・表現

PEOPLE_1: 質点の定義と運動の記述・表現

ソース

最初に、質点を考える。 質点とは、質量を持ち、その存在位置以外に自由度を持たない物体の事を言う。

存在位置が唯一の自由度という事は、存在位置の時間変化を理解すれば質点が完全に理解できた事になる。

存在位置の時間変化の事を運動と呼ぶ事にする。

質点の運動を表現する一つの方法は適当な3次元座標軸を設定して、質点の位置座標を時間の関数として表示する事だ。

例えば、螺旋運動を考えてみよう。 回転軸をz軸にとり、回転半径を1m、回転周期を10sec、1周あたりの上昇を0.5mと仮定すると、時間を\(t\)(sec)として、各座標(\(x, y, z\))は

\[ \theta =2 \pi t/10.0 \\ x=1.0 \times \cos{\theta} \\ y=1.0 \times \sin{\theta} \\ z=0.5/10.0\times t \]

と書けるので、以下の関数を定義すればよい。

In [1]:
def helix_xyz(time):
    _z=0.5/10.*time
    _theta=np.pi*2.*time/10.
    _x=1.*np.cos(_theta)
    _y=1.*np.sin(_theta)
    return _x,_y,_z

この関数を持ちいて、各座標の時間変化をグラフにしてみよう。

In [2]:
time=np.linspace(0.,50.,num=100)
x,y,z=helix_xyz(time)
plt.plot(time,x,label='x')
plt.plot(time,y,label='y')
plt.plot(time,z,label='z')
plt.xlabel('time(sec)')
plt.ylabel('x, y, z(m)')
plt.legend(loc='best')# loc はlocation つまり、凡例(legend)の位置を表す。
Out[2]:
<matplotlib.legend.Legend at 0x3ca84f0>

運動の軌道を見たい場合もあるだろう。 しかし3次元空間での運動をPCの画面に表示するのは容易な事ではない。

今回はmplot3dという機能を使ってみる。

In [3]:
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(x,y,z)
ax.set_xlabel('x (m)')
ax.set_ylabel('y (m)')
ax.set_zlabel('z (m)')
Out[3]:
<matplotlib.text.Text at 0x3d26210>

3次元空間の表示方法

我々は3次元空間内の運動や、立体的な物体の表示方法として確立された方法を得ている訳ではない。 いまだに学術論文は2次元の紙媒体か、それに準ずるPDF等の媒体を用いており、3次元空間を表示するにはそれを何等かの方法で2次元に射影、投影した物を利用する。 上記のグラフも、

pylab=qt

の設定であれば、マウス操作で見る角度を操作できるのだが、そのような3次元空間の情報を直接表示するのではない、射影、投影の方法で学術論文は成立している。

3次元情報を備えたグラフ表示や、更に時間情報を加えた3Dアニメーションが研究発表の標準的な方法になれば、科学の更なる発展が期待できるのかもしれないが、 現実は、上記のような単純な射影、投影の方法だけでも、かなりの事柄が理解できるという事を示している。 また、多くの場合、より単純な2次元グラフだけで済んでしまう場合も多い。

上記の螺旋運動の場合には、

In [4]:
plt.figure()
plt.plot(x,y)
plt.xlabel('x (m)')
plt.ylabel('y (m)')
ax=plt.gca()
ax.set_aspect(1)
plt.figure()
plt.plot(z,x)
plt.xlabel('z (m)')
plt.ylabel('x (m)')
ax=plt.gca()
ax.set_aspect(1)
plt.figure()
plt.plot(z,y)
plt.xlabel('z (m)')
plt.ylabel('y (m)')
ax=plt.gca()
ax.set_aspect(1)
plt.tight_layout()

このような平面的なグラフを組み合わせる事で定量的な記述と表現を行い、上記の様な3D的な投影図の役割は読者にイメージを喚起するだけに過ぎない場合が多い。

まとめ

今回はMatplotlibを用いた質点の運動の表示方法を示した。 次回以降、運動方程式を導入し、少しずつ物理実体指向の方向性を示していけたらと思う。