Rozwiązywanie układu równań liniowych metodą eliminacji Gaussa

0

Cześć. Jestem studentem na pierwszym semestrze informatyki i potrzebuje pomocy z programem, a dokładnie ostatnią funkcją.
Moje polecenie brzmi:
Napisać program rozwiązywania układu równań liniowych (co najwyżej 20) metodą eliminacji Gaussa przy założeniu, że macierz układu nie jest osobliwa.
Musi to być zrobione na strukturach, które zrobiłem i brakuje mi tylko funkcji z obliczaniem macierzy, próbowałem na różne sposoby ale nie mam pojęcia jak to zrobic. Prosiłbym o pomoc gdyż zależy to od mojego zaliczenia pierwszego semestru :/
Chodzi o język C i w programie CodeBlocks programuje.

#include <stdlib.h>
#include <stdio.h>
#define MAX_ILOSC_ROWNAN 20
#include <math.h>
//Napisać program rozwiązywania układu równań liniowych (co najwyżej 20) metodą eliminacji Gaussa przy założeniu, że macierz układu nie jest osobliwa.
struct Rownanie {
    int liczba_niewiadomych;
    float wspolczynniki[MAX_ILOSC_ROWNAN];
    float wyraz_wolny;
};
struct Rownania {
    struct Rownanie rownania[MAX_ILOSC_ROWNAN];
    int liczba_rownan;
};
void Wczytaj_rownanie(int liczba_niewiadomych, struct Rownanie* rownanie)
{
    int n, i;
    for (n = 0; n < liczba_niewiadomych; n++) {
        printf("Wspolczynnik %d: ", n);
        scanf("%f", &(rownanie->wspolczynniki[n]));
    }
    rownanie->liczba_niewiadomych = liczba_niewiadomych;
    printf("Wyraz wolny : ");
    scanf("%f", &rownanie->wyraz_wolny);
}

void Wczytaj_rownania(struct Rownania* rownania)
{
    printf("Liczba rownan: ");
    scanf("%d", &(rownania->liczba_rownan));
    for (int i = 0; i < rownania->liczba_rownan; ++i)
        Wczytaj_rownanie((rownania->liczba_rownan), &(rownania->rownania[i]));
}

void gauss(struct Rownania* rownania)
{

    int n, i, j, k;
    double m, s;
    for (i = 0; i < rownania->liczba_rownan; i++) {
        for (j = i + 1; j < rownania->liczba_rownan; j++) {
            if (abs(rownania->rownania[i].wspolczynniki[j] < 0))
                m = -rownania->rownania[i].wspolczynniki[j] / rownania->rownania[i].wspolczynniki[j];
            for (k = i + 1; k <= n; k++)
                rownania->liczba_rownan[j][k] += m * rownania->liczba_rownan[i][k];
        }
    }

    for (i = n - 1; i >= 0; i--) {
        s = AB[i][n];
        for (j = n - 1; j >= i + 1; j--)
            s -= AB[i][j] * X[j];
        if (abs(AB[i][i]) < 0)
            X[i] = s / AB[i][i];
    }
}
* /

    int main()
{
    struct Rownania rownania;
    Wczytaj_rownania(&rownania);
    return 0;
}
0

Tutaj Masz zaimplementowanego Gaussa, w Javie, wystarczy przepisać: https://introcs.cs.princeton.edu/java/95linear/GaussianElimination.java.html

0

Tylko własnie problem jest taki że zrobiłem gaussa wcześniej normalnie to było git i działało, tylko musze zrobić to za pomocą struktur i tu już sie pogubiłem :/

0

Teraz patrzę, rzeczywiście. Żeby zaimplementować Gaussa i nie osiwieć:) Musisz jakoś z tych struktur wyciągnąć macierz układu i wyrazy wolne.

0

No właśnie w tym problem ze nie potrafie tego zrobić a od tego zależą moje dalsze losy na studiach :(

0

Masakra, upewnie sie, to musi tak byc?

0

No musze w funkcji z gaussem popodstawiac struktury z tego co mi sie wydaje zeby program na strukturach po prostu działał a nie na samych pętlach i niewiadomych

Chyba własnie o to chodzi co napisałeś wyżej :)

0

Hmmm Bracie, jeśli teścią zadania jest:
Napisać program rozwiązywania układu równań liniowych (co najwyżej 20) metodą eliminacji Gaussa przy założeniu, że macierz układu nie jest osobliwa.
to skąd wziąłeś owe struktury?

0
AxeBlast napisał(a):

Tylko własnie problem jest taki że zrobiłem gaussa wcześniej normalnie to było git i działało, tylko musze zrobić to za pomocą struktur i tu już sie pogubiłem :/

Nie ma tu metody gausa, ale to powinna być wskazówka jak ugryźć użycie struktur.
https://wandbox.org/permlink/rwx2h03eqB08XURC

0
MasterBLB napisał(a):

