2015年12月3日木曜日

Python リスト内包表記の入れ子など

 2つのリストやタプルなどがあり、それらを組み合わせて新しいリストを作成するときにリスト内包表記を使用することができる。これによりコードを短くできる。

X = range(6)
Y = range(4)

[(x, y) for x in X for y in Y]
[(0, 0),
 (0, 1),
 (0, 2),
 (0, 3),
 (1, 0),
 (1, 1),
 (1, 2),
 (1, 3),
 (2, 0),
 (2, 1),
 (2, 2),
 (2, 3),
 (3, 0),
 (3, 1),
 (3, 2),
 (3, 3),
 (4, 0),
 (4, 1),
 (4, 2),
 (4, 3),
 (5, 0),
 (5, 1),
 (5, 2),
 (5, 3)]

 [[(x, y) for x in X] for y in Y]
[[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0)],
 [(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1)],
 [(0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (5, 2)],
 [(0, 3), (1, 3), (2, 3), (3, 3), (4, 3), (5, 3)]]

{x : y for x in X for y in Y}

{0: 3, 1: 3, 2: 3, 3: 3, 4: 3, 5: 3}

2015年12月2日水曜日

pythonのリスト内包表記、関数型、手続き,numpy

pythonで1から100までの自然数うち、3の倍数のみを10倍して合計を求める。

手続き
res = 0
for n in range(1,101):
    if n%3==0:
        res += n*10

関数型
res = sum(map(lambda n : n * 10, filter( lambda n : n%3==0, range(1,101)))

リスト内包表記
res = sum([n * 10 for n in range(1,101) if n%3==3])

numpy
import numpy as np
N=np.arange(1,101)
res = np.sum(N[N%3==0]*10)

関数型と二項演算子
res = sum(map(lambda n : n * 10 if n%3==0 else 0, range(1,101)))

関数型(ハードコア版)
res = reduce(lambda n1,n2: n1+n2,(map(lambda n : n * 10, filter( lambda n : n%3==0, range(1,101)))))

2015年12月1日火曜日

IPythonのクラスターについて

IPython.Parallel(ipyparallel)で、ハマったので(ハマりまくった)ので、ここに備忘録としてメモしておきます。

手元にあるPCから、リモートにあるPCでipengineを起動して使用したい場合、以下の手順で可能である。

ipython profile create --profile=parallel --parallel

~/.ipython/profile_parallel/ipcluster_config.pyを編集し以下を追記する。
c.IPClusterEngine.engine_launcher_class = "SSH"
c.SSHEngineSetLaucher.engines = {
   "hostname1" : 10,
   "hostname2" : 10,
   "hostname3" : 10,
}

~/.ipython/profile_parallel/ipengine_config.pyを編集し以下を追記する。
c.HubFactory.ip = "*"
もしくは、
c.RegistrationFactory.ip = "*"

これで準備完了で、ssh-agentなどでパスワードなしでリモートにログインできるようにしておいて、以下のコマンドで各ホストのエンジンを起動する。

ipcluster start --profile=parallel

これで、リモートホストにprofileを自動で転送され、エンジンが自動で起動する。

別のシェルで、プロファイルを指定してipythonを起動する。

ipython --profile=prallel

from ipyprallel import Client

c = Clinets()

c[:].ids

を実行し、指定エンジンの数だけ表示されればOKである。

これだけである。

==

しかし、これだけをするのにハマりまくった。

まず、ハマった原因として起動コマンドを実行した時に
engines appear to have started successfully と表示されても、実際にはリモートでEngineが起動していな事があった。この原因としては、リモートにおけるipengineの実行環境が整っていなことが原因だった。これは、リモートに個別にログインしてipengineを実行し、起動できるか確認すればわかる。

また、ipengine_config.pyに、c.RegistrationFactory.ip = "*"を書いておかないと、リモートからエンジンをcontroller?に登録しようとしても出来ないようなので、うまくエンジンが起動出来ないようだ。
 
最近?IPython.Parallelが4.xにバーションアップし、ipyparallelモジュールとして独立?したようだ。ハマっている時には、環境中に4.x系と3.x系が混在していた。これ原因かは分からないが、一度確認してみると良いかもしれない。 confingファイルの説明の記述もかなり変わっている。