ヤコビ法による行列方程式の解法(改訂版)


11

数学的背景

AをN×Nの実数行列、Nの実数のbaベクトル、xaのベクトルNの未知の実数とします。行列方程式はAx = bです。

ヤコビの方法は次のとおりです。A= D + Rを分解します。ここで、Dは対角行列で、Rは残りのエントリです。

初期推測解x0を作成する場合、改善された解はx1 = inverse(D)*(b-Rx)です。ここで、すべての乗算は行列ベクトル乗算で、inverse(D)は逆行列です。


問題の仕様

  • 入力:完全なプログラムは、次のデータを入力として受け入れる必要があります:行列A、ベクトルb、初期推測x0、および 'エラー'数e。
  • 出力:プログラムは、最新のソリューションが実際のソリューションと最大でe異なるように、最小の反復回数を出力する必要があります。これは、絶対的な大きさのベクトルの各成分が最大でe異なることを意味します。反復にはJacobiの方法を使用する必要があります。

データの入力方法は選択できます。コマンドラインでの独自の構文である可能性があります。ファイルから入力を選択することができます。

データの出力方法は任意です。ファイルに書き込み、コマンドラインに表示、ASCIIアートなど、人間が読み取り可能なものであれば何でも記述できます。

詳細

真の解決策は与えられません。真の解決策の計算方法は完全にあなた次第です。たとえば、Cramerのルールによって解決することも、逆関数を直接計算することもできます。重要なのは、反復と比較できる真のソリューションがあることです。

精度が問題です。一部の人々の比較のための「正確な解決策」は異なる場合があります。このゴルフの目的のために、正確な解は小数点以下10桁まで正確でなければなりません。

明確にするために、現在の反復ソリューションの1つのコンポーネントでさえ、真のソリューションの対応するコンポーネントをeだけ超えている場合は、繰り返し続ける必要があります。

Nの上限は、使用しているハードウェアと、プログラムの実行に費やす時間によって異なります。このコードゴルフでは、最大N = 50を想定しています。

前提条件

プログラムが呼び出されたとき、次のことが常に成り立つと考えることができます。

  • N> 1およびN <51。つまり、スカラー方程式は与えられず、常に行列方程式が与えられます。
  • すべての入力は実数のフィールド上にあり、決して複雑になることはありません。
  • 行列Aは常にメソッドが真の解に収束するようなものであるため、e以下のエラー(上記で定義)を最小化するための反復回数を常に見つけることができます。
  • Aはゼロ行列でも恒等行列でもありません。つまり、1つの解があります。

テストケース

A = ((9, -2), (1, 3)), b = (3,4), x0 = (1,1), e = 0.04

真の解決策は(0.586、1.138)です。最初の反復では、x1 =(5/9、1)が得られます。これは、真の解と0.04以上、少なくとも1つのコンポーネントが異なります。別の反復を行うと、x2 =(0.555、1.148)が(0.586、1.138)と0.04未満しか異なりません。したがって、出力は

2

A = ((2, 3), (1, 4)), b = (2, -1), x0 = (2.7, -0.7), e = 1.0

この場合、真の解は(2.2、-0.8)であり、初期推測x0にはすでにe = 1.0未満の誤差があるため、0を出力します。つまり、反復を行う必要がない場合は、単に出力します

0

提出評価

これはコードゴルフであり、すべての標準的な抜け穴はここでは禁止されています。最短の正しい完全なプログラム(または関数)、つまり最小のバイト数が勝ちます。必要な多くのステップを1つの関数にまとめるMathematicaのようなものを使用することはお勧めませんが、必要な言語を使用してください。


2
特に最近の閉鎖された投稿を考えると、あなたは本当にそれについてより多くのフィードバックを得るのを待つべきです。PPCGの課題は、通常、仕様で共通の構造を共有します。これは、通常、面倒で曖昧なものではなく、理解しやすいものです。適度に上回った課題のいくつかを見て、フォーマットをまねてみてください。
ウリエル

@Uriel私はこれを理解していますが、私は自分の仕様に徹底的に取り組んでいると感じており、形式はほとんどの質問に正確には適合していませんが、直線的に読むことができ、それに応じて読者を導きます。この形式では、問題自体の内容も念頭に置く必要があります。
user1997744

3
「最短の正しい完全なプログラム」は、機能のみではなくプログラムのみを許可するように聞こえます。「/ function」を追加します。
アダム

2
1つの書式を作るか疑問に集中する私の脳の能力を破る
スティーブン・

1
@ user1997744うん、理にかなっています。デフォルトでは、他の関数やpythonインポートのような他のコードは許可されますが、バイトカウントにも含まれると思います。
スティーブン

回答:


4

APL(Dyalog)78 68 65 49バイト

APLが作成された問題のタイプ。

-3 アウトゴルファーのエリックに感謝します。-11 ngnに感謝します

匿名挿入関数。Aを左引数として、xを右引数として取ります。1タリーマークとして使用し、その後に0句読点として使用して、結果をSTDOUTに垂直単項として出力します。これは、0の結果でさえも見ることができ、1の前にs がないことを意味し0ます。

{⎕←∨/e<|⍵-b⌹⊃A b e←⍺:⍺∇D+.×b-⍵+.×⍨A-⌹D←⌹A×=/¨⍳⍴A}

オンラインでお試しください!

読み上げ順の説明

