Resolver um sistema de equações lineares


12

Escreva um programa para resolver uma série de equações lineares o mais curta possível. Ele deve resolver problemas arbitrários de número de equações. Eles podem ser inseridos da maneira que você quiser; os coeficientes da matriz aumentada são provavelmente os mais fáceis. O programa não precisa lidar com coeficientes ou números não inteiros. Nenhum caso degenerado ou inválido será testado. O programa deve gerar o valor de cada variável ou formulário de escalão de linha reduzido.

Nenhuma biblioteca de solução de equações, funções de matriz ou qualquer maneira de resolver automaticamente é permitida. Você pode simular matrizes com matrizes ou listas.

Exemplo de entrada (ou equivalente):

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

Isto representa 2x+y-z=8, -3x-y+2z=-11, -2x+y+2z=-3

Exemplo de saída (ou equivalente):

{2,3,-1}

Isto representa x=2, y=3, z=-1


2
Os coeficientes das variáveis ​​e os termos constantes podem ser separados em duas matrizes na entrada?
precisa saber é o seguinte

@ace sim, isso é bom
QWR

11
O que exatamente você está dizendo em casos degenerados? Eu acho que você está se referindo a todos esses casos: 1) Entrada malformada; 2) Coisas como 0x=0ou 0x=5; 4) Casos em que o número de equações é diferente do número de variáveis; 5) Casos contraditórios como x+5y=7, x+5y=8; 6) Casos sem independência linear, como x+3y=6, 2x+6y=12. Estou certo?
22330 Victor Stafusa #

@ Victor Sim, qualquer entrada que tenha alguma ambiguidade ou que não possa ser solucionada.
QWR

E os casos que não são degenerados, mas estão mal condicionados? (Ou, em outras palavras, que tipo de giro é necessária?)
Peter Taylor

Respostas:


3

Python 169 166

Implementação

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]

Nota

Se você estiver bem com a aproximação de flutuação, poderá remover a chamada de função redonda e aumentar o golfe para 159 caracteres


9

APL, 1 caracter

Sei que não se encaixa nos requisitos (revisados), mas é bom demais para não postar:

O símbolo "dominó" (divisão ÷dentro de um retângulo) realiza a divisão matricial, portanto, pode resolver qualquer sistema de equações lineares. Você apenas precisa colocá-lo entre o vetor de termo constante e a matriz com os outros termos:

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

(se você quiser experimentá-lo no TryApl, é )


4

Javascript ( 284 181) - Método de eliminação de 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}

Teste

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

A matriz retornada combina a matriz de identidade e a solução.


Você pode salvar mais alguns caracteres.
precisa saber é o seguinte

Em vez de l=A.length;for(i=0;i<l;i++)usar for(i=0;i<l=A.length;i++).
Victor Stafusa

Em vez de for(i=l-1;i>=0;i--)usar for(i=l;--i;).
precisa saber é o seguinte

Você também pode w=A[j][i]entrar for()e pular {}.
MarcinJuraszek

Obrigado a todos, consegui mesclar etapas para a frente e para trás em uma única etapa, economizando cem caracteres e algumas de suas dicas não são mais válidas. (exceto @MarcinJuraszek dica)
Michael M.

3

Essa resposta não se encaixa mais na pergunta após a alteração da regra, pois usa uma função de matriz. *

Sage , 32

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

Entrada de amostra:

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

Saída de amostra:

(2, 3, -1)

* Indiscutivelmente, matrix()é um typecast, não uma função (a execução import types; isinstance(matrix, types.FunctionType)False). Além disso, os operadores~ e *são , não funções.


Eu atualizei as regras. O código deve lidar com um número diferente de equações e agora você não pode usar funções de matriz.
QWR

3

Java - 522 434 228 213 caracteres

Resolve verificando sistematicamente todas as n-tuplas inteiras possíveis por multiplicação direta até encontrar um que funcione.

A função assume matriz aumentada, A, vetor de solução de teste, x, e dimensão, n, como vetor de solução de entrada e saída, x. Observe que o vetor x é na verdade um maior que a dimensão para ajudar a percorrer as possíveis soluções. (Se eu declarasse as variáveis ​​A, x, n, j, k, s como variáveis ​​de instância, a função seria 31 caracteres menor - para um total de 182, mas isso parece inclinar muito as regras.)

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

Programa para teste (um pouco não-destruído):

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

O programa recebe a entrada do stdin como números inteiros separados por espaço, como segue: primeiro, a dimensão do problema, segundo, as entradas da matriz aumentada por linha.

Exemplo de execução:

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

Raspei vários caracteres seguindo o conselho de Victor sobre loops e "público", armazenando o RHS na matriz aumentada em vez de separadamente e adicionando uma entrada extra à minha solução de teste para simplificar a geração de cada nova solução de teste. O OP também disse que uma função é suficiente - não é necessário contar o programa inteiro.


while(true){f=0;for(j=0;j<n;j++)pode ser substituído por while(true){for(f=j=0;j<n;j++). Além disso, sua turma não precisa ser pública. For-loops com apenas uma instrução no corpo não precisam de chaves.
Victor Stafusa

Eu acho que isso for(j=0;j<n;j++){for(k=0;k<n;k++){A[j][k]=p.nextInt();}b[j]=p.nextInt();}pode ser substituído porfor(j=0;j<n;b[j++]=p.nextInt())for(k=0;k<n;)A[j][k++]=p.nextInt();
Victor Stafusa 2/14/14

@ Victor Obrigado, eu fiz essas e outras mudanças.
Wally

while(true)pode ser alterado parafor(;;)
user12205

@ace obrigado - mudou isso e algumas outras coisas e raspou 15 caracteres.
Wally

1

JavaScript (ES6),  152  151 bytes

Implementação da regra de 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))

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.