2013年6月30日日曜日

累乗高速計算

累乗を計算することがあって、まじめにn回掛け算をしていた。
どうやら素早く計算するアルゴリズムがあるようなのでそれを実装した。

たとえば2^11を計算するときは
2^11 = 2^0 * 2^1 * 2^2 * 2^8
   = 1 * 2 * 4 * 256
と計算すれば4回の掛け算で表すことができる。


def power(b, n):
    if n == 0:
        return 1
    elif n%2:
        return b*power(b, n-1)
    else:
        return power(b*b, n/2)

def ntimes(b,n):
    ret = 1
    for i in xrange(n):
        ret *= b
    return ret

if __name__ == "__main__":
    b = 2    
    n = 50    
    rep = 100000
    #print ntimes(b,n), power(b,n)
    
    from timeit import Timer
    t = Timer("ntimes(%d,%d)" % (b, n), "from __main__ import ntimes") 
    print t.timeit(rep)
    
    t = Timer("power(%d,%d)" % (b, n), "from __main__ import power") 
    print t.timeit(rep)
 
     

2013年6月28日金曜日

PyQtの勉強をしてみる。 その4 matplotlibを表示

今回はQtにmatplotlibを組み込む。
描画がインタラクティブな場合は前にやったようにPyQwtを使う必要があるけど、そうじゃない場合は使い慣れたmatplotlibがやっぱりいい。

参考URLはここ
なんかやりたいことがもう完成しとるけど、導入部分だけをシンプルに構成してみる。

MainWindowの中にBarPlotWidgetというのを使ってそこをmatplotlibの描画領域にする。
とりあえずはMainWindowはBarplotWidgetのみを配置することにする。

FigureCanvasQTAggをWidgetのようにaddWidget()すればレイアウトに追加できるようだ。 この辺は調べるの面倒やけ天下り的にやろう。
import sys

import numpy as np
from PyQt4.QtGui import *
from PyQt4.QtCore import *

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure


class BarPlot():
    def __init__(self, parent=None):
        
        # Create the mpl Figure and FigCanvas objects.
        # 5x4 inches, 100 dots-per-inch
        self.dpi = 100
        self.fig = Figure((5,4), dpi=self.dpi)
        self.canvas = FigureCanvas(self.fig)    #pass a figure to the canvas
        self.canvas.setParent(parent)
        
        self.axes = self.fig.add_subplot(111)
        
        self.data = [1,2,3,1,2,3]


    def on_draw(self):
        """
        redraw the figure
        """
        self.axes.clear()
        self.axes.grid()

        x = range(len(self.data))
        self.axes.bar(left=x, height=self.data, width=0.3, align='center',
                      alpha=0.44, picker=5)

        self.canvas.draw()
    