コードが問題の仕様と非常によく似ていることに注意してください。

{... } 与えられたA、B、及びE、及び所与のXに、
⎕← 印刷
∨/ こと文の任意の真実があるか否か
e< eがより小さくなる
|⍵- の絶対値は、xマイナス
b⌹ マトリックス分割によりB
⊃A b e A、Bの第一、及びe(すなわちA)
←⍺ は左引数で
: あり、そうであれば、 D行列時間 bマイナス x、 A  にDの逆数(残りのエントリ)を掛けた行列で
  ⍺∇ 再帰します。 ここでDは 形状の 等しい 座標 があるAですA(つまり、対角線)
  D+.×
  b-
  ⍵+.×⍨
  A-
  ⌹D
  
  
  =/¨
  
  ⍴A

段階的な説明

右から左への実際の実行順序:

{} 匿名関数で、Aはbe、⍵はx:
A b c←⍺ 左引数をA、b、eに 分割し、xの 現在の値と 許容される 絶対値との差b(xの真の値を与える
 )の最初の(A)
b⌹行列除算を選択しますそれらより小さいエラー? いずれにも当てはまりますか?(点灯または縮小) ブール値をSTDOUTに出力します。 その場合: shape of  各セルが各セルの独自の座標である形状の行列。 垂直座標と水平座標は等しいですか?(対角線) その(抽出対角線)を有するAの多重セル 逆行列 (のためにDに格納D iagonal)
⍵-
|
e<
∨/
⎕←
:
  ⍴A
  
  =/¨
  
  
  D←
   (通常に戻る)
  A- A
  ⍵+.×⍨ 行列からの逆算(ドット積と同じもの、したがって.)x  は、Dの
  b- b
  D+.×行列積からそれを減算し、
  ⍺∇ この関数を与えられたA beおよびxの新しい値として適用する


出力は、の精度に必要な反復回数でなければなりませんe
ズガーブ

-1:これは解決策ではありません。x0が必要なのは、全体のポイントが、特定の開始点から目的の精度に到達するために必要なステップ数を知ることだからです。
user1997744

@ user1997744ああ、私は問題を誤解しました。ごめんなさい。
アダム

@ user1997744良いですか?
アダム

1
@ user1997744算術演算ではなく単項式を読み取る能力だけで、実際には0 は何もありません
アダム

1

Python 3、132バイト

f=lambda A,b,x,e:e<l.norm(x-dot(l.inv(A),b))and 1+f(A,b,dot(l.inv(d(d(A))),b-dot(A-d(d(A)),x)),e)
from numpy import*
l=linalg
d=diag

オンラインでお試しください!

再帰的なソリューションを使用します。


@Adám私はかなり理解していると確信していません。fコードブロック内に名前がないと解釈しましたが、現在修正しています。ただし、それがまったく別の問題である場合は、依然として問題である可能性があります。
-notjagan

@Adámその答えは、私が現在持っているものを裏付けているようです。定義後、ユニットとして機能することができるヘルパーコードを持つ関数です。
-notjagan

ああ、わかった。じゃあ心配しないで。私はPythonを知らないので、興味がありました。よくやった!
アダム

停止基準「これは、絶対的な大きさのベクトルの各成分が最大でeだけ異なることを意味します」ではありませんか?基本的に、L2-normではなく、max-normです。
ニコニール

@NikoNyrh修正済み。
-notjagan

1

R、138バイト

function(A,x,b,e){R=A-(D=diag(diag(A)))
g=solve(A,b)
if(norm(t(x-g),"M")<e)T=0
while(norm((y=solve(D)%*%(b-R%*%x))-g,"M")>e){T=T+1;x=y}
T}

オンラインでお試しください!

バグを修正してくれたNikoNyrhに感謝

またRlinsolvelsolve.jacobi関数を含むRパッケージがあり、x(ソリューション)およびiter(必要な反復回数)を含むリストを返すことも注目に値しますが、正しい計算を行うかどうかはわかりません。


停止基準「これは、絶対的な大きさのベクトルの各成分が最大でeだけ異なることを意味します」ではありませんか?基本的に、L2-normではなく、max-normです。
ニコニール

@NikoNyrhあなたは正しいです!幸いなことに、このnorm関数は追加のバイトなしでそれを提供してくれます。
ジュゼッペ

1

Clojure、212 198 196バイト

#(let[E(range)I(iterate(fn[X](map(fn[r b d](/(- b(apply +(map * r X)))d))(map assoc % E(repeat 0))%2(map nth % E)))%3)](count(for[x I :while(not-every?(fn[e](<(- %4)e %4))(map -(nth I 1e9)x))]x)))

マトリックスライブラリなしで実装され、プロセスを1e9回繰り返して正しい答えを取得します。これはあまり条件の悪い入力では機能しませんが、実際には問題なく機能するはずです。

あまりゴルフをしなかったので、Rand の表現にとても満足しましたD:)最初の入力%(A)は、assoc使用できるようにリストではなくベクトルでなければなりません。

(def f #(let[R(map assoc %(range)(repeat 0))
             D(map nth %(range))
             I(iterate(fn[X](map(fn[r x b d](/(- b(apply +(map * r x)))d))R(repeat X)%2 D))%3)]
          (->> I
               (take-while (fn[x](not-every?(fn[e](<(- %4)e %4))(map -(nth I 1e9)x))))
               count)))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.