Top 8
Outer WildsストーリーMODを色々やってみた
June 18, 2023, 10:04 a.m.表面符号と戯れる【量子コンピューター Advent Calendar 2023 23 日目】
Dec. 23, 2023, 3:28 a.m.位数発見アルゴリズム ~Quantum Zooやっていく【特別編】~
Jan. 27, 2023, 2:50 p.m.ストーリー追加 Mod: The Outsider やっていく日記【Outer Wilds】
Feb. 19, 2023, 6:33 a.m.意識が量子効果で生じることを示す実験結果についてちょっと調べただけのメモ
April 21, 2022, 3:09 p.m.ストーリー追加 MOD: Astral Codec やっていく日記【Outer Wilds】
Feb. 25, 2024, 8:47 a.m.Outer Wilds の量子は計算能力が(ある程度)すごいのではという話
Jan. 15, 2022, 8:35 a.m.MacでAge of Empires 2 DE (AoE2DE)をCrossOverで動かす
May 31, 2021, 11:52 a.m.【環境・ソート編】Rustで色々なアルゴリズムを書きつつPyO3を使ってPythonで動かす
Aug. 13, 2023, 12:08 a.m. edited Aug. 14, 2023, 1:36 a.m.仕事内容が変わりアルゴリズムを本格的に知っておこうという気持ちになったので、Rust で色々書いていく企画。せっかくなので、PyO3(maturin)を使って、Rust で書いたアルゴリズムを Python で使えるようにしていく。
GitHub レポジトリはここ: algorithm_dict
今回実装するのはバブルソート・選択ソート・マージソート・クイックソートの4種類。それぞれ generics をサポートするように作っていく。
アルゴリズムの概要と実装
概要も何も、有名なアルゴリズムなので…。Wikipedia を見れば十分。実装は sort.rs
にある。
ただ、マージソートやクイックソートではデメリットも存在する再帰関数を使わずに、キュー(VecDeque
)を利用して実現している。
PyO3 および maturin
Rust で書いたプログラムを Python で呼び出すのに使うライブラリ・ツールとして PyO3+maturin はスタンダードになりつつある。以前使い方を記事(もう古い)に書いたのだが、もうその使い方も古くなってしまった。このようにバージョンが更新されるたびに色々変化が大きいので、使い方は各自ググるようにしてほしい。
参考
- PyO3 公式ドキュメント
- maturin 公式ドキュメント
- この 1 ページだけでプロジェクトの作成方法から PyPI へのリリース方法までわかるのですごい
PyO3 で generics
まず、普通に generics バージョンのバブルソートを考えると、以下のようになる:
fn bubble_sort<T: Copy + PartialOrd>(vec: &mut [T]) {
for i in 0..vec.len()-1 {
for j in i..vec.len() {
if vec[i] > vec[j] {
let tmp = vec[i];
vec[i] = vec[j];
vec[j] = tmp;
}
}
}
}
これは普通に
fn main() {
let mut li = vec![10, -5, 3];
bubble_sort(&mut li);
println!("{:?}", li);
let mut lf = vec![3.14, 2.718];
bubble_sort(&mut lf);
println!("{:?}", lf);
}
で確認できる。(ちなみに引数で Vec を使わない理由)
一見すると、これを単に pyfunction
としてやればいいだけに見えるが、 PyO3 では generics はサポートされていないのである(参考:想像以上に丁寧な teratail の回答)。
ではどうすれば良いかというと、その teratail での回答に近い、 StackOverflow に載っていたこの手法を用いる。つまり、いったん引数を PyObject
として受け取り、それをキャストして generics 版の本体のバブルソートを呼び出すというものである:
fn _call_each_type_sort(fi: fn(&mut [i64]), ff: fn(&mut [f64]), fu8: fn(&mut [u8]), vec: PyObject) -> PyResult<PyObject> {
Python::with_gil(|py| {
if let Ok(mut vec) = vec.extract::<Vec<i64>>(py) {
fi(&mut vec);
return Ok(vec.to_object(py));
}
else if let Ok(mut vec) = vec.extract::<Vec<f64>>(py) {
ff(&mut vec);
return Ok(vec.to_object(py));
}
else if let Ok(vec) = vec.extract::<String>(py) {
let mut vec = vec.into_bytes();
fu8(&mut vec);
return Ok(String::from_utf8(vec).unwrap().to_object(py));
}
Err(PyTypeError::new_err("Not supported"))
})
}
#[pyfunction]
pub fn bubble_sort(vec: PyObject) -> PyResult<PyObject> {
_call_each_type_sort(_bubble_sort::<i64>, _bubble_sort::<f64>, _bubble_sort::<u8>, vec)
}
fn _bubble_sort<T: Copy + PartialOrd>(vec: &mut [T]) {
for i in 0..vec.len()-1 {
for j in i..vec.len() {
if vec[i] > vec[j] {
let tmp = vec[i];
vec[i] = vec[j];
vec[j] = tmp;
}
}
}
}
また、この際、他のソートでも同じようなことをするので、まとめて _call_each_type_sort
で扱えるようにしている。(引数に generics の関数を渡すことさえできればもっと綺麗になるのに…)
テストおよび展望
テストには pytest を利用している(初めて使ったけど pytest
と打つだけで全部テストしてくれるの便利すぎでは??)。そのテストケースは次のようにしている(全体は test_sort.py
):
def test_sort():
l = [3, 10, -2, 60, 2]
sorted_l = sorted(l)
assert sorted_l == bubble_sort(l)
assert sorted_l == selection_sort(l)
assert sorted_l == merge_sort(l)
assert sorted_l == quick_sort(l)
l = [0.53, -0.83, 0.1234, 24, -56, 12, 1, 1]
sorted_l = sorted(l)
assert sorted_l == bubble_sort(l)
assert sorted_l == selection_sort(l)
assert sorted_l == merge_sort(l)
assert sorted_l == quick_sort(l)
l = 'hgrwoghoqgqpoh204hru'
sorted_l = ''.join(sorted(l))
assert sorted_l == bubble_sort(l)
assert sorted_l == selection_sort(l)
assert sorted_l == merge_sort(l)
assert sorted_l == quick_sort(l)
l = np.array([5, -1, 3, 0, 4, 3])
sorted_l = sorted(l)
assert sorted_l == bubble_sort(l)
assert sorted_l == selection_sort(l)
assert sorted_l == merge_sort(l)
assert sorted_l == quick_sort(l)
このように、整数のリストや浮動小数のリストだけでなく、文字列や numpy まで動くようになっている。素晴らしい!
ソートの次はグラフ系をやろうかなと思っている。
Top 8
Outer WildsストーリーMODを色々やってみた
June 18, 2023, 10:04 a.m.表面符号と戯れる【量子コンピューター Advent Calendar 2023 23 日目】
Dec. 23, 2023, 3:28 a.m.位数発見アルゴリズム ~Quantum Zooやっていく【特別編】~
Jan. 27, 2023, 2:50 p.m.ストーリー追加 Mod: The Outsider やっていく日記【Outer Wilds】
Feb. 19, 2023, 6:33 a.m.意識が量子効果で生じることを示す実験結果についてちょっと調べただけのメモ
April 21, 2022, 3:09 p.m.ストーリー追加 MOD: Astral Codec やっていく日記【Outer Wilds】
Feb. 25, 2024, 8:47 a.m.Outer Wilds の量子は計算能力が(ある程度)すごいのではという話
Jan. 15, 2022, 8:35 a.m.MacでAge of Empires 2 DE (AoE2DE)をCrossOverで動かす
May 31, 2021, 11:52 a.m.Tags
- #Python (26)
- #量子力学 (25)
- #量子情報 (23)
- #Unity (11)
- #Outer Wilds (11)
- #数学 (9)
- #Mac (9)
- #AoE2 (8)
- #Linux (7)
- #Quantum Zoo (6)
- #意識 (5)
- #シミュレーション (5)
- #NumPy (5)
- #Bash (5)
- #相対論 (4)
- #Docker (4)
- #Android (4)
- #Qiskit (4)
- #Rust (3)
- #PyO3 (3)
- #GitHub (3)
- #Django (2)
- #情報理論 (2)
- #LaTeX (2)
- #AR (2)
- #Git (2)
- #iOS (2)
- #C++ (2)
- #正規表現 (2)
- #論文 (2)
- #電磁気学 (1)
- #Google Drive (1)
- #Overleaf (1)
- #Let's Encrypt (1)
- #ポケモン (1)
- #AdMob (1)
- #Autoya (1)
- #docopt (1)
- #SymPy (1)
- #AWS (1)
- #Twitter (1)
- #URP (1)
- #iMovie (1)
- #PyTorch (1)
- #C# (1)
- #Vim (1)