class AppForm(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.creat_main_window()
        self.barplot.on_draw()

    def creat_main_window(self):
        self.main_frame = QWidget()
        self.barplot = BarPlot(self.main_frame)

        #set layout
        vbox = QVBoxLayout()
        vbox.addWidget(self.barplot.canvas)    #add canvs to the layout

        self.main_frame.setLayout(vbox)

        #set widget
        self.setCentralWidget(self.main_frame)
        
def main(args):
    app = QApplication(args)
    form = AppForm()
    form.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main(sys.argv)

2013年6月27日木曜日

PyQtの勉強をしてみる。その3 HelloWorld完結編

前々回はPyQtの導入をしてつまづいたので、前回はSignal/Slotの仕様を学習した。
今回こそPyQtのHelloWorldを完結させる。

参考ページの書き方は古いQtを使っているのでPyQt4で書き直すとこうなる。
ボタンを押すとウィンドウを閉じる。
import sys
from PyQt4.QtGui import *

class HelloButton(QPushButton):
   
    
    def __init__(self, *args):
        QPushButton.__init__(self, *args)
        self.setText("hello world")
        

class HelloWindow(QMainWindow):
    def __init__(self, *args):
        QMainWindow.__init__(self, *args)
        self.button = HelloButton(self)
        self.setCentralWidget(self.button)
        
        self.button.clicked.connect(self.close)    
        
def main(args):
    app = QApplication(args)
    win = HelloWindow()
    win.show()
    sys.exit(app.exec_())
        
        
if __name__ == "__main__":
    main(sys.argv)

前回勉強したpyqtSignalは使っていない。
QPushButtonはボタンを押されたらシグナルを出すような仕様になっているらしい(参考






2013年6月26日水曜日

PyQtの勉強をしてみる。その2 Signal/Slot の使い方

PyQtを始めてSignal/Slotの使い方がいまいち分かっていなかったのでここにまとめておく。
まとめると言ってもリファレンスガイドを参考に頭の整理をするだけなので
原文が良い人はそっちをみたほうが良いかも。
今回説明するのはPyQt4 v4.5で導入されたものだ。 


現状の理解では、シグナル/スロットのはたらきは、

  • オブジェクトをシグナルとスロットを連結させておけば、あるオブジェクトがシグナルを出したときにスロットがそれを感知して動作をする
という感じである。ここにもそんな感じで書いてある。


シグナルを定義するにはPyQt4.Qtcore.pyqtSignal(types[, name])を使う。

シグナルには3つの関数が準備されていて、それぞれ
  • connect:     スロットと繋げる。
  • disconnect: スロットとの繋がりを切る。
  • emit:          シグナルを発信する。


まず基本として、
引数を伴わないシグナルの例は(例そのまま)
from PyQt4.QtCore import QObject, pyqtSignal
class Hoge(QObject):
    def __init__(self): 
        QObject.__init__(self)
    
    #trigger と名付けたシグナルを定義する。    
    trigger = pyqtSignal()
    
    def connect_and_emit_trigger(self):
        #triggerをスロットと繋げる
        self.trigger.connect(self.handle_trigger)
        #スロットにシグナルを送信する。
        self.trigger.emit()
    
    def handle_trigger(self):
        #スロット
        print "trigger signal received"
        
if __name__ == "__main__":
    hoge = Hoge()
    hoge.connect_and_emit_trigger()


これをちょっとアレンジして、
引数を伴うシグナルの場合は
from PyQt4.QtCore import QObject, pyqtSignal
class Hoge(QObject):
    def __init__(self): 
        QObject.__init__(self)
    
    #trigger と名付けたシグナルを定義する。    
    trigger = pyqtSignal(int)
    
    def connect_and_emit_trigger(self):
        #triggerをスロットと繋げる
        self.trigger.connect(self.handle_trigger)
        #スロットにシグナルを送信する。
        self.trigger.emit(15)
    
    def handle_trigger(self, index):
        #スロット
        print "passed integer:", index
        
if __name__ == "__main__":
    hoge = Hoge()
    hoge.connect_and_emit_trigger()
    

また、スロットはどんな関数でもconnectできるけど、デコレータ@pyqtSlotでも指定できる。
よくわからんけど、明確にC++のQtスロットとして扱いたいときに使うらしい。
実行速度はデコレータを使ったほうが速くなる。
connectのやり方とかはさっきと一緒。
from PyQt4.QtCore import QObject, pyqtSignal, pyqtSlot

class Hoge(QObject):
    def __init__(self): 
        QObject.__init__(self)
    
    #trigger と名付けたシグナルを定義する。    
    trigger = pyqtSignal(int)
    
    def connect_and_emit_trigger(self):
        #triggerをスロットと繋げる
        self.trigger.connect(self.handle_trigger)
        #スロットにシグナルを送信する。
        self.trigger.emit(15)
    
    @pyqtSlot(int)    
    def handle_trigger(self, index):
        #スロット
        print "passed integer:", index
        
if __name__ == "__main__":
    hoge = Hoge()
    hoge.connect_and_emit_trigger()




PyQtの勉強をしてみる。その1


良さげなサイトが見つかったのでPyQtの勉強をしてみる。(結構PyQtの仕様が変わっているようだ)
http://www.commandprompt.com/community/pyqt/x1067.htm

7章にはSignal Slotの説明があるのでそこまでやってみることにした。
がしかし、記事が古くてQtのバージョンが違う。そのため所々変更が必要になるようだ。
でも概念が大きく変わった訳ではないだろうし、ちょっと勉強ついでに修正しながらやってみる。

まず、qtにおけるhello worldが書いてある。

変更点は2つ

  • QApplicationはPyQt4.QtGuiにある。
  • setMainWidgetはQMainWindowのwin.setCentralWidget()を使うことにした。
ここを参考にした。

import sys
from PyQt4.QtGui import *

app = QApplication(sys.argv)
button = QPushButton("hello world", None)
win = QMainWindow()
win.setCentralWidget(button)
win.show()
sys.exit(app.exec_())


でもこれはホンマのホンマに初歩らしくて、次のページにもっとそれっぽいhello worldが書かれてある。
シグナルとスロットを使ってインタラクティブなやりとりを実現しているらしいが、
どうもシグナルとスロットの書き方が変わっているようなので、その例は実装できなかった。

次回はsignal/slotの書き方を勉強しよう。




2013年6月25日火曜日

2013年6月24日月曜日

Pythonで正規表現の勉強をしてみる。 その2

今日はzero-width-assertionについて例を交えながらやっていく。

\d
任意の十進数とマッチ。[0-9]と同じ。
print re.search(r"\d\d", "this isn't 999.").group()
ちなみに\Dにすると否定になる([^0-9]と同じ)

\s
任意の空白文字とマッチする。[\t\n\r\f\v]と同じ。
ちなみに\Sにするとその逆になる。

\w
英数字と下線[a-zA-Z0-9_]と同じ。 ちなみに\Wはその否定となる。
print re.search(r"\w*", "this isn't 999.").group()



 |
orと同じ。
print re.match(r"[a|b]cd", "bcd").span()

^
行の先頭にマッチするという条件を付加する。

print re.search(r"^happy", "happy as hell")
はマッチするが、
print re.search(r"^happy", "are you happy?")
はマッチしない。

$
行の末尾を意味する。
print re.search(r"pen.$", "this is a pen.")


\b
単語の境界を意味する。つまり空白か非英数文字
print re.search(r"\bis\b", "this is a pen.")
はいいけど
print re.search(r"\bis\b", "this isn't a pen.")
はマッチしない。

グルーピング
()でくくることでグルーピングできる。.group()メソッドでそれを取り出せる。
print re.search(r"(a([b|c])d)", "acd.").group(0)
print re.search(r"(a([b|c])d)", "acd.").group(1)
print re.search(r"(a([b|c])d)", "acd.").group(2)


LookAhead Assertions(先読みアサーション)

よく分からん名前がついとるけど、これはif文みたいなもの。
例えばファイル名を名前部分と拡張子とに分けた形でマッチしたいとき
print re.match(r".*[.].*$", "base.txt").group()
とすればよい。「.」(dot)はなんでもよいという意味。

「.bat」の拡張子の拡張子を除外したいときは
print re.match(r".*[.](?!bat$).*$", "base.txt").group()
と(?!bat$)を加える。

この(?~)がifみたいなもので?以下の条件ならマッチングを続けるということらしい。
今回はその否定で「!」が挿入されている。
が肯定の場合は(?=~)。

条件を追加してexeも除外したいときは、
print re.match(r".*[.](?!bat|exe$).*$", "base.txt").group()
とする。






2013年6月23日日曜日

Pythonで正規表現の勉強をしてみる。 その1

Pythonで正規表現の勉強をしてみる。
会社なんかでもたまに決まったパターンの文字列から数値を取り出してきたりしたいのでちょっと勉強する。
とにかくどこを読んでもパッとしないのでここに手っ取り早く拾得できて復習にもなるようにまとめとこ。

公式ドキュメントのチュートリアルっぽいものを読みながら、

日本語訳もあるようだ。


Introduction
  • 実用上あまり重要でなさそう。
  • reではPerl-styleの正規表現を採用している。
  • 正規表現は一種の言語でありreモジュールを通してそれを使う。
  • マッチングエンジンはCで書かれている。
  • 複雑になりすぎるときは処理が遅くなるかもしれんけど、Pythonで書いたほうがわかりやすいよお。
みたいなことが描いてあった。
正規表現の実力がどんなものか全然わからんので、Pythonでゴリゴリ書くのは保留。

このあと、どうも文章が長くて、面倒なので動くサンプルコードを書く。

import re

p = re.compile(r"[a-z]+")
m = p.match("this1234was")
if m:
    print "matched"
else:
    print "nothing matched"


pに正規表現オブジェクトを作成。コンパイルするときにパターンを教える。
ちなみに、文字列のまえにはr (raw string)をつけておくと\の問題を回避できる。

パターンについては検索するといろいろ出てくるが、今回は[a-z]+(aからzの文字列が1回以上出現)というパターン。

mにはpの動作結果が入る。ここではmatch()を行った。match()の他にsearch(), findall(), finditer()があるようだ。
match()は文字列の先頭から正規表現とマッチするか判定するようなので今回は"this"に相当する部分が検出され、MatchObjectとして返される。検出されない場合はNoneが帰ってくる。
検出された部分を取り出すにはメソッドを使って

print m.group()
print m.start()
print m.end()
print m.span()

finditer()はすべてのマッチした部分をMatchObjectシーケンスのイタレータとして返してくれるので一番使えそうだ。

なお、reのモジュールレベルの関数として
print re.search(r"[a-z]+", "1234abc1234def").span()

と呼び出してもいいようだ。










2013年6月8日土曜日

pycudaをWindowsにインストール

光線追跡を高速化するためにPyCudaを導入することにした。
Cythonとかも考えて見たけど、Cっぽく書くならCUDAでもいいかと思った。


GPUの構造とかはAmazonで買った本を読んで何となく理解。

Python(x,y)を使っているのでライブラリのインストールはあまりやったことがなかった。
(それがPython(x,y)を使う理由の一つでもある)

バイナリっぽいのも落ちとったけど、どうもうまく行かず。
たぶん原因はPython(x,y)で使っているPython2.7が32-bitだということ。
なのでPyCudaも32-bitでインストールしければ。


最終的に参考になったページはここ。
https://github.com/Theano/Theano/wiki/WindowsInstallation


gccはPython(x,y)をインストールしたときに一緒に入ってる。
CUDAのバージョンは最新の5.0をインストールした。
gitはどうやら次のTheanoのインストールに使うらしく、今回はインストールしたけど意味なかったみたい。


手順通りやるとnumeric_cast_traits_common.hppとかがないと言われたのでネットを探して探している場所に置いた。

cl.exeのパスが通ってないと言われたので通した。
(会社のパソコンはVisualStudio Express10で、家はVisual Studio2008やけど、両方うまく行ったのでバージョンはあまり関係ないのか?)

サンプルコードを実行すると、Unicodeで保存したほうがええよ、的なメッセージが大量にでる。
Unicodeで保存すれば出んくなるけど、他のファイルを参照しだすとまた出てくる。全部保存し直すのは面倒で、しかもかなり見難くなる。ま、そのうちなおそう。

テストをするとGPUを使ったほうが早くなってるみたいやし、とりあえずインストール成功!


ちなみにテストは
http://wiki.tiker.net/PyCuda/Examples/SimpleSpeedTest
を使って結果は以下のようになった。
実行環境は
Windows7 Ultimate 64bit
Corei5  2.67GHz
GeForce GT 240
Python 2.7.2 32bit
Cuda5.0

Using nbr_values == 8192
Calculating 100000 iterations
SourceModule time and first three results:
0.207754s, [ 0.005477  0.005477  0.005477]
Elementwise time and first three results:
0.209894s, [ 0.005477  0.005477  0.005477]
Elementwise Python looping time and first three results:
5.444648s, [ 0.005477  0.005477  0.005477]
GPUArray time and first three results:
19.914516s, [ 0.005477  0.005477  0.005477]
CPU time and first three results:
64.993598s, [ 0.005477  0.005477  0.005477]


SourceModuleとElementwiseがあんまり変わらん結果になった。
Elementwiseがなんか分からんのでもうすこしこの辺勉強します。