2016-04-26 50 views
2

我需要用一些值填充矩陣(存儲爲數組數組)。該矩陣是一個簡單的擴散問題,雅可比,看起來像這樣:Smalltalk(Pharo)中嵌套的「if」(AKA「開關」)

J(1,1) = 1, J(N,N)=0 

1<n<N

J(n,n) = -2k/dx^2 - 2*c(n) 
J(n,n-1)=J(n,n+1) = k/dx^2 

矩陣元素都爲零的其餘部分。

到目前爲止,我有這個畸形:

(1 to: c size) collect: [ :n | 
       (1 to: c size) collect: [ :m | 
        n = 1 | (n = c size) 
         ifTrue: [ m = n ifTrue: [ 1.0 ] ifFalse: [ 0.0 ] ] 
         ifFalse: [ m = n 
          ifTrue: [ -2.0 * k/dx squared - (2.0 * (c at: n)) ] 
          ifFalse: [ m = (n-1) | (m = (n+1)) 
           ifTrue: [ k/dx squared ] 
           ifFalse: [ 0.0 ] ] ] 
        ] ] 

通知嵌套的 「if語句」(Smalltalk的當量)。這工作。但是,在那裏,也許有更好的方法來做同樣的事情?就目前來看,這是相當難以理解的。

+1

對於非玩具問題,您可能希望爲此使用更高效(稀疏)的矩陣實現。 –

+0

@StephanEggermont當然,對於更嚴重的任務,我必須實現一個稀疏(帶狀)矩陣:速度性能x2 - x3。 – mobiuseng

回答

4

出於可讀性的考慮,我會考慮犧牲額外的O(n)時間,並完全避免IF(這會讓它更快......)。

J(N,N) = 0 
J(1,1) = 1 
//and for 1<n<N: 
J(n,n) = Y(n) 
J(n,m-1) = J(n,m+1) = X 

這告訴我的是,整個矩陣看起來像這樣

(1 X 0 0 0) 
(X Y X 0 0) 
(0 X Y X 0) 
(0 0 X Y X) 
(0 0 0 X 0) 

這意味着我可以只使用零整個矩陣,然後更改對角線和鄰近的對角線。

jNM := [ k/dx squared ]. 
jNN := [ :n | -2.0 * k/dx squared - (2.0 * (c at: n)) ]. 

n := c size. 
m := Matrix 
    new: n 
    tabulate: [:i :j | 0 ]. 
(1 to: n - 1) do: [ :i | 
    m at: i at: i put: (jNN value: i). 
    m at: i + 1 at: i put: jnM value. 
    m at: i at: i + 1 put: jnM value. 
]. 
m at: 1 at: 1 put: 1. 

注:我不熟悉這背後的數學,但對於J(n,m-1)價值似乎是一個不斷給我。注意2:我將值設置爲i + 1索引,因爲我從1;1開始,但是您可以從相反方向開始,並且有i-1

+0

是的,我應該想到只是沿着對角線前進!至於你的問題:'J(n,n-1)'在這裏確實是不變的。但總的來說,它可能更復雜。 – mobiuseng

6
n := c size. 
Matrix 
    new: n 
    tabulate: [:i :j | self jacobianAtRow: i column: j] 

其中

jacobianAtRow: i column: j 
    n := c size. 
    (i = 1 or: [i = n]) ifTrue: [^j = i ifTrue: [1.0] ifFalse [0.0]]. 
    j = i ifTrue: [^-2.0 * k/dx squared - (2.0 * (c at: i))]. 
    (j = (i - 1) or: [j = (i + 1)]) ifTrue: [^k/dx squared]. 
    ^0.0 

基本上,一般的想法是這樣的:當你本身找到嵌套IFS,因子指出,一段代碼的方法和改造築巢成的情況下,像枚舉它會在每種可能情況下返回一個值。

+0

我認爲這種方法總的來說會更好,但是這個矩陣總體只適用於測試用例。所以,我會用另一個答案,這對我的具體情況更好。 – mobiuseng

+0

我也喜歡@Peter的解決方案,我認爲我們都有意讓你意識到'new:tabulate:'方法(我稱之爲'fromBlock:dimension:') –

+0

不幸的是,矩陣我是使用沒有這個方法。也許我不應該使用它,並使用標準的'矩陣'類(或添加'新:表:'),但這是一個不同的問題:) – mobiuseng