Re: [問題] 迴圈寫法詢問

看板Mathematica作者 (1597463007)時間10年前 (2014/06/10 19:42), 編輯推噓1(101)
留言2則, 1人參與, 最新討論串2/2 (看更多)
※ 引述《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
文章代碼(AID): #1JbkymTC (Mathematica)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
文章代碼(AID): #1JbkymTC (Mathematica)