目次
AtCoder2023年言語アップデートでPythonに入るライブラリ
それぞれ、何するやつかくらいのざっくり理解なので、あまり詳細なことは書いてない。
今後、使ってみて追記することがあるかも。
PuLP
線形問題(LP)ソルバー。COIN-ORという非営利の教育財団によって開発され、オープンソースで利用できるライブラリの1つ。
Pythonでも、PyPyでも使えるようになる。
変数 $x_1,x_2,...$ があり、いくつかの変数間の制約条件の下、目的関数の値を最大化(最小化)したい。
またその時の各変数の値を知りたい。という問題を解いてくれる。
- 例: ナップサック問題
- 変数: $x_1,x_2,...,x_N$ 各品物を選ぶか選ばないかの0-1値
- 目的関数: $x_1v_1+x_2v_2+...+x_Nv_N$ の最大化
- 制約: $x_1w_1+x_2w_2+...+x_Nw_N \le W$
こういう条件を与えると、解いてくれる。
時間を計測すると、$N=20000,W=1000$ という $NW \simeq 2 \times 10^7$ の問題でも、手元の環境で0.6秒以下で解ける。
また、(中でどうやってるのかよく分かってないが)$W=10^9,Vの最大値10$ みたいな、一般に $V$ をキーにする方の制約でも、0コンマ何秒で解ける。
$N$ をこれ以上増やすと、さすがに2秒以上かかってくるようになる($N=2 \times 10^5$ で、6秒くらい)。
かなり強力な武器であることは間違いないが、 使いこなすには「線形問題に上手く言い換える能力」と「それが計算量的に間に合うことが示せる能力or感覚」が必要そう。
精度
答えが桁落ち?することがあるみたい。
これは、↓の問題の入力例4だと思われ、
“Objective Value” では正しい値が表示されているのに、それを取り出した途端、末尾2桁が00になってしまっている。
(自環境でも再現)
厳密解が求められる場面ではイマイチ信用ならんなぁ。有効桁数の設定はあるんだろうか。
OR-Tools
Googleが作った、数理最適化ツール。分野はPuLPと似てる。
z3-solver
Microsoftが作った、SMTソルバー。
2-SATなどの「SAT」は、SATisfiability problem、充足可能性問題のこと。真偽値が複数あって、制約を満たす解を解く問題。
一方「SMT」は、Satisfiability Modulo Theories、真偽値だけで無く数値や、もっと複雑な式が変数であっても解ける、らしい。
なんか、シンプルな使い方を見てたら「変数の制約を与えて解かせる」という流れやその用途は 線形問題ソルバと似てそうだが、違いはあるんだろうか。あまり区別できてない。
sortedcontainers
C++でいうstd::setとかstd::multisetとかが使えるようになる。速度も十分っぽい。
- SortedSet
- SortedList
- SortedDict
SortedSetは要素の重複なし。SortedListは重複あり。
主な機能
- addで入れて、discardで消す
bisect_left(x), bisect_right(x)
で、$x$ 以上/より大きい要素位置 $O(\log{N})$irange(l,r)
で、$l$ から $r$ までを昇順にイテレート- SortedSetは、通常のsetよろしくdifference, intersection, union などもできる。(計算量的は不明)
mpmath
任意精度浮動小数点演算ができる。
上記のサイトによると、mpmathは'gmpy'というC実装の多倍長ライブラリがインストールされていれば使い、高速になる。
AtCoderでは、Pythonの方にはgmpy2が入っていてmpmathによって認識もされているが、PyPyの方には入っていない。
ひょっとするとこれを使う場合はPythonの方が高速になる場合もあり得る?
演算誤差に気をつけたり、それを避けるために工夫して解かなければならない問題もたまにあるが、それらを力業で突破してしまえるかも。
more-itertools
標準ライブラリ itertools から発展し、更にいろいろできるようにしたやつ。
リストから $k$ 個ずつひとまとめにイテレートする chunked とか、ちょこっと役立つものが何個かある。
ac-library-python
C++ のAtCoderLibraryの移植版。
これまでも、ローカル環境にインストールして使って、提出時には結合したコードを生成する、という使い方はできたが、
結合が必要なく、直接 import atcoder
できるようになった。
cppyy
PythonとC++ を連携させる。
以前もそういうパッケージはあったが、従来のものと比較していろいろ楽にできるらしい。
Python内にcppコードを書く必要があるが、C++でmultisetやconvolutionを実装して呼ぶと、 sortedcontainerや、ACLのconvolutionより高速に動作した例もある。
bitarray
01で表されるbit配列を、シフトしたり、XORしたりする。
64bit程度までなら整数をbit配列的に扱って問題ないと思うが、それ以上になるとこっちの方が有利だったりするのだろうか。
scikit-learn, torch, lightgbm
機械学習。AHC用途かな。
pandas, polars
どちらも、2次元テーブル的なデータを扱う、データ分析用ライブラリ。
アルゴリズムではあまり使わなさそう…。ヒューリスティックの開発に、人によっては使うことがある?
shapely
幾何的な概念を扱うライブラリ。
頂点の座標を与えてポリゴンの面積計算をするなど、幾何問題で楽になりそうな機能はあるが、計算時間がどの程度になるかは未調査。
numpy
PyPyでも使えるようになった。ただし、以下の点に留意が必要。
- importに400msくらいかかる
- Numpyで計算する箇所の速度は、素Python上のNumpyと比較して速いわけではない。というかむしろちょっと遅い?
- 100×100行列を2つ生成して内積をとる操作を1000回
- Python: 697ms
- PyPy: 872ms
- $10^5$ 要素の1次元配列を2つ生成して、np.rfftで畳み込む操作を50回
- Python: 2454ms
- PyPy: 2656ms
特に、400msのオーバーヘッドはなかなかきつい。
「Numpyは一部利用するが、他にもPython上で実行される重いコードがそれなりにあり、その部分をPythonからPyPyにした時の高速化が400msを上回る」というような場合以外
(Numpy上の演算メインの解法とか)は、従来通りPythonで提出した方がよさそう。