雑感等

音楽,数学,語学,その他に関するメモを記す.

pythonでレスラー方程式の解軌道を描画(ルンゲクッタ法)

pythonでルンゲクッタ法を実装した.
レスラー方程式を与えて描画する.

プログラム内関数のdxdt, dydt, dzdtを書き換えれば別の微分方程式も解ける.
下記プログラムはローレンツ方程式を解くようにも書き換えられる.

import numpy as np


def dxdt(a, b, c, x, y, z):  # 引数は,「関数のパラメータを並べたもの」,「変数を並べたもの」の順番で並べる.他の連立微分方程式と同じ形式で引数を並べる.
    return -y - z


def dydt(a, b, c, x, y, z):
    return x + a * y


def dzdt(a, b, c, x, y, z):
    return b + x * z - c * z


def _handler(func, *args):
    return func(*args)


pdelist = [dxdt, dydt, dzdt]  # 連立微分方程式を追加する場合は,関数名をこのlistにも追加すること.


def runge_kutta(funcs, param, vold, delta):
    """
    ルンゲクッタ法で時間を含まない微分方程式を解く
    :param funcs: 関数のlist.上記のpdelistのように並べる.
    :param param: パラメータを並べたndarray(np.array)
    :param vold: 現在時刻における未知関数の値を並べたndarray.pdelistに含まれる関数の引数のx, y, zに相当する.
    :param delta: 計算の1ステップあたりに進める時間
    :return: 計算を1ステップ進めた後の時刻における未知関数の値を並べたndarray.pdelistに含まれる関数の引数のx, y, zに相当する.
    """
    k1 = []
    k2 = []
    k3 = []
    k4 = []
    for fnc in funcs:
        k1.append(_handler(fnc, *param, *vold))

    k11 = vold + delta * 0.5 * np.array(k1)
    for fnc in funcs:
        k2.append(_handler(fnc, *param, *k11))

    k22 = vold + delta * 0.5 * np.array(k2)
    for fnc in funcs:
        k3.append(_handler(fnc, *param, *k22))

    k33 = vold + delta * np.array(k3)
    for fnc in funcs:
        k4.append(_handler(fnc, *param, *k33))
    return vold + (np.array(k1) + 2 * np.array(k2) + 2 * np.array(k3) +
                   np.array(k4)) * delta / 6


def main():
    import pickle
    import matplotlib.pyplot as plt
    param = np.array([0.2, 0.2, 7.1])  # レスラー方程式のパラメータ
    init = np.array([4, 4, 1])  # 微分方程式の初期値
    delta = 0.1  # 1ステップあたりの経過時間
    result = []
    vnew = init
    for i in range(1, 10000):
        result.append(vnew)
        vnew = runge_kutta(pdelist, param, vnew, delta)
    result.append(vnew)
    roessler = np.array(result)  # 解の変数.roessler[時刻(sample), 変数の番号]
    with open("signal_roessler.pickle", mode="wb") as f:  # 解の変数を保存
        pickle.dump(roessler, f)
    plt.plot(roessler[:, 0], roessler[:, 1])  # 解の変数の0番目(レスラー方程式のx)を横軸に,解の変数の1番目(レスラー方程式のy)を縦軸に取り,プロットする.
    plt.xlabel("x = roessler[:, 0]")
    plt.ylabel("y = roessler[:, 1]")


if __name__ == "__main__":
    import matplotlib.pyplot as plt

    main()
    plt.show()

上記プログラムを実行すると以下のグラフが表示される.

f:id:kazmus:20190218220859p:plain
レスラー方程式のx-y軌道.パラメータ(a,b,c)=(0.2, 0.2, 7.1)初期値(x,y,z)=(4, 4, 1).4次のルンゲクッタ法で1ステップの時間を0.1とし,1万ステップ計算した.

pythonで自己MIC(相互情報量)関数を計算

自己相関関数では,ある信号sig(t)とその信号を時間kだけ遅延させた信号sig(t+k)との相関係数を計算するが,
ここでは相関係数の代わりに相互情報量(MIC)を求める関数automicを示す.
MIC自体はminepyで計算する.

下記プログラムを実行すると,グラフが2つ表示される.

"""
「自己」相互情報量(MIC)関数を計算する.
自己相関関数において,遅延と相関係数の関係を求めるように,
本関数では,遅延とMICの関係を求める.
"""
from minepy import MINE  # MICの計算ライブラリをインポート
from typing import List  # 型表示における"List"を有効化


def automic(sig: List[float]) -> List[float]:
    """
    sig[0](遅延させていない信号)とsig[k](k点遅延させた信号)との相互情報量を求める.
    :rtype: List[float]
    :param sig: 1次元の数値配列.時系列信号など.
    :return: 1次元の数値配列mics.mics[k]は遅延kにおけるMIC.
    """
    mine = MINE()
    siglen = len(sig)
    mics = []
    for k in range(0, siglen - 1):
        mine.compute_score(sig[k:-1], sig[0:-k - 1])
        mics.append(mine.mic())
    return mics


if __name__ == "__main__":
    import numpy as np
    from matplotlib import pyplot as plt

    fs = 100  # サンプリング周波数
    f = 4  # 周波数
    tmax = 1  # 終了時刻[s]
    t = np.arange(0, tmax, 1 / fs)
    sig = np.sin(2 * np.pi * f * t)
    plt.plot(t, sig, marker=".")
    plt.xlabel("t [sample]")
    plt.ylabel("signal [a.u.]")
    plt.figure()
    mics = automic(sig)
    plt.plot(mics)
    plt.xlabel("delay k [sample]")
    plt.ylabel("MIC")
    plt.show()

