Memecahkan Sistem Persamaan Linear

12

Tulis sebuah program untuk menyelesaikan serangkaian persamaan linear sesingkat mungkin. Ini harus menyelesaikan sejumlah masalah persamaan. Mereka dapat diinput sesuai keinginan Anda, koefisien augmented matrix mungkin yang paling mudah. Program tidak harus menangani koefisien atau solusi non-integer. Tidak ada kasus rusak atau tidak valid yang akan diuji. Program harus menampilkan nilai setiap variabel atau bentuk eselon baris tereduksi.

Tidak ada perpustakaan yang memecahkan persamaan, fungsi matriks, atau cara apa pun untuk menyelesaikan secara otomatis diizinkan. Anda dapat mensimulasikan matriks dengan array atau daftar.

Input contoh (atau setara):

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

Ini mewakili 2x+y-z=8, -3x-y+2z=-11, -2x+y+2z=-3

Output contoh (atau setara):

{2,3,-1}

Ini mewakili x=2, y=3, z=-1

qwr
sumber
2
Dapatkah koefisien variabel dan suku konstanta dipisahkan menjadi dua array dalam input?
user12205
@ace ya, tidak apa-apa
qwr
1
Apa yang sebenarnya Anda katakan dengan kasus yang merosot? Saya kira Anda merujuk pada semua kasus tersebut: 1) Masukan salah; 2) Hal-hal seperti 0x=0atau 0x=5; 4) Kasus di mana jumlah persamaan berbeda dari jumlah variabel; 5) Kasus kontradiktif seperti x+5y=7, x+5y=8; 6) Kasus tanpa independensi linier, seperti x+3y=6, 2x+6y=12. Apakah saya benar?
Victor Stafusa
@ Viktor Ya, input apa pun yang memiliki ambiguitas sama sekali atau tidak dapat dipecahkan.
qwr
Bagaimana dengan kasus-kasus yang tidak merosot tetapi kondisinya buruk? (Atau, dengan kata lain, poros seperti apa yang diperlukan?)
Peter Taylor

Jawaban:

3

Python 169 166

Penerapan

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[]

Demo

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

Catatan

Jika Anda OK dengan aproksimasi float, maka Anda dapat menghapus panggilan fungsi putaran dan golf lebih lanjut hingga 159 karakter

Abhijit
sumber
9

APL, 1 char

Saya tahu ini tidak sesuai dengan persyaratan (yang direvisi), tetapi terlalu bagus untuk tidak memposting:

Simbol "domino" (pembagian ÷di dalam persegi panjang) melakukan pembagian matriks, oleh karena itu ia dapat menyelesaikan sistem persamaan linear apa pun. Anda hanya harus meletakkannya di antara vektor istilah konstan dan matriks dengan istilah lain:

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

(jika Anda ingin mencobanya di TryApl, adalah )

Tobia
sumber
4

Javascript ( 284 181) - Metode Elusinasi 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}

Uji

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]]

Array yang dikembalikan menggabungkan matriks identitas dan solusinya.

Michael M.
sumber
Anda dapat menyimpan beberapa karakter lagi.
MarcinJuraszek
Alih-alih l=A.length;for(i=0;i<l;i++)digunakan for(i=0;i<l=A.length;i++).
Victor Stafusa
Alih-alih for(i=l-1;i>=0;i--)digunakan for(i=l;--i;).
Victor Stafusa
Anda juga dapat pindah w=A[j][i]ke for()dan melewati {}.
MarcinJuraszek
Terima kasih semuanya, saya berhasil menggabungkan langkah maju dan mundur dalam satu langkah, menghemat seratus karakter dan beberapa tips Anda tidak berlaku lagi. (kecuali tip @MarcinJuraszek)
Michael M.
3

Jawaban ini tidak lagi cocok dengan pertanyaan setelah aturan berubah karena menggunakan fungsi matriks. *

Sage , 32

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

Input sampel:

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

Output sampel:

(2, 3, -1)

* Bisa dibilang, matrix()adalah typecast, bukan fungsi (running import types; isinstance(matrix, types.FunctionType)give False). Juga, ~dan *adalah operator , bukan fungsi.

pengguna12205
sumber
Saya sudah memperbarui aturan. Kode harus menangani jumlah persamaan yang berbeda dan Anda sekarang tidak dapat menggunakan fungsi matriks.
qwr
3

Jawa - 522 434 228 213 karakter

Memecahkannya dengan memeriksa secara sistematis semua n-tupel integer yang mungkin dengan perkalian langsung hingga ditemukan satu yang berfungsi.

Function mengambil augmented matrix, A, vektor solusi percobaan, x, dan dimensi, n, sebagai vektor solusi input - output, x. Perhatikan bahwa vektor x sebenarnya lebih besar dari dimensi untuk membantu melangkah melalui solusi yang mungkin. (Jika saya mendeklarasikan variabel A, x, n, j, k, s sebagai variabel instan, fungsinya akan menjadi 31 karakter lebih pendek - dengan total 182, tetapi itu terasa seperti membengkokkan aturan terlalu jauh.)

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;}}}

Program untuk pengujian (agak tidak diubah):

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;
            }
        }
    }
}

Program mengambil input dari stdin sebagai integer yang dipisahkan oleh ruang sebagai berikut: pertama, dimensi masalah, kedua, entri dari matriks yang ditambah dengan baris.

Contoh dijalankan:

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

Saya mencukur beberapa karakter dengan mengikuti saran Victor tentang loop dan "publik", menyimpan RHS dalam matriks yang diperbesar alih-alih secara terpisah, dan menambahkan entri tambahan ke solusi uji coba saya untuk menyederhanakan pembuatan setiap solusi uji coba baru. OP juga mengatakan bahwa suatu fungsi sudah cukup - tidak perlu menghitung keseluruhan program.

Wally
sumber
while(true){f=0;for(j=0;j<n;j++)dapat digantikan oleh while(true){for(f=j=0;j<n;j++). Selanjutnya kelas Anda tidak perlu menjadi publik. Untuk loop dengan hanya satu instruksi dalam tubuh tidak perlu kurung kurawal.
Victor Stafusa
Saya pikir itu for(j=0;j<n;j++){for(k=0;k<n;k++){A[j][k]=p.nextInt();}b[j]=p.nextInt();}bisa digantikan olehfor(j=0;j<n;b[j++]=p.nextInt())for(k=0;k<n;)A[j][k++]=p.nextInt();
Victor Stafusa
@ Viktor Terima kasih, saya membuat itu, dan lainnya, perubahan.
Wally
while(true)dapat diubah menjadifor(;;)
user12205
@ace terima kasih - mengubahnya dan beberapa hal lainnya dan mencukur 15 karakter.
Wally
1

JavaScript (ES6),  152  151 byte

Implementasi aturan 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))

Cobalah online!

Arnauld
sumber