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