matematykaszkolna.pl
zadanie dla fil metody numeryczne Mariusz: fil , Mila zaproponowała abyśmy kontynuowali temat z wątku https://matematykaszkolna.pl/forum/402102.html w nowym wątku co ty na to ? Przy okazji Czy ten fragment kodu: for(i = k + 1;i <= n;i++) A[i][k] = (double)(A[i][k]/A[i][i]); for(j = k + 1;j <= n;j++) for(i = k + 1;i <= n;i++) A[i][j] −= A[i][k]*A[k][j]; Mozemy zapisac tak: for (int i = k + 1; i <= n; i++) { double r = A[i][k] / A[k][k]; for (int j = k + 1; j <= n; j++) { A[i][j] −= r * A[k][j]; } } Sprawdziłem i z twoją propozycją jest taki problem że ty nie dzielisz elementów w kolumnie poniżej głównej przekątnej przez znaleziony element główny choć algorytm tego wymaga
29 maj 10:12
fil: Mozemy, bo tamten jest zasmiecony dlugimi wiadomosciami nie na temat. Faktycznie algorytm wymaga tego, aby dzielic elementy, wiec moj sposob jest bledny. Przy okazji, algorytm mowi nam aby iterowac od k + 1 do N: czy w kodzie w warunku petli for() nie powinnismy napisac for(...; i < n;...)?
29 maj 10:19
Mariusz: Zauważ że oni indeksują macierz od jedynki a ty od zera więc dalej jest dobrze bo w swoim kodzie to uwzględniłeś że te indeksy trzeba przesunąć Dotychczas twój kod wygląda tak bool gauss(double** A, int n, int* P) { for (int k = 0; k < n − 1; k++) { double maxelement = std::fabs(A[k][k]); int maxelementindex = k; for (int i = k + 1; i < n; i++) { if (std::fabs(A[i][k]) > maxelement) { maxelement = std::fabs(A[i][k]); maxelementindex = i; } } if (maxelement == 0) return false; P[k] = maxelementindex; P[maxelementindex] = k; if (maxelementindex != k) { double* temp = A[k]; A[k] = A[maxelementindex]; A[maxelementindex] = temp; } for (int j = k + 1; j < n; j++) { double r = A[j][k] / A[k][k]; for (int x = k + 1; x < n; x++) { A[j][x] −= r * A[k][x]; } } } if (A[n − 1][n − 1] == 0) return false; return true; } Twój kod byłby dobry gdybyś w poniższym fragmencie kodu dał for (int i = k + 1; i < n; i++) { double r = A[i][k] / A[k][k]; A[i][k] = r; // Tej linijki u Ciebie brakuje for (int j = k + 1; j < n; j++) { A[i][j] −= r * A[k][j]; } } Tylko czy wtedy jest sens wprowadzać nową zmienną ? A jeśli chodzi o funkcję rozwiązującą to najpierw odtwarzasz poprawną kolejność składowych wektora reprezentującego kolumnę wyrazów wolnych a następnie przechodzisz do algorytmu podstawiania opisanego w artykule http://wazniak.mimuw.edu.pl/index.php?title=MN05 w sekcji układy z macierzą trójkątną tyle że najpierw realizujesz "Podstawienie w przód" a następnie "Podstawienie w tył"
29 maj 10:46
fil: Czesc Mariusz, niestety jeszcze nie napisalem podstawienia w przod oraz w tyl, poniewaz brak mi troche czasu. Mam nadzieje ze do godziny 20 uda mi sie podeslac gotowy kod
29 maj 13:10
fil: Tak, tak wlasciwie nie potrzebna jest tutaj zmienna r
29 maj 13:11
Mariusz: Pamiętaj że podczas rozkładu macierzy na iloczyn LU=PA dokonywałeś przestawień wierszy i dlatego zanim przystąpisz do pisania podstawienia w przód a następnie w typ musisz odtworzyć poprawną kolejność składowych wektora reprezentującego kolumnę wyrazów wolnych Do odtworzenia tej poprawnej kolejności wykorzystujesz wektor P w którym zapisywałeś pozycje elementów głównych
29 maj 14:09
fil: Patrzac do twojej implementacji, gdzie w poznizszej funkcji uzywasz tego vectora P? /* void LUsolve(double **A,int n, int *P,double *c) { int i,j; double sum; for(i = 2;i <= n;i++) { sum = 0.0; for (j = 1;j < i;j++) sum += A[i][j]*c[j]; c[i]−=sum; } c[n] = (double)(c[n]/A[n][n]); for(i = n − 1;i >= 1;i−−) { sum = 0.0; for(j = i + 1;j <= n;j++) sum += A[i][j]*c[j]; c[i] = (double)((c[i] − sum)/A[i][i]); } } */
29 maj 14:25
Mariusz: No właśnie ja tutaj nie użyłem ale aby poprawnie rozwiązywał to na początku musisz przestawić elementy vectora c używając do tego vectora P
29 maj 16:30
fil: Hmm, napisalem tak, ale nie wiem czy jest poprawnie (podstawienie w przod) void solve(double** A, int* P, double* c) { c[0] = (double)P[0] / A[0][0]; for (int i = 1; i < n − 1; i++) { double sum = 0.0; for (int j = 0; j < i − 1; j++) { sum += A[i][j] * c[j]; } c[i] = (double)(c[i] − sum) / A[i][i]; } }
30 maj 11:33
fil: W sumie podobnie do ciebie, jedyna roznica (chyba) to ze ty idziesz od konca, a ja od poczatku
30 maj 11:58
Mariusz: Ja to napisałem tak Najpierw przestawiłem elementy wektora c za pomocą wektora P a następnie napisałem obydwa podstawienia na podstawie ich pseudokodu zamieszczonego w sekcji Układy z macierzą trójkątną Wektor P zawiera pozycję elementów głównych i można za jego pomocą odtworzyć macierz permutacji a także wektora Pc , który jest twoją kolumną wyrazów wolnych W artykule masz przepis na rozwiązywanie układów równań znajdź rozkład <math>\displaystyle PA = LU</math>; rozwiąż względem <math>\displaystyle y</math> układ z macierzą górną trójkątną <math>\displaystyle Ly = Pb</math>; rozwiąż względem <math>\displaystyle x</math> układ z macierzą dolną trójkątną <math>\displaystyle Ux = y</math>; A pseudokod algorytmu podstawiania masz w sekcji "Układy z macierzą trójkątną"
30 maj 18:23
Mariusz: 30 maj 2020 11:33 Wydaje mi się że najpierw powinieneś dokonać permutacji wektora c zgodnie z wektorem P Początkowo składowe wektora c są ustawione w takiej kolejności 0,1,2,...,n−1 a po permutacji wektora c składowe wektora c powinny być ustawione w kolejności P[0],P[1],P[2],...,P[n−1] dopiero wtedy przystępujesz do podstawiania a co do twojego kodu to twoja zewnętrzna pętla wykonuje o jedną iterację mniej niż ich pętla W podstawianiu w przód idę od początku a w podstawianiu w tył idę od końca ty na razie masz podstawianie w przód
31 maj 11:36