Hmmm Bracie, jeśli teścią zadania jest:
Napisać program rozwiązywania układu równań liniowych (co najwyżej 20) metodą eliminacji Gaussa przy założeniu, że macierz układu nie jest osobliwa.
to skąd wziąłeś owe struktury?

Bo ogólnie to jest projekt sprawdzający struktury i mówił nam wykładowca na zajęciach ze koniecznie z nimi musi byc.

0
MarekR22 napisał(a):
AxeBlast napisał(a):

Tylko własnie problem jest taki że zrobiłem gaussa wcześniej normalnie to było git i działało, tylko musze zrobić to za pomocą struktur i tu już sie pogubiłem :/

Nie ma tu metody gausa, ale to powinna być wskazówka jak ugryźć użycie struktur.
https://wandbox.org/permlink/rwx2h03eqB08XURC

to jest na strukturach zrobione?

0

Ja bym to "zhakował". Mając strukturę Rownania czyli tablicę równań, odtworzyłbym z niej macierz układu, dla każdego elementu struktury (każdego równania):
liczba_niewiadomych, jak również MAX_ILOSC_ROWNAN to będzie rozmiar n kwadratowej macierzy układu;
tablica wspolczynniki, to pierwszy (a następne to kolejne) wiersz macierzy;
wyraz_wolny to pierwszy element wektora wyrazów wolnych (i następne).
Czyli, w funkcji Gauss, Przypisujesz w pętlach odpowiednie elementy, do zadeklarowancych na stosie macierzy i wektora (wyrazów wolnych), po czym Rozwiązujesz metodą Gaussa i Zwracasz wynik.

0

No właśnie coś w tym stylu musze zrobić tylko próbowałem to przypasowywać i nie może mi wyjść to dobrze :/
W tych pętlach musze zamiast tych zmiennych i j k, i innych wstawiac nazwy tych struktur

0

Rozwijając przykład, który ci dałem:

void _MMatrixDoubleSubstractRowWithFactor(MMatrixDoubleRef m, double factor, int toSubstract, int substractFrom, int firstColumn)
{
    // TODO: 
    ....
}

void _MMatrixDoubleGaussLinearSolution(MMatrixDoubleRef a, MMatrixDoubleRef x, MMatrixDoubleRef v)
{
    for (int i=0; i < a->rowCount; ++i) {
        // TODO: eliminacja Gaussa
        .....
    }
}

MMatrixDoubleRef MMatrixDoubleCreateLinearSolution(MMatrixDoubleRef a, MMatrixDoubleRef v)
{
    if (a->columnCount != v->rowCount) return NULL;
    if (v->columnCount != 1) return NULL; // dla uproszczenia, warunek nie jest konieczny
    MMatrixDoubleRef aDup = MMatrixDoubleCreateClone(a);
    MMatrixDoubleRef vDup = MMatrixDoubleCreateClone(v);
    MMatrixDoubleRef x = MMatrixDoubleCreate(v->rowCount, v->columnCount);

    _MMatrixDoubleGaussLinearSolution(aDup, x, vDup);

    MMatrixDoubleFree(vDup);
    MMatrixDoubleFree(aDup);

    return x;
}
0

Jak wróce do domu to spróbuje cos takiego zrobić i zobacze jak to wyjdzie :) dzięki za pomoc

0

Niewiele z tego rozumiem i nie wychodzi mi nic :/ ktoś pomoże jeszcze? Jutro mam ostateczny termin już

0
#include <stdlib.h>
#include <stdio.h>
#define MAX_ILOSC_ROWNAN 20
#include <math.h>
//Napisaæ program rozwi¹zywania uk³adu równañ liniowych (co najwy¿ej 20) metod¹ eliminacji Gaussa przy za³o¿eniu, ¿e macierz uk³adu nie jest osobliwa.
struct Rownanie
{
    int liczba_niewiadomych;
    float wspolczynniki[MAX_ILOSC_ROWNAN];
    float wyraz_wolny;
};
struct Rownania
{
    struct Rownanie rownania[MAX_ILOSC_ROWNAN];
    int liczba_rownan;
};
void Wczytaj_rownanie(int liczba_niewiadomych, struct Rownanie *rownanie)
{
    int n;
    for(n=0;n<liczba_niewiadomych;n++)
    {
        printf("Wspolczynnik %d: ", n);
        scanf("%f", & (rownanie->wspolczynniki[n]));
    }
    rownanie->liczba_niewiadomych=liczba_niewiadomych;
    printf("Wyraz wolny : ");
    scanf("%f", &rownanie->wyraz_wolny);
}

void Wczytaj_rownania(struct Rownania *rownania)
{
    int i;
    printf("Liczba rownan: ");
    scanf("%d", & (rownania->liczba_rownan));
    for( i = 0; i < rownania->liczba_rownan; ++i )
        Wczytaj_rownanie((rownania->liczba_rownan),& (rownania->rownania[i]) );
}

