pelican でブログ作っているので手短にやったことを書く。このポスト自体が pelican のテストなのであまりちゃんと解説書く気ないですスイマセン。
インストール
まず github でリポジトリを作り gh-pages
ブランチを作る。
$ git clone https://github.com/{username}/blog.git
$ cd blog
python 3.x のサポートが微妙なので(Fabric がインストールできない) 2.7 に切り替える。
$ pyenv local 2.7.6
必要なものをインストール。
$ pip install pelican
$ pip install Fabric
$ pip install Markdown
$ pip install ghp-import
pelican-quickstart
して適当に質問に答えると色々ファイルが生成される。
日記を書く
content
以下に Markdown 形式で日記を書く。書式は以下からコピペして書き換える。
Title: My super title
Date: 2010-12-03 10:20
Category: Python
Tags: pelican, publishing
Slug: my-super-post
Author: Alexis Metaireau
Summary: Short version for index and feeds
This is the content of my super blog post.
早速ビルドしてみる。
$ fab build
$ fab reserve
ブラウザから localhost:8000
を開く。
Slug から URL が生成されるらしい。Slug を削ると Title を元に URL を生成するらしいのだが、これが日本語を中国語の翻訳機にかけたような謎の URL になる。
pelican で作るブログ
http://localhost:8000/pelican-dezuo-ruburogu.html
pelican dezuo ruburogu とは一体…
ブログなら URL は {year}/{month}/{date}/{slug}.html
という構成にしたいですね。
上の URL settings を見ればいいのだがちょっと把握しづらい。
とりあえず pelicanconf.py
に以下を追加したらなんとなくいい感じになった。
ARTICLE_URL = 'posts/{date:%Y}/{date:%m}/{date:%d}/{slug}/'
ARTICLE_SAVE_AS = 'posts/{date:%Y}/{date:%m}/{date:%d}/{slug}/index.html'
liquid tag による IPython Notebook の挿入
まず数式が使えないので pelican-plugins
から latex
パッケージを入れておく。これは mathjax
の別名。
$ git clone https://github.com/getpelican/pelican-plugins
conf ファイルに以下を記述する(pelican から実行できれば名前は何でもいいっぽい? pelican-quickstart
から作った場合デフォルトは pelicanconf.py
と publishconf.py
のどちらか)。
PLUGIN_PATH = '/path/to/pelican-plugins'
PLUGINS = ['liquid_tags.notebook', 'latex']
/path/to/
は絶対パスで。~
をなんとなしに使ったらダメだった。そりゃそうか。
数式はこれだけの設定でよい。liquid_tags.notebook
というプラグインで IPython Notebook を記事の好きな場所に挟み込むことができるようになる。
{% notebook filename.ipynb %}
注意点は notebook を置く場所である。デフォルトでは content/
以下に notebooks/
というフォルダを作ってそこに filename.ipynb
を置く必要がある。そういう規約である。NOTEBOOK_DIR
を変えればデフォルトの設定は変更できるが特に不満はないしそのままにしておく。
最後のステップとして _nb_header.html
の設定をする必要がある。_nb_header.html
は liquid_tags.notebook
を使っているとpelican プロジェクトのルートフォルダに自動で生成される。これを挿入すると notebook の表示が奇麗になる。
まず theme
の template
に次のような文を書く。
{% if EXTRA_HEADER %}
{{ EXTRA_HEADER }}
{% endif %}
が、自分は pelipress
テーマを使っておりそこには既に書かれていたので必要なかった。
conf に _nb_header.html
を読みこむ設定を書く。
EXTRA_HEADER = open('_nb_header.html').read().decode('utf-8')
これにて準備は完成!
以前作ったノートを挟んでおく。
IJulia
なのだが構文がカラーリングされておりませんな。
ランダムサーチ
Clever Algorithms: Nature-Inspired Programming Recipes
This work is licensed under a CC BY-NC-SA 2.5 AU
ランダムサーチは確率的アルゴリズムのなかでも一番単純なものである.
数学的には解に収束性があるかなどを考えるらしいので簡単というわけではないらしいが,プログラムとして書くだけならとても簡単である.またランダムサーチは局所探索法や山登り法といったよりよい手法と組み合わせるための基本的な手法である.
実例
$ n = 2 $ における $ f = \sum_{i=1}^{n} x_i^2, -5.0 \leq x_i \leq 5.0 $ の最小値 $ \min f(x) $ を求める.パラボラ放物線の底を求める問題に過ぎないので数値的に解く意義は特にない.
まず位置ベクトルを受け取ったらコストを返す目的関数を定義する.
objective_function(vector) = sum(map(x -> x^2, vector))
続いて探索区間を受け取って(この問題では [-5 5; -5 5]
),ランダムな位置ベクトルを返す関数を定義する.区間 [-5, 5] からランダムに 2 回選ぶだけなので今回は難しくないが,選ばれる点に偏りが出ていないかは常に考慮するべきである.
function random_vector(minmax :: Array{(Float64, Float64)})
[mn + (mx - mn) * rand() for (mn, mx) = minmax] # rand() は区間 [0, 1) の一様乱数を返す (Float64)
end
上2つの補助関数を用いて探索関数を記述すればよい.
探索関数 search
は探索区間の配列と探索の試行回数を受け取り,返り値は最善の結果(コストとベクトルの情報)とする.
function search(search_space :: Array{(Float64, Float64)}, max_iter :: Int)
best = Dict()
for _ in 1:max_iter
candidate = Dict()
candidate[:vector] = random_vector(search_space)
candidate[:cost] = objective_function(candidate[:vector])
best = !isempty(best) && best[:cost] < candidate[:cost] ?
best :
candidate
end
best
end
たんに書籍のRubyコードを移植しているだけなのだが,Julia特有の考察点がいくつか浮かび上がってくる.
まず引数の型を記述している.JuliaはRubyのように型を記述せずとも動くが,可能な限り書いたほうがよい.型はその関数の振る舞いを規定しているからである.型を書かないと,その関数はどんなデータ型に対しても適用される(ジェネリックな関数).これは動作が把握しづらい.
また Julia であれば search
関数をもっと短く書けるのではないだろうか.以下はシンタックスエラーで動かないが,vector
を内包表記で一時的に蓄えたりすることはできないのだろうか(内包表記は内部の値を書き換えてはならなかった気がするので一時変数はだめか…).
function search(search_space, max_iter)
minimum([(objective_function(vector), vector), vector = random_vector(search_space) for _ in 1:max_iter])
end
ところで,関数名 objective_function
や random_vector
もそのまま本から移植しただけであるが,Juliaでは関数名にスネークケース (名前を区切るのにアンダースコア_
を使うこと) は推奨されていない.スネークケースで名前が区切られている場合,往々にして処理単位が 1 つに絞れていないということが起こっているので非推奨とされている.objective_function
や random_vector
はあまりよい関数名ではないかもしれないが,処理単位としてはこれ以上ないくらい小さく絞られていると思うのでこのままでよいだろう.
では最後に,実際に探索を行ってみよう.
search_space = [(-5.0, 5.0) (-5.0, 5.0)]
max_iter = 1000
best = search(search_space, max_iter)
println("Done. Best Solution: c=$(best[:cost]), v=$(best[:vector])")