แก้สมการเมทริกซ์ด้วยวิธีของ Jacobi (แก้ไข)


11

พื้นหลังทางคณิตศาสตร์

ให้ A เป็นเมทริกซ์ N คูณ N ของจำนวนจริง, เวกเตอร์ ba ของจำนวนจริง N และเวกเตอร์ xa N ไม่ทราบจำนวนจริง สมการเมทริกซ์คือ Axe = b

วิธีการของ Jacobi มีดังต่อไปนี้: ย่อยสลาย A = D + R โดยที่ D คือเมทริกซ์ของเส้นทแยงมุมและ R คือรายการที่เหลือ

หากคุณสร้างโซลูชันเดาเริ่มต้น x0 โซลูชันที่ได้รับการปรับปรุงคือ x1 = inverse (D) * (b - Rx) โดยการคูณทั้งหมดเป็นการคูณเมทริกซ์เวกเตอร์และอินเวอร์ส (D) เป็นเมทริกซ์ผกผัน


ข้อกำหนดของปัญหา

  • อินพุต : โปรแกรมที่สมบูรณ์ของคุณควรยอมรับว่าป้อนข้อมูลต่อไปนี้: เมทริกซ์ A, เวกเตอร์ b, การเดาเริ่มต้น x0 และหมายเลข 'ข้อผิดพลาด' e
  • เอาท์พุท : โปรแกรมจะต้องส่งออกจำนวนรอบต่ำสุดของการทำซ้ำเพื่อให้โซลูชั่นล่าสุดแตกต่างจากการแก้ปัญหาที่แท้จริงโดยมากที่สุด e นี่หมายความว่าแต่ละองค์ประกอบของเวกเตอร์ที่มีขนาดสมบูรณ์แตกต่างกันมากที่สุด e คุณต้องใช้วิธีการของ Jacobi สำหรับการทำซ้ำ

วิธีการป้อนข้อมูลเป็นทางเลือกของคุณ ; มันอาจเป็นไวยากรณ์ของคุณเองในบรรทัดคำสั่งคุณสามารถรับอินพุตจากไฟล์อะไรก็ได้ที่คุณเลือก

คุณเลือกเอาท์พุทข้อมูลอย่างไร มันสามารถเขียนลงในไฟล์ที่แสดงในบรรทัดคำสั่งเขียนเป็นศิลปะ ASCII ทุกอย่างตราบเท่าที่มนุษย์สามารถอ่านได้

รายละเอียดเพิ่มเติม

คุณไม่ได้รับโซลูชันที่แท้จริง: วิธีคำนวณโซลูชันที่แท้จริงนั้นขึ้นอยู่กับคุณทั้งหมด คุณสามารถแก้ไขได้โดยกฎของ Cramer เช่นหรือคำนวณคำผกผันโดยตรง สิ่งที่สำคัญคือคุณมีทางออกที่แท้จริงเพื่อให้สามารถเปรียบเทียบกับการทำซ้ำได้

ความแม่นยำเป็นปัญหา 'การแก้ปัญหาที่แน่นอน' ของบางคนสำหรับการเปรียบเทียบอาจแตกต่างกัน สำหรับจุดประสงค์ของรหัสนี้กอล์ฟทางออกที่แน่นอนจะต้องเป็นจริงถึงทศนิยม 10 ตำแหน่ง

เพื่อให้มีความชัดเจนอย่างแน่นอนหากองค์ประกอบหนึ่งในโซลูชันการทำซ้ำปัจจุบันของคุณเกินกว่าองค์ประกอบที่เกี่ยวข้องในโซลูชันที่แท้จริงโดย e คุณจะต้องทำการวนซ้ำ

ขีด จำกัด สูงสุดเป็น N แตกต่างกันไปตามฮาร์ดแวร์ที่คุณใช้และเวลาที่คุณยินดีจ่ายในการใช้งานโปรแกรม สำหรับจุดประสงค์ของกอล์ฟรหัสนี้ให้ถือว่า N สูงสุด 50

ปัจจัยพื้นฐาน

เมื่อโปรแกรมของคุณถูกเรียกใช้คุณมีอิสระที่จะคิดว่าสิ่งเหล่านี้มีอยู่ตลอดเวลา:

  • N> 1 และ N <51 นั่นคือคุณจะไม่ได้สมการสเกลาร์มาเป็นสมการเมทริกซ์เสมอ
  • อินพุตทั้งหมดอยู่เหนือสนามจำนวนจริงและจะไม่ซับซ้อน
  • เมทริกซ์ A เป็นวิธีการที่แปรเปลี่ยนเป็นวิธีแก้ปัญหาที่แท้จริงเสมอซึ่งคุณสามารถค้นหาจำนวนซ้ำเพื่อลดข้อผิดพลาด (ตามที่กำหนดไว้ด้านบน) ด้านล่างหรือเท่ากับ e
  • A ไม่เคยเป็นศูนย์เมทริกซ์หรือเมทริกซ์เอกลักษณ์นั่นคือมีวิธีแก้ปัญหาเดียว