/*
Funkcja zeruje współczynniki o indeksach >=i w równaniu o indeksie j używając równania o indeksie i
*/
void wyzerujWspolczynniki( struct Rownania *rownania, int i, int j )
{
    int k,w,n;
    w=rownania->rownania[j].wspolczynniki[i];
    for(k=i; i<=n; i++)
        rownania[j][k]-=w.rownania[i][k];
}

void gauss(struct Rownania *rownania)
{

    int i,j,k;
    double m,s;
    for(i = 0; i < rownania->liczba_rownan-1; i++)
    {
        for(j = i + 1; j < rownania->liczba_rownan; j++)
        {

            wyzerujWspolczynniki( rownania, i, j );
            if(abs(rownania->rownania[i].wspolczynniki[j]< 0))
            m = -rownania->rownania[i].wspolczynniki[j] / rownania->rownania[i].wspolczynniki[j];
            for(k = i + 1; k <= rownania->liczba_rownan; k++)
                rownania->rownania[j].wspolczynniki[k] += m * rownania->rownania[i].wspolczynniki[k];
    }
  }

  /*  for(i = rownania->liczba_rownan - 1; i >= 0; i--)
  {
    s = rownania->liczba_rownan[i][liczba_rownan];
    for(j = liczba_rownan - 1; j >= i + 1; j--)
      s -= rownania->liczba_rownan[i][j] * X[j];
    if(abs(rownania->liczba_rownan[i][i]) < 0)
    X[i] = s / rownania->liczba_rownan[i][i];
  }*/
}


int main()
{
    struct Rownania rownania;
    Wczytaj_rownania(&rownania);
    return 0;
}


Tak to wygląda i nie wiem jak dalej, pogubiłem sie :/ ostatnie 2 funkcje są źle zrobione tylko je musze poprawić ale nwm jak :vv

0

twoje wyzerujWspolczynniki mniej więcej odpowiada mojemu _MMatrixDoubleSubstractRowWithFactor.
U mnie masz wartość factor, a u ciebie nie ma nic analogicznego. Mało tego ten kod nie ma prawa się kompilować! Gdzie jest dzielenie?

0

Ok, przede wszystkim masz problem kształtu Twojej macierzy:

    float wspolczynniki[MAX_ILOSC_ROWNAN];

Współczynników jest tyle co niewiadomych, a nie tyle co równań.

0

Natomiast w kwestii samego problemu, należy równanie macierzowe jest tak naprawdę układem równań wektorowych (i operacje, które przeprowadzasz są operacjami na wierszach). Zaimplementuj funkcje dodające równania i mnożące przez stałe. Później dopiero operuj na tym, czyli bierzesz pierwsze równanie, dzielisz przez pierwszy element cały wiersz (razem z czynnikiem stałym), i za jego pomocą zerujesz wszystko w dół.Taka metoda ma problem taki, że istnieją nieosobliwe macierze, dla których mimo wszystko napotkasz dzielenie przez zero. By radzić sobie z tym, istnieje metoda zwana eliminacją Gausa z częściowym (lub całkowitym) wyborem elementu głównego. Wyszukaj te terminy, znajdziesz proste instrukcje (a i metody nie są trudne w implementacji, szczególnie ten częściowy wybór).

0

Dla Ciebie nie są trudne w implementacji te metody, dla mnie są i to już długo się z tym męcze :/ mógłbyś pomóc z samą funkcją która zeruje gaussa? a reszte jakoś dam rade zrobić

0

A masz te funkcje, które dodają równania i mnożą przez stałe?

0

Mam tylko to co wysłałem w tym kodzie :/ i wykładowca mi mówił żebym zrobil chociaz te 2 ostatnie funkcje czyli gaussa i zerowanie współczynników

0
AxeBlast napisał(a):

Mam tylko to co wysłałem w tym kodzie :/ i wykładowca mi mówił żebym zrobil chociaz te 2 ostatnie funkcje czyli gaussa i zerowanie współczynników

To była moja sugestia, żebyś je zaprogramował.

0

Krok pierwszy policz współczynnik przez który musisz przemnożyć wiersz przed jego odjęciem (współczynnik jest inny dla każdej pary wierszy).
Jak zrobisz to, to potem wykonanie tego odejmowania to naprawdę żaden problem.

0

Krokowo to wszystko wiem jak robić tylko nie potrafie tego napisac w pseudokodzie :/

1

Jak się pisze małymi funkcjami to wygląda to dużo prościej:
https://wandbox.org/permlink/ktsqg27KDrddnreY

static
void _MMatrixDoubleGaussElimination(MMatrixDoubleRef a,  MMatrixDoubleRef v)
{
    int i, j;
    for (i = 0; i < a->rowCount; ++i) {
        for (j = i + 1; j < a->rowCount; ++j) {
            double factor = MMatrixDoubleGet(a, j, i) / MMatrixDoubleGet(a, i, i);
            _MMatrixDoubleSubstractRowWithFactor(a, factor, i, j, i + 1);
            _MMatrixDoubleSubstractRowWithFactor(v, factor, i, j, 0);
        }
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1