f:id:kazmus:20190217232923p:plain
上記プログラムでの入力信号

f:id:kazmus:20190217233012p:plain
計算された自己MIC(相互情報量)関数.入力された信号と遅延させた信号が同位相と逆位相の場合でMICが1に近づいているため,8回ピークがある.ただし,最後のピークは入力波形が短くなりすぎたためノイズが生じている.

matlabで振幅スペクトルの表示(fft)

matlab高速フーリエ変換し,振幅スペクトルを表示する.

function showfft(sig,fs)
%sig:信号.1次元配列
%fs:信号のサンプリング周波数
N=length(sig);   % 信号のサンプル数
plot(fs*(0:N-1)/N,abs(fft(sig)/N))   %振幅スペクトルの描画:縦軸が振幅,横軸が周波数
title('amplitude spectrum')
xlabel('frequency [Hz]')
ylabel('amplitude [a.u.]')
end

haskellで逆引き辞書ソート

単語を羅列したファイルから『逆引き広辞苑』みたいにソートする.

import System.IO

main :: IO ()
main = do
  hin <- openFile "test_words.txt" ReadMode  -- 読みこむファイル:単語リスト
  hout <- openFile "reverse_idx.txt" WriteMode  -- 書き込むファイル:逆引きソートした単語リスト
  contents <- hGetContents hin
  let
    rev_idx = reverseEachWords  -- もう一度各単語を逆にする. [[String]]
              $unduplicate  -- 単語リストをソートして↑ [[String]]
              $reverseEachWords  -- 単語リストの各単語を逆にして↑ [[String]]
              $words  -- 単語ごとにリストに分解して↑ [[String]]
              contents  -- 単語リストの文字列contentsを↑ [String]
  mapM_ (hPutStrLn hout) rev_idx
  hClose hout
  hClose hin
  


-- ソート,重複なくす
unduplicate::Ord a => [a] -> [a]
unduplicate []=[]
unduplicate (xs:xss)=unduplicate smaller++[xs]++unduplicate larger
  where
    smaller = [a | a <- xss, a < xs]
    larger  = [b | b <- xss, b > xs]


-- 単語リストの各要素にreverseを適用する
reverseEachWords :: [[a]] -> [[a]] -- [a]=String:1単語
reverseEachWords xs= map reverse xs

実行例

↓test_words.txt

alfabeta
alto
astrofisica
bistro
blanca
calimba
clasica
musica
temperatur
tenor
tradisional
traversa

上記プログラム実行後
↓reverse_idx.txt

calimba
clasica
astrofisica
musica
blanca
traversa
alfabeta
tradisional
bistro
alto
tenor
temperatur

参照ページ

ファイルの読み書きについて:
お気楽 Haskell プログラミング入門

reverse関数について:
reverse関数 - 結城浩のHaskell日記 - haskell

梱包テープでトイレ詰まりを解消する

下記の動画を参考にして,トイレ詰まりを解消できた.
突然トイレの流れが悪くなった 驚異のセロハンテープだけで直す方法!超簡単 - YouTube

方法

  • 念のため,「大」のレバーで水を流しても,水があふれない程度に水位を下げる(放置して水位が下がるのを待つか,便器から水をくむ).
  • 便器のふたと便座を上げる.
  • 便器のふちの水分や汚れを落とす(ふき取る程度).
  • 梱包テープで膜を作るよう便器に貼り,密封する.
    • 梱包テープは重なるように貼り,密封する.
  • 完全に密封したら,レバーを回し,水を流す.
  • 水が流れている間,便座内の圧力が上がり梱包テープの膜が膨らむが,手で押さえつける.
  • 水が流れ終えるころには,つまりが解消する.
  • 念のため,梱包テープをはがす前に1~3回水を流す.
  • 貼った梱包テープをすべてはがす.

問題の状況

詰まった原因はおそらく,トイレットペーパーを流しすぎたため.

以前も,トイレットペーパーを流しすぎて詰まったことがあったが,
トイレ内の水位が上がった状態で放置すれば,自然に解消していた.

しかし,今回は水を流して放置しても,解消しない状態が24時間以上継続した.
そのため,今回の方法を実行した.

詰まりの度合は,流れが完全に止まっていたわけではない.
ただし,便器の返し近くまで水位が上がっても,普通の水位に戻るまで30分~1時間かかっていた.
流れないため,実用できない状態だった.

他に試した対処

梱包テープを用いる以外の対処も試したが流れなかった.以下に示す.

  • ぬるま湯で流す.
  • キッチンハイターを入れる.
  • 酢を入れる.

使用したテープ

  • 3M ガムテープ 梱包テープ 重量用 48mm×50m カッター付 315DSN

Amazonで購入した.購入,到着してから4か月弱経過したものを使用した.
今回このテープで便器を密封する際は,隙間ができないように,テープ同士の一部が重なるように貼ったが,
このテープ自体の強度があったため,二重に貼らなくても問題なかった.

f:id:kazmus:20190120142557j:plain
梱包テープを便器に貼った状態.テープ同士の一部が重なるように貼った.この図では水を流し終えて,詰まりが解消した状態

Prilyさんの音列即興

音列: c g h
https://youtu.be/MEJs01hQVjI?t=1006

音列: h c f
https://youtu.be/MEJs01hQVjI?t=1114

音列: a h d
https://youtu.be/MEJs01hQVjI?t=1473

音列: d es g
https://youtu.be/MEJs01hQVjI?t=1729

音列: fis h a
https://youtu.be/MEJs01hQVjI?t=3249

音列: g cis fis
https://youtu.be/MEJs01hQVjI?t=5451