Giải hệ phương trình tuyến tính


12

Viết chương trình giải một loạt phương trình tuyến tính càng ngắn càng tốt. Nó phải giải quyết số lượng các vấn đề phương trình tùy ý. Họ có thể nhập vào theo cách bạn muốn, hệ số của ma trận tăng có lẽ là dễ nhất. Chương trình không phải xử lý các hệ số hoặc giải pháp không nguyên. Không có trường hợp thoái hóa hoặc không hợp lệ sẽ được kiểm tra. Chương trình phải xuất giá trị của từng dạng biến đổi hàng giảm hoặc hàng giảm.

Không cho phép các thư viện giải phương trình, hàm ma trận hoặc bất kỳ cách nào để tự động giải được. Bạn có thể mô phỏng ma trận với các mảng hoặc danh sách.

Ví dụ đầu vào (hoặc tương đương):

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

Điều này thể hiện 2x+y-z=8, -3x-y+2z=-11, -2x+y+2z=-3

Ví dụ đầu ra (hoặc tương đương):

{2,3,-1}

Điều này thể hiện x=2, y=3, z=-1


2
Các hệ số của các biến và các điều khoản không đổi có thể được tách thành hai mảng trong đầu vào không?
dùng12205

@ace vâng, điều đó tốt thôi
qwr

1
Chính xác những gì bạn đang nói bởi các trường hợp thoái hóa? Tôi đoán rằng bạn đang đề cập đến tất cả các trường hợp sau: 1) Đầu vào không đúng định dạng; 2) Những thứ như 0x=0hoặc 0x=5; 4) Các trường hợp số phương trình khác với số lượng biến; 5) Các trường hợp mâu thuẫn như x+5y=7, x+5y=8; 6) Các trường hợp không có độc lập tuyến tính, như x+3y=6, 2x+6y=12. Tôi có đúng không
Victor Stafusa

@Victor Có, bất kỳ đầu vào nào có bất kỳ sự mơ hồ nào hoặc không thể giải quyết được.
qwr

Còn những trường hợp không bị thoái hóa nhưng bị bệnh thì sao? (Hay nói cách khác, loại trục nào là bắt buộc?)
Peter Taylor

Câu trả lời:


3

Con trăn 169 166

Thực hiện

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

Bản giới thiệu

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

Ghi chú

Nếu bạn ổn với xấp xỉ float, thì bạn có thể loại bỏ lệnh gọi hàm tròn và tiếp tục chơi gôn tới 159 ký tự


9

APL, 1 char

Tôi biết nó không phù hợp với yêu cầu (đã sửa đổi), nhưng quá tốt để không đăng:

Biểu tượng "domino" (phép chia ÷bên trong hình chữ nhật) thực hiện phép chia ma trận, do đó nó có thể giải bất kỳ hệ phương trình tuyến tính nào. Bạn chỉ cần đặt nó giữa vectơ không đổi và ma trận với các điều khoản khác:

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

(nếu bạn muốn dùng thử trên TryApl, )


4

Javascript ( 284 181) - Phương pháp loại bỏ 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}

Kiểm tra

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

Mảng trả về kết hợp ma trận danh tính và giải pháp.


Bạn có thể lưu thêm vài ký tự.
MarcinJuraszek

Thay vì l=A.length;for(i=0;i<l;i++)sử dụng for(i=0;i<l=A.length;i++).
Victor Stafusa

Thay vì for(i=l-1;i>=0;i--)sử dụng for(i=l;--i;).
Victor Stafusa

Bạn cũng có thể di chuyển w=A[j][i]vào for()và bỏ qua {}xung quanh.
MarcinJuraszek

Cảm ơn tất cả mọi người, tôi đã xoay sở để hợp nhất các bước tiến và lùi trong một bước duy nhất, tiết kiệm hàng trăm ký tự và một số mẹo của bạn không còn hiệu lực nữa. (ngoại trừ mẹo @MarcinJuraszek)
Michael M.

3

Câu trả lời này không còn phù hợp với câu hỏi sau khi thay đổi quy tắc vì nó sử dụng hàm ma trận. *

Hiền nhân , 32

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

Đầu vào mẫu:

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

Đầu ra mẫu:

(2, 3, -1)

* Có thể cho rằng, matrix()là một typecast, không phải là một chức năng (chạy import types; isinstance(matrix, types.FunctionType)cho False). Ngoài ra, ~*toán tử , không phải chức năng.


Tôi đã cập nhật các quy tắc. Mã phải xử lý số phương trình khác nhau và bây giờ bạn không thể sử dụng các hàm ma trận.
qwr

3

Java - 522 434 228 213 ký tự

Giải quyết bằng cách kiểm tra một cách có hệ thống tất cả các số nguyên n có thể bằng cách nhân trực tiếp cho đến khi tìm thấy một hoạt động.

Hàm lấy ma trận tăng, A, vectơ giải pháp thử nghiệm, x và kích thước, n, làm vectơ giải pháp đầu vào - đầu ra, x. Lưu ý rằng vectơ x thực sự là một vectơ lớn hơn kích thước để giúp bước qua các giải pháp có thể. .

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

Chương trình thử nghiệm (hơi vô dụng):

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

Chương trình lấy đầu vào từ stdin làm số nguyên phân tách không gian như sau: thứ nhất, thứ nguyên của vấn đề, thứ hai, các mục của ma trận tăng theo hàng.

Chạy mẫu:

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

Tôi đã cạo một số ký tự bằng cách làm theo lời khuyên của Victor về các vòng lặp và "công khai", lưu trữ RHS trong ma trận tăng cường thay vì riêng biệt và thêm một mục nhập vào giải pháp dùng thử của tôi để đơn giản hóa việc tạo ra mỗi giải pháp dùng thử mới. OP cũng nói rằng một chức năng là đủ - không cần phải tính toàn bộ chương trình.


while(true){f=0;for(j=0;j<n;j++)có thể được thay thế bởi while(true){for(f=j=0;j<n;j++). Hơn nữa lớp học của bạn không cần phải công khai. Vòng lặp chỉ có một hướng dẫn trong cơ thể không cần niềng răng xoăn.
Victor Stafusa

Tôi nghĩ rằng for(j=0;j<n;j++){for(k=0;k<n;k++){A[j][k]=p.nextInt();}b[j]=p.nextInt();}có thể được thay thế bởifor(j=0;j<n;b[j++]=p.nextInt())for(k=0;k<n;)A[j][k++]=p.nextInt();
Victor Stafusa

@Victor Cảm ơn, tôi đã thực hiện những thay đổi đó và những thứ khác.
Wally

while(true)có thể được thay đổi thànhfor(;;)
user12205

@ace cảm ơn - đã thay đổi điều đó và một vài điều khác và cạo 15 ký tự.
Wally

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.