Re: [問題] 迴圈寫法詢問
※ 引述《bear0418 (貝爾出品 優質好文)》之銘言:
: 各位好
: 我有先看過說明裡面有關迴圈的範例 可是裡面的都是很單純的舉例
: 以我現在的程度 我沒辦法類比到我現在碰到的問題
: 所以來請問大家一下 希望可以幫忙
: 我現在碰到的問題是解harmonic oscillator 的 eigenvalue problem
: 我已經定義好了一個矩陣A (9 by 9)
: 現在我定義一個sv1=Table[1,{9}] (sv是starting vector)
: 計算 A.sv1 會給我一個新的vector 我們叫他sv2
: 接下來我要把sv2除以裡面數字最大的那個元素
: 比如說 sv2是{-9,5,0,0,0,0,2,1,3}就除-9 sv2是{-5,2,3,0,1,2,6,8,12}就除12
: 這部分我是用以下方法解決(nf=normalized factor)
: nf2=
: Which[Abs[Max[sv2]]>Abs[Min[sv2],Max[SV2],Abs[Max[sv2]<Abs[Min[sv2]],Min[sv2]
: 所以上面給我我所需要的元素 除掉後會有一個被normalize過的vector
: 我們叫其 sv3=sv2/nf2
: 接下來我要計算A.sv3
: 然後重複以上步驟 將結果除以裏面數字最大的元素->得到一個normalized的向量
: 再用A去打
: 最後我想看我所提出來的那個數字 nf會收斂到多少
: 這個問題我想很久了 我沒辦法把上述的流程整合成一個迴圈....
: 請大家幫幫忙 謝謝
也就是說一個迴圈裡包含了兩小步
第一小步是 A dot 第二小步則是 normalize
那麼先定函數吧:
transform[v_] := A.Transpose[v]
normalize[v_] := v / If[Abs[Max[v]] >= Abs[Min[v]], Max[v], Min[v]]
說明一下
第一小步要加 Transpose 的原因是
如果你想這樣內積, Dot 的右邊應該要是 column vector
但你的中間結果卻是 row vector 所以需要轉置
而且這樣一來 sv 得要寫成 {Table[1, {9}]} 這樣才是一個 2D row vector
單單 Table[1, {9}] 只是 1D vector 而已
第二小步由於你這裡只有兩個狀況, 所以用 If 就足夠了, 不需要用到 Which
Which 是在三個以上的條件時才會用
(不過要仔細考慮一下最大最小值絕對值相等的狀況要哪邊, 上面寫的是這時選正的)
函數定好之後你的每個步驟就會是 normalize[transform[v]]
也把它定成函數:
step[v_] := normalize[transform[v]]
再來就是這篇的主角 函數迭代系列函式
這一系列函式共有以下成員:
Nest
NestWhile
Fold
FixedPoint
以及上面四個函式名後面多 List:
NestList
NestWhileList
FoldList
FixedPointList
一共八個函式
做的事情都很類似, 就是把一個結果不斷地代入函式裡直到某個時候為止
Nest 最單純
Nest[f, x, n] 計算 f[f[f[...f[x]...]]] 一共 n 層 f 的結果
NestWhile 則稍微有點變化
NestWhile[f, x, g] 會一直套 f 到某一次的結果代入 g 得不到 True 為止
也就是會回傳第一個使 g[f[...f[x]...]] 不為 True 的 f[...f[x]...]
Fold 是帶額外參數的, 它比較像是 Accumulate 的推廣
Fold[f, x, {a, b, c, ..., z}] 計算 f[...f[f[f[x, a], b], c]..., z] 的結果
FixedPoint 則是求不動點, 也就是代到不動了為止
FixedPoint[f, x] 從 x 開始, 代 f 之後再看看是不是不動了
回傳代到不動的那個答案
這四個函式如果換成有 List 的名字的話
它會把所有中間結果都收集起來回傳給你
得到的答案第一個是一開始給的 x, 最後一個則是沒有 List 時的回傳值
(Accumulate 的說明裡有提到
Accumulate[list] 等同於 Rest[FoldList[Plus, 0, list]]
這就是為什麼我說 Fold 比較像是 Accumulate 的推廣)
以你的問題來說, 由於你是想觀察收斂情形
使用 NestList 比較適合
NestList[step, sv, 10] 會回傳一個含 11 個元素的 List
第一個是 sv, 第二個是一步之後的 sv, etc. 到第 11 個是 10 步之後的 sv
只不過由於你的元素是 row vector 的關係
因此中間結果收集起來會變成一個三維 List
不過這也不妨礙觀察結果就是
---
關於這些函式
NestWhile 有一些變化型, 可以選擇要代進 g 的中間結果個數
條件滿足後要回傳多代還是少代幾次的結果, 以及最多代 f 代幾次
FixedPoint 可以用 SameTest->func 來指定怎樣叫做不動了 (預設是 SameQ)
當然也能指定最多代 f 代幾次
可以視情況選擇應用
在你的狀況, 如果你只是想要看收斂值的話
可以用 FixedPoint 指定 SameTest 讓它算到誤差多少以內就當不動
(例如 error[v1_, v2_] := Norm[v1-v2] < 10^-5 然後指定 SameTest->error)
這樣回傳的答案就是收斂值了
或者改成 FixedPointList 那就還能看收斂過程
這系列的迭代函式很常用在「做某件事幾次」或「做某件事到什麼條件為止」的情境
同樣的目的如果用 Do/For/While 寫的話會比較麻煩一點
(用 Do/For/While 的話要自己紀錄過去的結果
如果要觀察過程的話除了 Print 大概得用上我在上幾篇帶過的 Sow/Reap
你可能就是因為這樣才會卡關的)
--
題外話, 我在版上其實還滿常在推廣純函式的
不過這系列的 f 函數是我少數會先定個名字下來的情形
一來好寫, 二來可以先測一下每一步的動作是不是我要的
不過像上面 SameTest 那種我大概會直接寫 SameTest->(Norm[#1-#2] < 10^-5 &) XD
--
1985/01/12 三嶋鳴海 1989/02/22 優希堂悟 1990/02/22 冬川こころ 1993/07/05 小町
つぐみ 歡迎來到 1994/05/21 高江ミュウ 1997/03/24 守野いづみ 1997/03/24 伊野瀬
チサト 1998/06/18 守野くるみ 打越鋼太郎的 1999/10/19 楠田ゆに 2000/02/15 樋口遙
2002/12/17 八神ココ 2011/01/11 HAL18於朱倉岳墜機 ∞與∫的世界 2011/04/02 茜崎空
啟動 2012/05/21 第貮日蝕計畫預定 2017/05/01~07 LeMU崩壞 2019/04/01~07 某大學合宿
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.112.30.32
※ 文章網址: http://www.ptt.cc/bbs/Mathematica/M.1402400560.A.74C.html
推
06/10 19:49, , 1F
06/10 19:49, 1F
→
06/10 19:51, , 2F
06/10 19:51, 2F
討論串 (同標題文章)
Mathematica 近期熱門文章
PTT數位生活區 即時熱門文章