Jacobi의 방법으로 행렬 방정식 풀기 (개정)


11

수학적 배경

A를 실수의 N x N 행렬, N 실수의 ba 벡터 및 xa 벡터 N 알 수없는 실수로하자. 행렬 방정식은 Ax = b입니다.

Jacobi의 방법은 다음과 같습니다. 분해 A = D + R. 여기서 D는 대각선의 행렬이고 R은 나머지 항목입니다.

초기 추측 솔루션 x0을 만드는 경우 개선 된 솔루션은 x1 = inverse (D) * (b-Rx)입니다. 여기서 모든 곱셈은 행렬-벡터 곱셈이고 inverse (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.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

제출 평가

이것은 모든 표준 허점이 허용되지 않는 코드 골프입니다. 가장 짧은 정확한 완전한 프로그램 (또는 기능), 즉 가장 적은 바이트 수가 이깁니다. 그것은되는 낙담 한 함수에 필요한 많은 단계를 마무리하지만, 당신이 원하는 언어를 사용 티카 같은 사용 것들.


2
특히 최근 닫힌 게시물을 고려할 때 더 많은 피드백을 얻을 때까지 기다려야합니다. PPCG 과제는 일반적으로 사양이 공통적 인 구조를 공유하는데, 이는 일반적으로 귀찮고 모호하지 않고 이해하기 쉽도록 기여합니다. 합리적으로 제기 된 도전 과제를 살펴보고 형식을 모방하십시오.
우리엘

@Uriel 나는 이것을 알고 있지만, 나는 내 사양에 철저한 느낌이 들었고, 대부분의 질문에 정확하게 맞지 않으면 서 형식을 선형으로 읽고 독자에 따라 독자를 인도 할 수 있습니다. 형식은 또한 문제 자체의 내용을 염두에 두어야합니다.
user1997744

3
"가장 짧은 정확한 전체 프로그램 "은 프로그램 만 허용하고 기능은 허용하지 않는 것처럼 들립니다. "/ function"을 추가하겠습니다.
Adám

2
+1 형식은 내 두뇌가 질문에 집중하는 능력을 만들거나 깨뜨린 다
Stephen

1
그렇습니다. 기본적으로 다른 함수 또는 파이썬 가져 오기와 같은 다른 코드는 허용되지만 바이트 수에도 포함되어 있다고 생각합니다.
Stephen

답변:


4

APL (Dyalog) , 78 68 65 49 바이트

정확하게 APL이 만들어지는 문제의 유형.

-3 Outgolfer Erik에게 감사합니다 . ngn 덕분에 -11 감사합니다 .

익명의 접사 기능. A를 왼쪽 인수로 사용하고 x를 오른쪽 인수로 사용합니다. 1탈리 마크를 사용하고 그 뒤에 0구두점을 사용하여 결과를 STDOUT에 세로 단항으로 인쇄 합니다 . 즉, 1앞에 0이없는 0 결과도 볼 수 있습니다 0.

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

온라인으로 사용해보십시오!

읽기 순서 설명

코드가 문제 사양과 매우 유사하게 읽는 방법에 주목하십시오.

{... } 지정된 A, B 및 E, 및 주어진 X에
⎕← 인쇄
∨/ 되는 문의 모든 진리가 있는지
e< 예는보다 작은
|⍵- 절대 값이 X 뺀
b⌹ 행렬 분할하여 B
⊃A b e A, B의 제 및 E (즉, A)
←⍺ 왼쪽 인자있는
: 등, 경우
  ⍺∇ 재귀
  D+.× D 행렬 배
  b- 마이너스 B
  ⍵+.×⍨ X는 매트릭스 승산
  A- 마이너스
  ⌹D D (나머지 항목)의 역
   D가  동일있다  좌표  형상 A (즉, 대각선)
  
  =/¨
  
  ⍴A

단계별 설명

오른쪽에서 왼쪽으로 실제 실행 순서 :

{… A가 있고 ⍵이 x 인 } 익명 함수 :
A b c←⍺ 왼쪽 인수를 A, b로 나누고 e  는 x의  현재 값과  허용 가능한  절대 값 사이 의 b (x는 실제 값 제공
 )를
b⌹갖는 첫 번째 (A) 행렬 나누기를 선택합니다. 그보다 적은 오류?  어떤 사실입니까? (lit. OR reduction)  해당 부울을 STDOUT으로 인쇄  하고 그럴 경우 :  모양  각 셀이 각 셀에 대한 고유 좌표 인 해당 모양 의 행렬은  세로 및 가로 좌표가 동일합니까? (대각선)  그 (추출 대각선)와의 곱셈 세포  역행렬  D에 저장 (용 D iagonal)
⍵-
|
e<
∨/
⎕←
:
  ⍴A
  
  =/¨
  
  
  D←
  
  A- A
  ⍵+.×⍨ 행렬 에서  역 (역으로 돌아 가기) 빼기 (점 곱과 같은 것, 따라서 .) x  는 D의
  b- b
  D+.×행렬 곱 에서 빼고
  ⍺∇ 주어진 A be와 함께이 함수 를 적용하고 x의 새로운 값으로 곱합니다.


출력은의 정확도에 필요한 반복 횟수 여야합니다 e.
Zgarb

-1 : 해결책이 아닙니다. 요점은 특정 시작점에서 원하는 정확도에 도달하는 데 걸리는 단계 수를 아는 것이므로 x0이 필요합니다.
user1997744

@ user1997744 아, 나는 문제를 오해했다. 죄송합니다.
Adám

더 나은?
Adám

1
@ user1997744 산술 연산이 아니라 단항 읽기 기능 만 있습니다. 실제로 0 은 아무것도 아닙니다 .
Adám

1

파이썬 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

그래. 그럼 신경 쓰지 마 나는 파이썬을 모른다. 그래서 나는 단지 궁금했다. 잘 했어!
Adám

정지 기준이 아닌가? "이것은 절대 크기의 벡터의 각 성분이 최대 e만큼 다르다는 것을 의미합니까?" 기본적으로 L2-norm이 아닌 max-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에게 감사합니다

함수 Rlinsolve를 포함하고 (솔루션)과 (반복 횟수 )가 lsolve.jacobi있는 목록을 반환 하는 R 패키지가 있다는 점도 주목할 가치가 있지만 올바른 계산을 수행하는지 확실하지 않습니다.xiter


정지 기준이 아닌가? "이것은 절대 크기의 벡터의 각 성분이 최대 e만큼 다르다는 것을 의미합니까?" 기본적으로 L2-norm이 아닌 max-norm입니다.
NikoNyrh

@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 회 반복합니다. 이것은 너무 좋지 않은 입력에 대해서는 작동하지 않지만 실제로는 잘 작동합니다.

이하 나는 표현에 아주 행복했다, golfed RD: 첫 번째 입력 %(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.