Don't think, feel! (別館)
"Don't think, feel! It is like a finger pointing away to the moon. Don't concentrate on the finger or you will miss all that heavenly glory." – Bruce Lee
2011/08/02
2011/06/28
basic individual based models / clojure
https://gist.github.com/35bd78f7bb197e39164f (scripts of clojure with comments in English)

今回のソースはブログに載せるのは長すぎる(2つのファイルで350行くらい。拡張性を考えて関数を結構細かく分けています。)ので、ソースは載せないです。上記を参考にしてください。いずれは解説を加える予定ですが、こちらじゃなくて、ホームページに載せると思います。(ブログでソースを取り扱うのは何かと面倒なので。)
上記プログラムの実行例です。連続時間モデル(イベントベースシミュレーション)も離散時間モデルも同じような図ですが、各シミュレーションは50回試行したものをそれぞれIncanter chartsを利用してグラフ化しています。1000個体のものを50回試行させてグラフ化した時の時間が2分30秒ほどかかってます。これは未最適状態です。

離散:初期個体数 10でt=100まで

Labels:
clojure,
incanter,
individual based model
メアドの暗号化について / javascript
もともと持っていたホームページを改変することを考えててどうしようかって検討してたんだけど、jekyllを利用することを考えてます。jekyllの場合、わざわざブラウザのエディタを使わなくてよいので、emacs/vimで作れるので大変楽です。作成したものをそのまま、ホームページのホスティングに転送するようにしておけばいいですからね。個人のページなんで動的なことが必要なのはあまりないものでこれで十分かと思ったくらいです。
そこですこしjavascriptをいじってみた。メールアドレス用のスクリプトを作ってました。もっとも、僕の場合、普段からメアドを野ざらしにしているからいまさら暗号化する必要はないんですがね。その暗号を解読する関数ですね。作りは簡単なんですが。nこの長さmの文字列を用意してみます。以下は3つの文字列で5の長さを持ってるものです:
abcde
fghij
klmno
ここから先頭から縦に取ってきて順番並べると "afkbglchmdinejo"が作れますね。これを キャラクターコードの配列に置き換えます。(97, 102, 107, 98, 103, 108, 99, 104, 109, 100, 105, 110, 101, 106, 111)これをdecipherに読み込ませると終了です。
これを実際に使うと次のようになります。node.jsで試してます。
ちょっとしたことを組み込んでました。野ざらしにしてる僕のメアドですが、gmailのスパムを見てるとさほど多くないから、意外と取られてないんだなとは思いますよ。これをどう使ったかというのはここで書かないけど。
そこですこしjavascriptをいじってみた。メールアドレス用のスクリプトを作ってました。もっとも、僕の場合、普段からメアドを野ざらしにしているからいまさら暗号化する必要はないんですがね。その暗号を解読する関数ですね。作りは簡単なんですが。nこの長さmの文字列を用意してみます。以下は3つの文字列で5の長さを持ってるものです:
abcde
fghij
klmno
ここから先頭から縦に取ってきて順番並べると "afkbglchmdinejo"が作れますね。これを キャラクターコードの配列に置き換えます。(97, 102, 107, 98, 103, 108, 99, 104, 109, 100, 105, 110, 101, 106, 111)これをdecipherに読み込ませると終了です。
function decipher(c,n)
{
var s0 = String.fromCharCode.apply(String, c);
var s1=new Array(n);
for(i=0 ; i < n ; i++){
s1[i]="";
}
for(i=0 ; i < s0.length/n ; i++){
for(j=0 ; j < n ; j++){
s1[j]=s1[j] + s0.charAt(n*i+j);
}
}
return(s1);
};
これを実際に使うと次のようになります。node.jsで試してます。
> var arr = new Array(97, 102, 107, 98, 103, 108, 99, 104, 109, 100, 105, 110, 101, 106, 111);
> var result = decipher(arr,3);
> result[0];
'abcde'
> result[1];
'fghij'
> result[2];
'klmno'
ちょっとしたことを組み込んでました。野ざらしにしてる僕のメアドですが、gmailのスパムを見てるとさほど多くないから、意外と取られてないんだなとは思いますよ。これをどう使ったかというのはここで書かないけど。
Labels:
javascript
2011/06/20
階乗計算の比較(apply, reduce, cps, recur and iterate) / clojure
上記のグラフはIncanter/chartsの練習で作ったものなんです。同じ作るならば、ちょっとは参考になるものをと考えて見るのが良いだろうと思って、階乗計算のパフォーマンスをグラフ化してみた。赤色は継続渡し、青色は再帰、緑はiterate, 黄色とラベンダー色(重なってる)はapply,reduceを利用して、それぞれ要素が1000,2000,3000,4000,5000の時の階乗計算を10回行いその平均をグラフ化したものです。その結果は、apply,reduceのパフォーマンスは圧倒的に悪いですね。特に型宣言を行うといったチューニングはしていないですが、この位の差が出てくるようです。視覚化するとよくわかりますね。継続渡し再帰を利用したものが一番パフォーマンスが良かったです。継続渡しっていいんですね。要素数が少ない時はさほど気にはならないけど、大規模なことをするときは注意する必要があるってことを示してるのでしょう。;;; time+ origins from 'time' of clojure.core under EPL by Rich Hickey.
(defmacro time+
"Evaluates expr and prints the time it took. Returns the value of
expr."
{:added "1.0"}
[expr]
`(let [start# (. System (nanoTime))
ret# ~expr]
(/ (double (- (. System (nanoTime)) start#)) 1000000.0)))
(defmacro time-repeat [t expr]
`(take ~t (repeatedly (fn[] (time+ ~expr)))))
(defn fact-cps [n cont]
(if (zero? n)
(cont 1)
(recur (dec n) (fn[x] (cont (* n x))))))
(defn fact-recur [n result]
(if (zero? n)
result
(recur (dec n) (* n result))))
(performance/time-repeat
10 (last (map #(second %)
(take 5000 ; 5000までの階乗計算
(iterate (fn[[x y]][(inc x) (* x y)])
[2 1])))))
(reduce * 1 (range 2 5001))
(apply * (range 1 5001))
2011/06/10
macroでmacroを作る。 /clojure
Clojureでマクロをつくろうとする場合、common lispより制約が強いので作り方も若干変える必要があります。そこで一番大きいのは、マクロで悪名高かったバッククオート`を重ねられない点です。その点をよく考えて、障害を乗り越えなければいけません。制約があるために、バッククオート以前に処理をするのが勝負どころと言えるでしょうね。swingなどでproxyを設定することがあるけど、あれは糖衣するのに良い材料だと思ってます。残念ながら僕はJavaのライブラリを使うコツをまだつかんでないので、これは試作段階のものです。だからまだ、githubにはアップロードしないです。Practical clojureの共著者のSierraさんのブログをみてみる[1]と、この手のマクロはon-actionマクロのようにadd〜のところからマクロにするほうがいいのだろうな。と今は思ってます。以下のdefproxyってのはマクロ名とinterface名とが同じになるようにしているけど、それが適切かどうかまだ判断つかないですね。^^;
だからマクロでマクロをつくろうと思えば、作れないことはない。しかし、common lispのマクロとは違った工夫が必要だよ。ってことですね。もう少しわかりやすく作れないのか?まだ考えています。でも、ここまで出来れば、マクロで関数とマクロを同時に設定するという芸当も可能だってことはわかります。その時は、
(defmacro defproxy [name]
(let [body# 'body
name# name
amp# '&]
`(defmacro ~name# [~amp# ~body#]
(conj ~body# [] ['~name#] 'proxy))))
だからマクロでマクロをつくろうと思えば、作れないことはない。しかし、common lispのマクロとは違った工夫が必要だよ。ってことですね。もう少しわかりやすく作れないのか?まだ考えています。でも、ここまで出来れば、マクロで関数とマクロを同時に設定するという芸当も可能だってことはわかります。その時は、
(defmacro foo [bar ...]
(let [...]
`(do
(defmacro ....)
(defn ....)))
というような作成方法になります。さて、どこで使うかやね。笑
Labels:
clojure
2011/06/03
dopoll マクロ / clojure
dopollマクロですが、ちょいと分かりにくいので解説です。サンプルと出力結果はPriorityBlokingQueueの利用例ですが、Javaのライブラリで供給されているデーター構造とそれの操作する関数群があるんですが、その操作を繰り返し行うときに利用するように作ったマクロです。だから恐らく.pollと.sizeをメソッドに持ってるjavaのクラスならば活用できるでしょう。
ご存知のように?この手の繰り返し操作をしようとすると、loopマクロを利用することになりますが、loopマクロは取り扱いがシンプルではないので、何かとエンバグしやすい印象があるんですね。loopで同じ事をさせようと思ったらwhen-not以下を普通に記述すればいいのですが、案外失敗して、無限ループに突入してしまうこともあるんですね。そのために常にqueueのサイズが0になってるかどうかチェックしています。これを常に知っておかないと、loopを使って記述しても悩んでしまうバグとして関数内に放置してしまう可能性がありますが、予めマクロを作っておくとその可能性はなくなります。使い方は極めてシンプルしていてdotimesやdoseqを知っていれば直感的に使えるようになっています。ただし、終了条件だけはいつも最後まで繰り返さないときのために第三項目として取り上げています。このマクロでは、マクロと解釈する前に、ベクターの3つめの項目があるかどうか調べて、なければ最後までループさせるようにして、あれば、それを終了条件になるようにしています。それはサンプルを見てください。
マクロとしては複雑に見えるけど、macroexpand-1をして分かりやすく加工すると次のように解釈してくれることがわかります。
ソース:&と不等号の箇所はブログの仕様上自動的に;が挿入されるので試すときは;を取ってくださいね。
久しぶりにいっヶ月ばかりclojureと格闘したけど、プログラミンの感覚を少し取り戻したような気がします。:-)
ご存知のように?この手の繰り返し操作をしようとすると、loopマクロを利用することになりますが、loopマクロは取り扱いがシンプルではないので、何かとエンバグしやすい印象があるんですね。loopで同じ事をさせようと思ったらwhen-not以下を普通に記述すればいいのですが、案外失敗して、無限ループに突入してしまうこともあるんですね。そのために常にqueueのサイズが0になってるかどうかチェックしています。これを常に知っておかないと、loopを使って記述しても悩んでしまうバグとして関数内に放置してしまう可能性がありますが、予めマクロを作っておくとその可能性はなくなります。使い方は極めてシンプルしていてdotimesやdoseqを知っていれば直感的に使えるようになっています。ただし、終了条件だけはいつも最後まで繰り返さないときのために第三項目として取り上げています。このマクロでは、マクロと解釈する前に、ベクターの3つめの項目があるかどうか調べて、なければ最後までループさせるようにして、あれば、それを終了条件になるようにしています。それはサンプルを見てください。
マクロとしては複雑に見えるけど、macroexpand-1をして分かりやすく加工すると次のように解釈してくれることがわかります。
user> (macroexpand-1 '(dopoll [i a]
(println i)))
(when-not (zero? (.size a))
(loop [i (.poll a)]
(println i) (if-not (zero? (.size a))
(recur (.poll a)))))
user> (macroexpand-1 '(dopoll [i a (> (.peek a) 10)]
(println i)))
(when-not (or (zero? (.size a)) (> (.peek a) 10))
(loop [i (.poll a)]
(println i)
(if-not (or (zero? (.size a)) (> (.peek a) 10))
(recur (.poll a)))))
ソース:&と不等号の箇所はブログの仕様上自動的に;が挿入されるので試すときは;を取ってくださいね。
(defmacro dopoll [bindings & body]
"A macro for loop manipulations of java collection queues"
(let [var# (bindings 0)
pq# (bindings 1)
term# (if (= (count bindings) 2)
`(zero? (.size ~pq#))
`(or (zero? (.size ~pq#)) ~(bindings 2)))]
`(when-not ~term#
(loop [~var# (.poll ~pq#)]
~@body
(if-not ~term#
(recur (.poll ~pq#)))))))
(comment =example=
(import [java.util.concurrent PriorityBlockingQueue])
(defn print-pq []
(let [pq (new PriorityBlockingQueue)]
(dotimes [_ 10]
(.add pq (rand 1000)))
(dopoll [i pq (> (.peek pq) 500)]
(println i))
(println "elements more than 500:")
(dopoll [i pq]
(println i))))
;; user> (print-pq)
;; 163.45692827827574
;; 335.192525607674
;; 440.69978223389404
;; elements more than 500:
;; 528.0780372058205
;; 608.7673080309557
;; 724.6340821453795
;; 731.3274923835517
;; 821.201362348645
;; 899.2657774538147
;; 968.5099196992995
;; nil
;; user>
)
久しぶりにいっヶ月ばかりclojureと格闘したけど、プログラミンの感覚を少し取り戻したような気がします。:-)
Labels:
clojure
incanter-processing を試す その4 + dopull macro / clojure
これもincanter/processingのデモですけど、今度は動画に落としてみました。ubuntu上でconvertコマンドを利用して変換させています。
ここでは、Java標準に付いてるPriorityBlokingQueueを利用して、オブジェクトの優先順位をフレームごとに変えて描写させています。(ubuntu上のffmpegで再変換して動画を作り直しました。)そこで活躍してるのはdopollマクロなんですが、この説明はまたの機会にて。これはincanter/processingとPriorityBlokingQueueの練習とdopollの実戦投入テストですね。
https://gist.github.com/1006213
ここでは、Java標準に付いてるPriorityBlokingQueueを利用して、オブジェクトの優先順位をフレームごとに変えて描写させています。(ubuntu上のffmpegで再変換して動画を作り直しました。)そこで活躍してるのはdopollマクロなんですが、この説明はまたの機会にて。これはincanter/processingとPriorityBlokingQueueの練習とdopollの実戦投入テストですね。
https://gist.github.com/1006213
;;; -*- Mode: Clojure; Coding: utf-8 -*-
;;;
;;; rotate2.clj - an incanter/processing example of 'rotate'
;;;
;;; Copyright (C) 2011 by Yasuto TAKENAKA y.takenaka@gmail.com
;;;
;;; Time-stamp: <2011-06-03 20:17:30 yasuto>
;;; License : http://en.wikipedia.org/wiki/MIT_License
;;;
(ns processing-samples.rotate2
(:use (incanter core processing))
(:import [java.util.concurrent PriorityBlockingQueue]))
(defstruct obj :tr :color :time)
(defmacro dopoll [bindings & body]
"A macro for loop manipulations of java collection queues"
(let [var# (bindings 0)
pq# (bindings 1)
term# (if (= (count bindings) 2)
`(zero? (.size ~pq#))
`(or (zero? (.size ~pq#)) ~(bindings 2)))]
`(when-not ~term#
(loop [~var# (.poll ~pq#)]
~@body
(if-not ~term#
(recur (.poll ~pq#)))))))
(defn rloc []
(let [dif 180]
(- (int (rand (* 2 dif))) dif)))
(defn rcol []
(let [lim 256]
(int (rand lim))))
(defn init-objs [n]
(for [x (range n)]
(struct obj [(rloc)(rloc)] [(rcol)(rcol)(rcol)]
(ref (rand 1)))))
(defn obj-comp [obj1 obj2]
(if (< @(:time obj1) @(:time obj2)) true false))
(defn four-circle [sktch [tr-x tr-y] [r g b] rad]
(doto sktch
push-matrix
(fill r g b)
(translate tr-x tr-y)
(rotate (radians rad))
(ellipse -15 -15 30 30)
(ellipse 15 -15 30 30)
(ellipse 15 15 30 30)
(ellipse -15 15 30 30)
pop-matrix))
(defn fname [cunt]
(cond
(> 10 cunt) (str "000" cunt)
(> 100 cunt) (str "00" cunt)
(> 1000 cunt) (str "0" cunt)
:else (str cunt)))
(defn rotate-example2 []
(let [objs (init-objs 30)
pq (new PriorityBlockingQueue 10 obj-comp)
rad (ref 0)
cunt (ref 0)
sktch (sketch
(setup []
(doto this
(size 400 400)
(background 255)
smooth
no-stroke
))
(draw []
(doseq [el objs]
(.add pq el))
(doto this
(background 255)
(translate (/ (width this) 2) (/ (height this) 2))
(rotate (radians @rad)))
(dopoll [ite pq]
(four-circle this (:tr ite)
(:color ite) @rad)
(dosync (ref-set (:time ite) (rand 1))))
;; (save this (str "sample" (fname @cunt) ".png"))
(dosync (alter rad inc)
(alter cunt inc))))]
(view sktch :size [400 400] :title "rotate example")))
Labels:
clojure,
incanter,
processing
登録:
投稿 (Atom)



