Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Creating the Fibonacci Sequence: Writing, Testing, and Benchmarking Algorithms

onouyek
December 10, 2021

Creating the Fibonacci Sequence: Writing, Testing, and Benchmarking Algorithms

onouyek

December 10, 2021
Tweet

More Decks by onouyek

Other Decks in Programming

Transcript

  1. 【第4回】ゼロから始めるゲノム解析
    (Python編)
    Creating the Fibonacci Sequence: Writing, Testing, and Benchmarking Algorithms
    @onouyek

    View full-size slide

  2. 本勉強会の概要・目的
    書籍名
    対象者/目的
    Mastering Python for Bioinformatics
    Python・バイオインフォ知識ほぼゼロの人
    を対象に、正しいPythonのコーディング手
    法について学ぶ
    頻度 毎週〜隔週開催予定
    登壇者 募集中!

    View full-size slide

  3. Rosalindとは
    ● 問題解決を通じてバイオインフォマティク
    ス、プログラミング、およびアルゴリズムを
    学習するためのプラットフォーム
    ● 大学やハッカソン、就職の面接にも
    600回
    以上の採用実績あり
    参考:https://qiita.com/_kimoton/items/d534d0fa9b83dd7dc412
    概要

    View full-size slide

  4. 環境構築 - 必要パッケージ群のインストール
    # 公開されているレポジトリからファイル群を取得
    $ git clone https://github.com/kyclark/biofx_python
    $ cd biofx_python
    # requirements.txt に記載のパッケージをインストール
    $ pip3 install -r requirements.txt
    # pylintの設定ファイルをホームディレクトリに移動
    $ cp pylintrc ~/.pylintrc
    # mypyの設定ファイルをホームディレクトリに移動
    $ cp mypy.ini ~/.mypy.ini

    View full-size slide

  5. 本日のお題 http://rosalind.info/problems/fib/
    正の整数n(<=40)、k(<=5)が与えられる。1ペアから始めて、各世代において繁殖年齢のペアのウサギが kペ
    アのウサギの子孫を残すとしたとき、 nか月後に存在するウサギのペアの総数を求めよ。

    View full-size slide

  6. 本日学ぶこと
    ● 引数の評価とエラーの出し方
    ● listのスタックとしての使い方
    ● ジェネレーター関数の書き方
    ● 再帰関数の書き方
    ● メモ化を用いた高速化
    ● デコレーターの使い方

    View full-size slide

  7. argparseの型チェック
    argparseのtypeにintを指定しておけば異なる型で入力されるとエラーになる
    $ ./fib.py 5 3.2
    usage: fib.py [-h] generations litter
    fib.py: error: argument litter: invalid int value: '3.2'
    $ ./fib.py -3 2
    usage: fib.py [-h] generations litter
    fib.py: error: generations "-3" must be between 1 and 40
    今回の問題の条件である
    1<=n<=40、1<=k<=5を満たさない
    場合にエラーを上げたい場合はどう
    すればよいか?

    View full-size slide

  8. 引数のバリデーション
    ①args.genはint型なので条件比較する
    ことができる
    ②条件に合わない場合は parse.error()
    でエラーを上げてプログラムを終了でき



    View full-size slide

  9. Solution 1: listをスタックとして用いる
    ①n=0、n=1のときのペア数0,1をスタックにいれておく
    ②n=2以降の計算結果(F
    n
    = F
    n-2
    *litter + F
    n-1
    )をスタックに追加
    ③スタックに最後に入れた数が nヶ月後に存在するペア数



    スタック:LIFO (Last-In-First-Out)
    1
    3
    2
    1
    3
    2
    Push Pop

    View full-size slide

  10. Solution 2: ジェネレーター関数を使う



    yieldを使うと関数の呼
    び出しごとに結果が返
    されるジェネレーターに
    なる
    ①x,yを0,1で初期化
    ②1世代前の値を返す
    ③2世代前のxを1世代
    前yのk倍に置き換え、1
    世代前yを直近2世代の
    和に置き換える
    x=0
    y=1
    yield x
    0
    0
    x=0
    y=1
    yield y
    x=y*k=2
    y=x+y=1
    1
    1
    x=2
    y=1
    yield y
    x=y*k=2
    y=x+y=3
    1
    2
    x=2
    y=3
    yield y
    x=y*k=6
    y=x+y=5
    3
    3
    x=6
    y=5
    yield y
    x=y*k=10
    y=x+y=11
    5
    4
    x=10
    y=11
    yield y
    x=y*k=22
    y=x+y=21
    11
    5
    k=2の例

    View full-size slide

  11. (参考)itertools.islice()
    for文の代わりにislice()を使えば、指定した
    要素まで返すイテレーターが作られる
    islice(イテラブル, 要素数)
    リストにして最後の要素を取得

    View full-size slide

  12. Solution 3-1: 再帰関数を使う
    ①終了条件:nが1または2になったら1を返す
    ②それ以外は2世代前と1世代前のfib()が呼ばれる
    下図のようなスタックコールが作られていき計算される


    fib(5)
    fib(3) fib(4)
    fib(2) fib(3)
    fib(1) fib(2)
    fib(1) fib(2)

    View full-size slide

  13. Solution 3-2: メモ化による高速化


    毎回計算するのは効率が悪い
    ①空の辞書を作る
    ②辞書にない場合だけ計算する
    fib(5)
    fib(3) fib(4)
    fib(2) fib(3)
    fib(1) fib(2)
    fib(1) fib(2)

    View full-size slide

  14. Solution 3-3: メモ化(デコレーター)
    fib関数の上に@memoizeとすることでメモ化機
    能を上書くことができる

    View full-size slide

  15. Solution 3-4: functools.lru_cache()
    memoize関数を作らなくてもfunctoolsライブラリにlru_cache関数が使える

    View full-size slide

  16. ベンチマークツール:hyperfine
    ①複数回実行した平均値がわかる
    ②サマリーで速度比較の結果がわかる
    demo


    https://github.com/sharkdp/hyperfine

    View full-size slide

  17. randomを使ってランダム値でテストする
    ①random.choice()で与えられたシーケンスか
    らランダムに要素を返す
    ②random.randint(a, b)でa<=N<=bからラン
    ダムな整数を返す




    View full-size slide

  18. makeコマンドからテストを実行する
    Makefileにテストコマンドを記述しておけばmake testでテストが実行できる

    View full-size slide

  19. すべてのSolutionをまとめてテストする
    ①re.match()で正規表現にマッチする
    ファイルを取得
    ②取得したファイルに対してテストを実行


    View full-size slide

  20. 本日学んだこと
    ● 引数のバリデーションとparser.error()によるエラーの上げ方
    ● listのスタックとしての使い方
    ● yieldを使ったジェネレーターの作成
    ● 再帰関数の書き方とメモ化による高速化
    ● デコレーターの使い方
    ● hyperfineによるベンチマーキング
    ● randomモジュールによる値のランダム生成

    View full-size slide