กรณีทดสอบ

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

ทางออกที่แท้จริงคือ (0.586, 1.138) การวนซ้ำครั้งแรกให้ x1 = (5/9, 1), แตกต่างกันมากกว่า 0.04 จากการแก้ปัญหาจริงโดยอย่างน้อยหนึ่งองค์ประกอบ เราพบการวนซ้ำอีกครั้ง, x2 = (0.555, 1.148) ซึ่งแตกต่างน้อยกว่า 0.04 จาก (0.586, 1.138) ดังนั้นผลลัพธ์คือ

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

การประเมินผลการส่ง

นี่คือรหัสกอล์ฟโดยที่ช่องโหว่มาตรฐานทั้งหมดไม่อนุญาต โปรแกรมที่สมบูรณ์ที่สั้นที่สุดที่ถูกต้อง(หรือฟังก์ชัน) คือจำนวนไบต์ต่ำสุดที่ชนะ มันเป็นกำลังใจที่จะใช้สิ่งที่ต้องการ Mathematica ซึ่งห่อขึ้นมากของขั้นตอนที่จำเป็นเป็นหนึ่งในฟังก์ชั่น แต่ใช้ภาษาที่คุณต้องการ


2
คุณควรรอรับข้อเสนอแนะเพิ่มเติมโดยเฉพาะอย่างยิ่งโพสต์ที่ปิดล่าสุด ความท้าทายของ PPCG มักจะแบ่งปันโครงสร้างทั่วไปในสเปคสิ่งที่มักจะช่วยให้พวกเขาเข้าใจง่ายแทนที่จะเป็นที่น่าเบื่อและคลุมเครือ พยายามที่จะดูบางส่วนของความท้าทายที่ upvoted พอสมควรและเลียนแบบรูปแบบ
Uriel

@Uriel ฉันตระหนักถึงสิ่งนี้ แต่ฉันรู้สึกว่าฉันหมดแรงในสเปคของฉันและรูปแบบที่ไม่ตรงกับคำถามส่วนใหญ่สามารถอ่านได้ในเชิงเส้นตรงและให้คำแนะนำผู้อ่านตามนั้น รูปแบบควรคำนึงถึงเนื้อหาของปัญหาด้วย
user1997744

3
" โปรแกรมที่สมบูรณ์ที่สั้นที่สุดที่ถูกต้อง" ดูเหมือนว่าคุณจะอนุญาตเฉพาะโปรแกรมและไม่ทำงาน ฉันจะเพิ่ม "/ function"
อดัม

2
การจัดรูปแบบ +1 ทำให้หรือทำลายความสามารถของสมองของฉันในการตั้งคำถาม
Stephen

1
@ user1997744 ใช่แล้วทำให้รู้สึก ฉันเชื่อว่าค่าเริ่มต้นคืออนุญาตให้ใช้รหัสอื่นใดเช่นฟังก์ชั่นอื่นหรือการนำเข้าหลาม แต่ยังรวมอยู่ใน bytecount
สตีเฟ่น

คำตอบ:


4

APL (Dyalog) , 78 68 65 49 ไบต์

ประเภทของปัญหา APL ถูกสร้างขึ้นอย่างแน่นอน

-3 ขอบคุณที่เอริก Outgolfer -11 ขอบคุณ NGN

ฟังก์ชั่นมัดไม่ระบุชื่อ รับค่า A เป็นอาร์กิวเมนต์ซ้ายและ x เป็นอาร์กิวเมนต์ที่ถูกต้อง พิมพ์ผลลัพธ์ไปที่ STDOUT เป็นแนวตั้งโดยใช้1เป็นเครื่องหมายนับตามด้วย0เครื่องหมายวรรคตอน ซึ่งหมายความว่าแม้ 0 ผลสามารถมองเห็นได้เป็นไม่มี1s 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+.× D matrix- คูณ
  b- b ลบ
  ⍵+.×⍨ x, เมทริกซ์คูณด้วย
  A- A ลบ
  ⌹D ค่าผกผันของ D (รายการที่เหลือ)
   โดย D คือ
   A ที่
  =/¨ มี
   พิกัดเท่ากับ
  ⍴A  รูปร่าง ของ A (เช่นเส้นทแยงมุม)

