Risolvi un sistema di equazioni lineari


12

Scrivi un programma per risolvere una serie di equazioni lineari il più breve possibile. Deve risolvere un numero arbitrario di problemi con le equazioni. Possono essere immessi come preferisci, i coefficienti di matrice aumentata sono probabilmente i più semplici. Il programma non deve gestire coefficienti o soluzioni non interi. Non verranno testati casi degenerati o non validi. Il programma deve generare il valore di ogni variabile o modulo di echelon a riga ridotta.

Non sono consentite librerie di risoluzione di equazioni, funzioni di matrice o alcun modo per risolvere automaticamente. È possibile simulare matrici con matrici o elenchi.

Esempio di input (o equivalente):

m={{2,1,-1,8},{-3,-1,2,-11},{-2,1,2,-3}}

Questo rappresenta 2x+y-z=8, -3x-y+2z=-11, -2x+y+2z=-3

Esempio di output (o equivalente):

{2,3,-1}

Questo rappresenta x=2, y=3, z=-1


2
I coefficienti delle variabili e i termini costanti possono essere separati in due array nell'input?
utente12205

@ace sì, va bene
qwr

1
Cosa stai dicendo esattamente in casi degenerati? Immagino che ti riferisci a tutti quei casi: 1) input non valido; 2) Cose come 0x=0o 0x=5; 4) Casi in cui il numero di equazioni è diverso dal numero di variabili; 5) Casi contraddittori come x+5y=7, x+5y=8; 6) Casi senza indipendenza lineare, come x+3y=6, 2x+6y=12. Ho ragione?
Victor Stafusa

@Victor Sì, qualsiasi input che abbia qualche ambiguità o non sia risolvibile.
qwr

Che dire dei casi che non sono degeneri ma che sono mal condizionati? (O, in altre parole, che tipo di perno è richiesto?)
Peter Taylor,

Risposte:


3

Python 169 166

Implementazione

def s(a):
 if a:b=a[0];r=s([[x-1.*y*b[0]/r[0]for x,y in zip(b[1:],r[1:])]for r in a[1:]]);return[round((b[-1]-sum(x*y for x,y in zip(b[1:-1],r)))/b[0])]+r
 return[]

dimostrazione

>>> arr=[[2, 1, -1, 8], [-3, -1, 2, -11], [-2, 1, 2, -3]]
>>> s(arr)
[2.0, 3.0, -1.0]

Nota

Se si è d'accordo con l'approssimazione float, è possibile rimuovere la chiamata di funzione rotonda e continuare a golf a 159 caratteri


9

APL, 1 carattere

So che non soddisfa i requisiti (rivisti), ma è troppo bello per non pubblicare:

Il simbolo "domino" (divisione ÷all'interno di un rettangolo) esegue la divisione matrice, quindi può risolvere qualsiasi sistema di equazioni lineari. Devi solo metterlo tra il vettore di termine costante e la matrice con gli altri termini:

      8 ¯11 ¯3 ⌹ ⊃(2 1 ¯1)(¯3 ¯1 2)(¯2 1 2)
2 3 ¯1

(se vuoi provarlo su TryApl, è )


4

Javascript ( 284 181) - Metodo di eliminazione di Gauss

function f(A){l=A.length;d=1;for(i=0;i+1;i+=d){v=A[i][i];for(k=0;k<l+1;k++)A[i][k]/=v;for(j=i+d;A[j];j+=d)for(k=0,w=A[j][i];k<l+1;k++)A[j][k]-=w*A[i][k];if(i==l-d)d=-1,i=l}return A}

Test

f([[2,1,-1,8],[-3,-1,2,-11],[-2,1,2,-3]]);

=> [[1,0,0,2],[0,1,0,3],[-0,-0,1,-1]]

L'array restituito combina la matrice identità e la soluzione.


Puoi salvare altri due personaggi.
MarcinJuraszek,

Invece di l=A.length;for(i=0;i<l;i++)usare for(i=0;i<l=A.length;i++).
Victor Stafusa

Invece di for(i=l-1;i>=0;i--)usare for(i=l;--i;).
Victor Stafusa

È anche possibile spostare w=A[j][i]in for()e saltare {}in giro.
MarcinJuraszek,

Grazie a tutti, sono riuscito a unire i passaggi avanti e indietro in un solo passaggio, risparmiando un centinaio di caratteri e alcuni dei tuoi suggerimenti non sono più validi. (tranne la punta di @MarcinJuraszek)
Michael M.

3

Questa risposta non si adatta più alla domanda dopo la modifica della regola poiché utilizza una funzione matrice. *

Sage , 32

~matrix(input())*vector(input())

Input di esempio:

[[2, 1, -1], [-3, -1, 2], [-2, 1, 2]]
[8, -11, -3]

Uscita campione:

(2, 3, -1)

* Probabilmente, matrix()è un typecast, non una funzione (in esecuzione import types; isinstance(matrix, types.FunctionType)False). Inoltre, gli operatori sono ~e non le funzioni.*


Ho aggiornato le regole. Il codice deve gestire un numero diverso di equazioni e ora non è possibile utilizzare le funzioni matrice.
qwr

3

Java - 522 434 228 213 caratteri

Risolve controllando sistematicamente tutte le possibili n-tuple di numeri interi per moltiplicazione diretta fino a quando non si trova che funziona.

La funzione accetta matrice aumentata, A, vettore soluzione di prova, x e dimensione, n, come vettore soluzione di input - output, x. Si noti che il vettore x è in realtà uno più grande della dimensione per aiutare a passare attraverso possibili soluzioni. (Se avessi dichiarato le variabili A, x, n, j, k, s come variabili di istanza, la funzione sarebbe stata di 31 caratteri più corta - per un totale di 182, ma sembra che si pieghino troppo le regole.)

int[]Z(int[][]A,int[]x,int n){int j,k,s;for(;;){for(j=0;j<n;j++){for(k=s=0;k<n;s+=A[j][k]*x[k++]);if(s!=A[j][n])j+=n;}if(j==n)return x;for(j=0;j<=n;j++)if(x[j]!=x[n]||j==n){x[j]++;for(k=0;k<j;x[k++]=-x[n]);j=n;}}}

Programma per i test (un po 'non golfizzato):

import java.util.*;
class MatrixSolver{
    public MatrixSolver() {
        Scanner p=new Scanner(System.in); //initialize everything from stdin
        int j,k,n=p.nextInt(),A[][]=new int[n][n+1],x[]=new int[n+1];
        for(j=0;j<n;j++)for(k=0;k<=n;A[j][k++]=p.nextInt());
        x=Z(A,x,n); //call the magic function
        for(j=0;j<n;j++) System.out.print(x[j]+" "); //print the output
    }
    public static void main(String[]args){
        new MatrixSolver();
    } 

    int[]Z(int[][]A,int[]x,int n){
        int j,k,s;
        for(;;){
            for(j=0;j<n;j++){ //multiply each row of matrix by trial solution and check to see if it is correct
                for(k=s=0;k<n;s+=A[j][k]*x[k++]);
                if(s!=A[j][n])j+=n;
            }
            if(j==n)return x; //if it is correct return the trial solution
            for(j=0;j<=n;j++)if(x[j]!=x[n]||j==n){//calculate the next trial solution
                x[j]++;
                for(k=0;k<j;x[k++]=-x[n]);
                j=n;
            }
        }
    }
}

Il programma prende l'input dallo stdin come numeri interi separati da spazio come segue: in primo luogo, la dimensione del problema, in secondo luogo, le voci della matrice aumentata per riga.

Esecuzione di esempio:

$java -jar MatrixSolver.jar
3 2 1 -1 8 -3 -1 2 -11 -2 1 2 -3
2 3 -1 

Ho rasato diversi personaggi seguendo i consigli di Victor su loop e "pubblico", memorizzando l'RHS nella matrice aumentata anziché separatamente e aggiungendo una voce aggiuntiva alla mia soluzione di prova per semplificare la generazione di ogni nuova soluzione di prova. L'OP ha anche affermato che una funzione è sufficiente: non è necessario contare l'intero programma.


while(true){f=0;for(j=0;j<n;j++)può essere sostituito da while(true){for(f=j=0;j<n;j++). Inoltre la tua classe non deve essere pubblica. I for-loop con una sola istruzione nel corpo non hanno bisogno delle parentesi graffe.
Victor Stafusa

Penso che for(j=0;j<n;j++){for(k=0;k<n;k++){A[j][k]=p.nextInt();}b[j]=p.nextInt();}possa essere sostituito dafor(j=0;j<n;b[j++]=p.nextInt())for(k=0;k<n;)A[j][k++]=p.nextInt();
Victor Stafusa

@Victor Grazie, ho apportato queste e altre modifiche.
Wally,

while(true)può essere modificato infor(;;)
user12205

@ace grazie - ho cambiato questo e un paio di altre cose e ho raduto 15 caratteri.
Wally,

1

JavaScript (ES6),  152  151 byte

Implementazione di regola Cramer .

(m)(v)mv

m=>v=>m.map((_,i)=>(D=m=>m+m?m.reduce((s,[v],i)=>s+(i&1?-v:v)*D(m.map(([,...r])=>r).filter(_=>i--)),0):1)(m.map((r,y)=>r.map((k,x)=>x-i?k:v[y])))/D(m))

Provalo online!

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.