弾性体の振動の縦波と横波
よねすけです。振動波動論の試験で弾性体の振動に関する問題が出て勉強してなくて全く分かりませんでした。つらい。。。
弾性体中の座標ベクトルの点の、時間における変位をとすると、弾性体の振動の方程式は
で与えられます。ここでは弾性体の密度、はヤング率、はポアソン比です。(いずれも定数、)
定ベクトルを用いてと書けたとします。これを先の振動の式に代入して整理すると
が得られます。
縦波の場合、すなわち考える波の進行方向と媒質の振動方向が平行な場合、
が言えます。を代入すれば
です。縦波の速さをとおくとなので
が分かりました。
横波の場合、すなわち考える波の進行方向と媒質の振動方向が垂直な場合、
が言えます。
横波の速さをとおくとなので
が分かりました。
縦波、横波の速さを比較してみましょう。
これより、が分かります。
地震のP波の速さはおよそ、地震のQ波の速さはおよそと言われているそうなのでだいたい一致していますね。
それでは。
無理数の無理数の無理数の・・・
こんにちは。世の大学生は試験前で忙しい頃ですね。僕ももれなく忙しいです。試験勉強頑張りましょうね。
少し前にtsujimotterさんのこの記事が話題になりました。
tsujimotter.hatenablog.com
この記事ではを用いて無理数の無理数乗の中で有理数になるものが存在することの証明を行っていました。結果から言うとは超越数になります。(このことは
ゲルフォント=シュナイダーの定理 - Wikipediaを用いるとすぐに分かります。)
では、次の値を考えてみましょう。
なんじゃこれ、そもそも収束するのか??って思わせる式ですね。
でもこれ、きちんと収束してくれるんですよ。しかも有理数に。不思議ですよね。は超越数になるのに、その操作を無限回行うと有理数になる。無限というものの神秘を感じます。
以下に証明を示します。証明は理系の高校生ならわかるとてもシンプルなものになっています。
高校生でも理解できる簡単な証明ですね。(これは多分同志社大学の数学の入試問題やった。)
(証明)
与えられた式を次のように数列を用いて漸化式で書き換えます。
証明すべきことはがに収束することです。
まずを数学的帰納法により示します。の時は明らかです。あるでだとすると
となりの場合も示されました。以上よりです。
次にという関数を考えます。
となります。ここで平均値の定理を考えると区間で
なるが存在します。が分かっているのでです。これより
が分かります。あとはこれを順番に用いると
となります。よりの極限で
となりました。以上よりが示されました。
一般にが自然対数の底よりも小さな以上の実数なら
が成立します。極限は奥が深いですね。
それでは。
数学のメモその3
今回は、一旦ゼータ関数を置いといてフーリエ解析に関することを書きます。
授業の中でPlancherel(プランシュレル)の定理というものを習いました、
Plancherelの定理というものなんですが授業ではさらっと流されて証明もプリントで、、、みたいな感じやったんですけどこの定理は結構面白いことを言ってるんじゃないかなあと思いました。
:有界連続
適当な正規直交関数系を一つ考えてみましょう。正規直交関数系とは
を満たすもののことです。勘の良い方はこれで僕が何を言いたいのか分かったかも知れませんね笑。この関数がに関してなどなど適当な条件を満たしているとしましょう。のFourier変換をと書くことにすると、
がプランシュレルの定理から分かります。これが何を意味しているかというと適当な条件を満たす正規直交関数系をひとつ持ってこればそれをFourier変換して得られる系もまた正規直交関数系となるのです!!
教授氏にこのことについて質問してみると、チェビシェフの多項式においてこのことが成り立つそうです。また時間があるときに確かめてみたいです。
それでは。
数学のメモその2
前回に続きの証明を書きたいと思います。
〜2重積分を用いる〜
この証明は2重積分
の値を2通リに求めることからわかります。1つ目はを等比級数に展開することです。
の2つ目の計算方法は変数変換です。
と変数変換します。するとより
である。またヤコビアンはである。
変数変換後の積分領域は上の図の色がけ部であるからとに分けて積分する。またに関して対称であることも考慮すると
となります。ここでを用いました。
ここでとおくと、であるから結局、となります。
またとおくと、であるから結局、となります。よって、
がわかります。ここで第1項の積分については、第2項の積分についてはと変数変換すると
となります!!!以上より
が示されました。
あと1つ証明があるのでそれはまた今度ということで。
数学のメモ
授業の演習問題での証明する問題が出たのでいろいろな証明を載せたいと思います。
~フーリエ級数展開の利用~
についてこれは無限級数なのでフーリエ級数展開を用いることを考えます。(授業の演習問題はこの方法だった)
周期関数の複素フーリエ級数展開を計算すると
である。を代入すると
となります。あとは式変形すると
となることがわかりました。
~別の級数から求める~
先ほどの関数の複素でない場合のフーリエ級数展開から得られる
があります。これを書き下してみると
一方、適切な不等式評価を行うとは収束することがわかるので、この値をと置いてみます。
ここで以下のような級数を考えます。
この級数はきちんと収束して先ほどのを用いるととなります。
そこでこの2つの無限級数を足し合わせてみます。
すると左辺はちょうどとなり、これはに一致します。右辺と比較するとより、
が得られました。
続きは長くなるので次回に書きます。
C++で8パズルをA*探索、IDA*探索を用いて解いた
授業で8パズルの探索を図示する課題があったんだけど、どうせならってことでプログラムを書いた。
A*アルゴリズムと言うのは、推定関数h(x)を使って、ゴールまでの距離を推定して、今までの探索の深さとの合計によってそのノードの評価値f(x)を決めて、それを元に最良優先探索をするアルゴリズムのこと。
IDA*アルゴリズムは、A*と同じようにf(x)を決めて、cutoff以下のf(x)の点だけを展開して深さ優先探索して、詰んだらcutoffを増やしてやり直し、っていうアルゴリズム(反復深化+A*みたいなかんじ)
コマンドライン引数で、
1:A*,推定関数は位置が違うパズルの数
2:A*,推定関数はマンハッタン距離
3:IDA*,推定関数は位置が違うパズルの数
4:IDA*,推定関数はマンハッタン距離
出力の方法が雑魚いのは勘弁して下さい\(^o^)/
#include <iostream> #include <cstdlib> #include <functional> #include <queue> #include <stack> #include <map> #include <vector> struct state { int puzzle[9]; int depth; int evaluation; bool operator>(const state &s) const { return evaluation > s.evaluation; } }; state start = { {1, 2, 3, 4, 5, 6, 7, 8, 0}, 0, 0}; state goal = { {4, 1, 5, 0, 3, 2, 7, 8, 6}, // puzzle 0, // depth 0}; // evaluation std::priority_queue <state, std::vector<state>, std::greater<state> > open; std::stack<state> open2; std::vector<state> closed; int count = 0; int max = 0; bool IsFinished(state s) { for (int i = 0; i < 8; i++) { if (s.puzzle[i] != goal.puzzle[i]) { return false; } } return true; } int ManhattanOne(int n, int place) { if (goal.puzzle[n] == 0) { return 0; } int q, r; q = abs(place / 3 - n / 3); r = abs(place % 3 - n % 3); return q + r; } int manhattan(state s) { int eval = 0; std::map<int, int> goalplace; for (int i = 0; i < 9; i++) { goalplace[goal.puzzle[i]] = i; } for (int i = 0; i < 9; i++) { eval += ManhattanOne(goalplace[s.puzzle[i]], i); } return eval; } int wrong(state s) { int eval = 0; for (int i = 0; i < 9; i++) { if (s.puzzle[i] != 0 and s.puzzle[i] != goal.puzzle[i]) { eval++; } } return eval; } void PrintState(state s) { std::cout << '|' << s.puzzle[0] << '|' << s.puzzle[1] << '|' << s.puzzle[2] << '|' << ' ' << count << std::endl; std::cout << '|' << s.puzzle[3] << '|' << s.puzzle[4] << '|' << s.puzzle[5] << '|' << " f(n) = " << s.evaluation << std::endl; std::cout << '|' << s.puzzle[6] << '|' << s.puzzle[7] << '|' << s.puzzle[8] << '|' << " g(n) = " << s.depth << std::endl << std::endl; return; } bool IsSamePuzzle(state s1, state s2) { for (int i = 0; i < 9; i++) { if (s1.puzzle[i] != s2.puzzle[i]) { return false; } } return true; } bool InClosed(state s) { for (int i = 0; i < closed.size(); i++) { if (IsSamePuzzle(s, closed[i])) { return true; } } return false; } void AStar(std::function<int(state)> fun) { if (open.empty()) { std::cerr << "Search have mistakenly stopped!" << std::endl; } if (max < open.size() + closed.size()) { max = open.size() + closed.size(); } count++; state now = open.top(); open.pop(); closed.push_back(now); PrintState(now); if (IsFinished(now)) { std::cout << "Finished!" << std::endl; return; } state s = now; int zero; for (int i = 0; i < 9; i++) { if (now.puzzle[i] == 0) { zero = i; break; } } if (zero - 3 >= 0) { std::swap(s.puzzle[zero - 3], s.puzzle[zero]); if (not InClosed(s)) { s.depth++; s.evaluation = fun(s) + s.depth; open.push(s); } s = now; } if (zero % 3 != 0) { std::swap(s.puzzle[zero - 1], s.puzzle[zero]); if (not InClosed(s)) { s.depth++; s.evaluation = fun(s) + s.depth; open.push(s); } s = now; } if (zero % 3 != 2) { std::swap(s.puzzle[zero + 1], s.puzzle[zero]); if (not InClosed(s)) { s.depth++; s.evaluation = fun(s) + s.depth; open.push(s); } s = now; } if (zero + 3 < 9) { std::swap(s.puzzle[zero + 3], s.puzzle[zero]); if (not InClosed(s)) { s.depth++; s.evaluation = fun(s) + s.depth; open.push(s); } } AStar(fun); return; } void IDAStar_rep(std::function<int(state)> fun, int c) { if (open2.empty()) { std::cout << c << " roop end" << std::endl; c++; open2.push(start); closed.clear(); IDAStar_rep(fun, c); return; } if (max < open2.size() + closed.size()) { max = open2.size() + closed.size(); } state now = open2.top(); closed.push_back(now); open2.pop(); count++; if (IsFinished(now)) { PrintState(now); std::cout << "Finished!" << std::endl; return; } state s = now; PrintState(now); int zero; for (int i = 0; i < 9; i++) { if (now.puzzle[i] == 0) { zero = i; break; } } if (zero - 3 >= 0) { std::swap(s.puzzle[zero - 3], s.puzzle[zero]); if (not InClosed(s)) { s.depth++; s.evaluation = fun(s) + s.depth; if (s.evaluation <= c) { open2.push(s); } } s = now; } if (zero % 3 != 0) { std::swap(s.puzzle[zero - 1], s.puzzle[zero]); if (not InClosed(s)) { s.depth++; s.evaluation = fun(s) + s.depth; if (s.evaluation <= c) { open2.push(s); } } s = now; } if (zero % 3 != 2) { std::swap(s.puzzle[zero + 1], s.puzzle[zero]); if (not InClosed(s)) { s.depth++; s.evaluation = fun(s) + s.depth; if (s.evaluation <= c) { open2.push(s); } } s = now; } if (zero + 3 < 9) { std::swap(s.puzzle[zero + 3], s.puzzle[zero]); if (not InClosed(s)) { s.depth++; s.evaluation = fun(s) + s.depth; if (s.evaluation <= c) { open2.push(s); } } s = now; } IDAStar_rep(fun, c); return; } void IDAStar(std::function<int(state)> fun) { IDAStar_rep(fun, open2.top().evaluation); return; } int main(int argc, char *argv[]) { if(argc != 2) { std::cerr << "Usage: <Executable filename> <type number>" << std::endl; exit(0); } std::function< int(state) > fun; std::function< void(std::function< int(state) >) > alg; switch (*argv[1]) { case '1': fun = wrong; alg = AStar; break; case '2': fun = manhattan; alg = AStar; break; case '3': fun = wrong; alg = IDAStar; break; case '4': fun = manhattan; alg = IDAStar; break; } start.evaluation = fun(start); open.push(start); open2.push(start); alg(fun); std::cout << "Most saved nodes: " << max << std::endl; return 0; }
結果は、以下のとおり
1のとき、28手、メモリに保存したノードの数52
2のとき、21手、メモリに保存したノードの数35
3のとき、33手、メモリに保存したノードの数17
4のとき、10手、メモリに保存したノードの数12
IDA*つえー
行列の固有値計算のJacobi法をpythonで実装した
数値計算ライブラリのnumpyはほんとに便利。
import numpy as np def jacobi(A,N,check): B = np.fabs(A - np.diag(list(np.diag(A)))) nondiagmax = np.max(B) while nondiagmax > check: k = int(np.argmax(B) / 3) m = np.argmax(B) % 3 cos2phi = np.fabs(A[k,k] - A[m,m]) / \ np.sqrt(4.0 * A[k,m]**2 + (A[k,k] - A[m,m])**2) cosphi = np.sqrt((1.0 + cos2phi) / 2.0) sinphi = np.sign(-A[k,m] * (A[k,k] - A[m,m])) * \ np.sqrt((1.0 - cos2phi) / 2.0) P = np.matrix(np.identity(N)) P[k,k] = cosphi P[k,m] = sinphi P[m,k] = -sinphi P[m,m] = cosphi A = ((P.T).dot(A)).dot(P) B = np.fabs(A - np.diag(list(np.diag(A)))) nondiagmax = np.max(B) print(A) print(np.diag(A)) if __name__ == "__main__": EPS = 1e-8 N = 3 A = np.matrix([[3.0,0.01,0.1],[0.01,2.0,0.1],[0.1,0.1,1.0]]) print(A) jacobi(A,N,EPS)
結果より、固有値は、[ 3.00521156 2.00950971 0.98527872]