คำอธิบายทีละขั้นตอน

ลำดับการดำเนินการจริงจากขวาไปซ้าย:

{} ฟังก์ชั่นนิรนามโดยที่A คือและ⍵คือ x:
A b c←⍺ แยกอาร์กิวเมนต์ซ้ายเป็น A, b และ e
 เลือก
b⌹ ส่วนเมทริกซ์แรก (A) กับ b (ให้ค่าจริงของ x)
⍵- ความแตกต่างระหว่างค่าปัจจุบันของ x และ
| ค่าสัมบูรณ์
e< ที่ยอมรับได้ ข้อผิดพลาดน้อยกว่านั้น?
∨/ จริงหรือ? (สว่างหรือลดขนาด)
⎕← พิมพ์บูลีนไปยัง STDOUT
: และหากเป็นเช่นนั้น:
  ⍴A รูปร่างของ
   เมทริกซ์ของรูปร่างนั้นโดยที่แต่ละเซลล์เป็นพิกัดของตนเอง
  =/¨ สำหรับแต่ละเซลล์พิกัดแนวตั้งและแนวนอนเท่ากันหรือไม่ (เส้นทแยงมุม)
   คูณเซลล์ของ A ด้วย
   เมทริกซ์ที่
  D← เก็บ ( ตรงกันข้าม) ใน D (สำหรับD iagonal)
   ผกผัน (กลับสู่ปกติ)
  A- ลบออกจาก A
  ⍵+.×⍨ คูณเมทริกซ์ (เหมือนกับ dot dot ดังนั้น.) ที่มี x
  b- ลบนั่นจาก b
  D+.× เมทริกซ์ผลคูณของ D และ
  ⍺∇ ใช้ฟังก์ชันนี้โดยให้ A เป็นและเป็นค่าใหม่ของ x


eการส่งออกควรจะมีจำนวนซ้ำที่จำเป็นสำหรับความถูกต้องของนั้น
Zgarb

-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

ลองออนไลน์!

ใช้โซลูชันแบบเรียกซ้ำ


@ Adam ฉันไม่แน่ใจว่าฉันค่อนข้างเข้าใจ ฉันตีความว่าfไม่มีชื่ออยู่ในบล็อคโค้ดซึ่งตอนนี้ฉันคงที่แล้ว อย่างไรก็ตามหากเป็นปัญหาอื่นทั้งหมดก็อาจยังคงมีปัญหา
notjagan

@ Adámคำตอบนั้นดูเหมือนจะยืนยันสิ่งที่ฉันมีอยู่ในปัจจุบัน; มันเป็นฟังก์ชั่นที่มีรหัสผู้ช่วยที่สามารถทำงานเป็นหน่วยหลังจากคำจำกัดความของมัน
notjagan

อาโอเค. ไม่เป็นไรแล้ว ฉันไม่รู้จัก Python ดังนั้นฉันแค่อยากรู้ เยี่ยมมาก!
Adám

เกณฑ์การหยุดไม่ใช่ "นี่หมายความว่าแต่ละองค์ประกอบของเวกเตอร์ที่มีขนาดสมบูรณ์แตกต่างกันอย่างมากโดย e" หรือไม่? โดยทั่วไปแล้ว max-norm ไม่ใช่ L2-norm
NikoNyrh

@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 สำหรับการแก้ไขข้อผิดพลาด

นอกจากนี้ยังเป็นที่น่าสังเกตว่ามีแพ็กเกจ R Rlinsolveซึ่งมีlsolve.jacobiฟังก์ชั่นส่งคืนรายการด้วยx(โซลูชัน) และiter(จำนวนการทำซ้ำที่จำเป็น) แต่ฉันไม่แน่ใจว่ามันทำการคำนวณที่ถูกต้อง


เกณฑ์การหยุดไม่ใช่ "นี่หมายความว่าแต่ละองค์ประกอบของเวกเตอร์ที่มีขนาดสมบูรณ์แตกต่างกันอย่างมากโดย e" หรือไม่? โดยทั่วไปแล้ว max-norm ไม่ใช่ L2-norm
NikoNyrh

@NikoNyrh คุณถูกต้อง! โชคดีที่normฟังก์ชั่นให้ฉันด้วยเช่นกันโดยไม่ต้องเพิ่มไบต์
Giuseppe

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 ครั้งเพื่อรับคำตอบที่ถูกต้อง สิ่งนี้จะไม่ทำงานกับอินพุตที่ไม่ได้คุณภาพ แต่ควรใช้ในทางปฏิบัติได้ดี

กอล์ฟน้อยฉันมีความสุขมากกับการแสดงออกRและ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.