Risolvi un'equazione di matrice con il metodo di Jacobi (rivisto)


11

Sfondo matematico

Sia A una matrice N per N di numeri reali, ba vettore di N numeri reali e xa vettore N numeri reali sconosciuti. Un'equazione di matrice è Ax = b.

Il metodo di Jacobi è il seguente: decomponi A = D + R, dove D è la matrice delle diagonali e R sono le voci rimanenti.

se si crea una soluzione di ipotesi iniziale x0, una soluzione migliorata è x1 = inversa (D) * (b - Rx) in cui tutte le moltiplicazioni sono moltiplicazione matrice-vettore e inverso (D) è l'inverso della matrice.


Specifica del problema

  • Input : il programma completo dovrebbe accettare come input i seguenti dati: la matrice A, il vettore b, un'ipotesi iniziale x0 e un numero di "errore" e.
  • Output : il programma deve generare il numero minimo di iterazioni in modo tale che l'ultima soluzione differisca dalla soluzione reale, al massimo da e. Ciò significa che ogni componente dei vettori in grandezza assoluta differisce al massimo da e. È necessario utilizzare il metodo Jacobi per le iterazioni.

Come vengono immessi i dati è la tua scelta ; potrebbe essere la tua sintassi su una riga di comando, potresti prendere l'input da un file, qualunque cosa tu scelga.

Come vengono emessi i dati è la tua scelta ; può essere scritto in un file, visualizzato nella riga di comando, scritto come arte ASCII, qualsiasi cosa, purché sia ​​leggibile da un essere umano.

Maggiori dettagli

Non ti viene data la vera soluzione: il modo in cui calcoli la vera soluzione dipende interamente da te. Puoi risolverlo secondo la regola di Cramer per esempio, o calcolare direttamente un inverso. Ciò che conta è che hai una vera soluzione per essere in grado di confrontare le iterazioni.

La precisione è un problema; alcune "soluzioni esatte" per il confronto possono differire. Ai fini di questo codice golf, la soluzione esatta deve essere fedele a 10 decimali.

Per essere assolutamente chiari, se anche un solo componente della soluzione di iterazione attuale supera di e il componente corrispondente nella soluzione reale, allora è necessario continuare a iterare.

Il limite superiore di N varia in base all'hardware utilizzato e al tempo che sei disposto a dedicare all'esecuzione del programma. Ai fini di questo codice golf, assumere massimo N = 50.

presupposti

Quando viene chiamato il tuo programma, sei libero di supporre che ciò che segue sia sempre valido:

  • N> 1 e N <51, cioè non ti verrà mai data un'equazione scalare, sempre un'equazione di matrice.
  • Tutti gli input sono sul campo dei numeri reali e non saranno mai complessi.
  • La matrice A è sempre tale che il metodo converge alla vera soluzione, in modo tale che puoi sempre trovare un numero di iterazioni per ridurre al minimo l'errore (come definito sopra) di seguito o uguale a e.
  • A non è mai la matrice zero o la matrice identità, ovvero esiste una soluzione.

Casi test

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

La vera soluzione è (0,586, 1,138). La prima iterazione fornisce x1 = (5/9, 1), differendo di oltre 0,04 dalla soluzione reale, di almeno un componente. Prendendo un'altra iterazione troviamo, x2 = (0,555, 1,148) che differisce di meno di 0,04 da (0,586, 1,138). Quindi l'output è

2

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

In questo caso la vera soluzione è (2.2, -0.8) e la supposizione iniziale x0 ha già un errore inferiore a e = 1.0, quindi viene emesso 0. In altre parole, ogni volta che non è necessario eseguire un'iterazione, si esegue semplicemente l'output

0

Valutazione di presentazione

Questo è il golf del codice, con tutte le scappatoie standard non consentite. Vince il programma completo (o funzione) corretto più breve , ovvero il numero più basso di byte. È sconsigliato usare cose come Mathematica che racchiudono molti passaggi necessari in una funzione, ma usano qualsiasi linguaggio tu voglia.


2
Dovresti davvero aspettare per ottenere più feedback, soprattutto dato il recente post chiuso. Le sfide PPCG di solito condividono una struttura comune nelle specifiche, ciò che di solito contribuisce a renderle facili da capire, piuttosto che noiose e ambigue. Prova ad esaminare alcune delle sfide ragionevolmente votate e imita il formato.
Uriel,

@Uriel me ne rendo conto, ma sento di essere stato esaustivo nelle mie specifiche e che il formato non si adatta perfettamente alla maggior parte delle domande, può essere letto in modo lineare e guidare il lettore di conseguenza. Il formato dovrebbe anche tenere presente il contenuto del problema stesso.
user1997744

3
"Il programma completo corretto più breve " suona come se consentissi solo programmi e non funzioni. Aggiungerei "/ funzione".
Adám,

2
La formattazione +1 rende o spezza la capacità del mio cervello di concentrarsi su una domanda
Stephen,

1
@ user1997744 Sì, ha senso. Ritengo che il valore predefinito sia che qualsiasi altro codice, come altre funzioni o importazioni di Python, è consentito, ma incluso anche nel bytecount.
Stephen,

Risposte:


4

APL (Dyalog) , 78 68 65 49 byte

Esattamente il tipo di problema per cui è stato creato APL.

-3 grazie a Erik the Outgolfer . -11 grazie a ngn .

Funzione infix anonima. Prende A come argomento di sinistra e x come argomento di destra. Stampa il risultato su STDOUT come unario verticale usando 1come segni di conteggio, seguito da 0punteggiatura. Ciò significa che è possibile vedere anche un risultato 0, senza essere 1prima di 0.

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

Provalo online!

Spiegazione in ordine di lettura

Notare come il codice legge in modo molto simile alla specifica del problema:

{... } sulla data A, b, ee e sulla data x,
⎕← stampa
∨/ se c'è qualche verità nell'affermazione che
e< e è più piccola
|⍵- del valore assoluto di x meno
b⌹ b matrice divisa per
⊃A b e la prima di A, b e e (cioè A)
←⍺ che sono l'argomento sinistro
: e, in tal caso, si
  ⍺∇ basano su
  D+.× D matrice-volte
  b- b meno
  ⍵+.×⍨ x, matrice moltiplicata per
  A- A meno
  ⌹D l'inverso di D (le voci rimanenti)
   dove D è
   A dove
  =/¨ ci sono
   coordinate uguali per
  ⍴A la forma di A (cioè la diagonale)

Spiegazione dettagliata

L'effettivo ordine di esecuzione da destra a sinistra:

{} Funzione anonima dove A è e ⍵ è x:
A b c←⍺ divide l'argomento sinistro in A, b ed e
 seleziona la prima
b⌹ divisione di matrice (A) con b (dà il vero valore di x)
⍵- differenze tra i valori correnti di x e quei
| valori assoluti
e< accettabili errore inferiore a quelli?
∨/ vero per nessuno? (lett. riduzione O)
⎕← stampa quel booleano su STDOUT
: e, in tal caso:
  ⍴A forma di una
   matrice di quella forma in cui ogni cella ha le proprie coordinate
  =/¨ per ogni cella, le coordinate verticale e orizzontale sono uguali? (diagonale)
   moltiplicare le cellule di A con il che (estratti diagonale)
   matrice inversa
  D← negozio a D (per D iagonal)
  
  A- sottrai  (indietro alla normalità) sottrae dalla
  ⍵+.×⍨ matrice A moltiplica (stessa cosa del prodotto punto, quindi il .) che con x
  b- sottrae quello dalla
  D+.× matrice b prodotto di D e che
  ⍺∇ applicano questa funzione con A dato e che come nuovo valore di x


L'output dovrebbe essere il numero di iterazioni richieste per una precisione di e.
Zgarb,

-1: questa non è una soluzione. È necessario x0 poiché l'intero punto è sapere quanti passaggi sono necessari per ottenere l'accuratezza desiderata da un particolare punto di partenza.
user1997744

@ user1997744 Ah, ho frainteso il problema. Scusate.
Adám,

@ user1997744 Meglio?
Adám,

1
@ user1997744 Operazione non aritmetica, ma solo capacità di leggere unaria , dove in effetti 0 è nulla .
Adám,

1

Python 3 , 132 byte

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

Provalo online!

Utilizza una soluzione ricorsiva.


@Adám Non sono sicuro di aver capito bene. L'ho interpretato come fnon avere il nome all'interno del blocco di codice, che ora ho risolto; tuttavia, se si tratta di un problema completamente diverso, potrebbe essere ancora un problema.
Notjagan,

@Adám Quella risposta sembra confermare ciò che ho attualmente; è una funzione con codice helper in grado di funzionare come unità dopo la sua definizione.
Notjagan,

Ah ok. Non importa allora. Non conosco Python, quindi ero solo curioso. Buon lavoro!
Adám,

Il criterio di arresto "Questo significa che ogni componente dei vettori in magnitudine assoluta differisce al massimo da e"? Fondamentalmente la norma massima, non la norma L2.
NikoNyrh,

@NikoNyrh Risolto.
Notjagan,

1

R , 138 byte

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}

Provalo online!

grazie a NikoNyrh per aver corretto un bug

Vale anche la pena notare che esiste un pacchetto R, Rlinsolveche contiene una lsolve.jacobifunzione, che restituisce un elenco con x(la soluzione) e iter(il numero di iterazioni richieste), ma non sono sicuro che esegua i calcoli corretti.


Il criterio di arresto "Questo significa che ogni componente dei vettori in magnitudine assoluta differisce al massimo da e"? Fondamentalmente la norma massima, non la norma L2.
NikoNyrh,

@NikoNyrh hai ragione! fortunatamente, la normfunzione lo prevede anche per me senza byte aggiuntivi.
Giuseppe,

1

Clojure, 212 198 196 byte

#(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)))

Implementato senza una libreria di matrici, itera il processo 1e9 volte per ottenere la risposta corretta. Questo non funzionerebbe su input troppo mal condizionati, ma dovrebbe funzionare bene in pratica.

Meno golfista, ero abbastanza contento delle espressioni di Re D:) Il primo input %(A) deve essere un vettore, non un elenco in modo che assocpossa essere utilizzato.

(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)))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.