Generowanie macierzy

0

Witam,
Zadanie, które muszę wykonać z pozoru jest trywialne i w zasadzie radzę sobie z każdym jego punktem, ale nie kiedy trzeba połączyć wszystko na raz.
Sprawa wygląda następująco. Do programu muszę wygenerować macierz symetryczną macierz kwadratową NxN. Z tym nie ma najmniejszego problemu. Następnie muszę upewnić się, że wartości w macierzy mają w jednym przypadku mają te same rzędy wielkości, a w innym rzędy wielkości odległe. Tu mam trochę problemu, bo teraz robię tak, że sprawdzam wylosowaną liczbę czy jej wartość bezwzględna jest z przedziału 1-10 po podzieleniu przez poprzednio wylosowaną liczbę. Jeżeli tak, to znaczy, że są tego samego rzędu, jeżeli nie, to losuje jeszcze raz itd. Tu problem polega na tym, że owszem, dwie najbliższe liczby będą tych samych rzędów, ale już niekoniecznie inne w generowanej macierzy. Największy problem sprawia mi połączenie losowania liczb tych samych/odległych rzędów wraz z kolejnym punktem zadania, czyli generowaniem macierzy dodatnio określonej. W programie wykorzystuje rozkład Choleskiego, sprawdzając, czy user image jest większy od zera.
Podsumowując generowana macierz musi być:

  • symetryczna (nie ma problemu)
  • dodatnio określona (jest problem)
  • posiadać równe/różne rzędy wielkości (jest problem)
  • zawierać liczby rzeczywiste, całkowite, ujemne i nieujemne (nie ma problemu)

Pytanie zatem jak połączyć wszystkie te elementy i wygenerować ową macierz. Nie chodzi mi wcale o algorytm, tylko jakieś kolejne kroki, jak to mniej więcej ma wyglądać. Będę bardzo wdzięczny. Dziękuje.

0

Myślicie, że takie coś jest ok? (dla rzędów odległych)

function losuj(n : Integer) : matrix;
var
i, j, k: Integer;
macierz : matrix;
temp, suma: Extended;
begin
  SetLength(macierz, n+1, n+2);
  Randomize();

  for i:=1 to n do
  begin
    for j:=i to n+1 do
    begin
    if j = n+1 then
      while macierz[i][j] <= 0 do
        macierz[i][j] := random(1000)/10
    else
      macierz[i][j] := -1;
    end;
  end;

  for i:=1 to n do
  begin
    suma := 0;
    for j:=1 to i do
    begin
      while macierz[i][j] <= 0 do
      begin
        macierz[i][j] := random(1000)/10;
        temp := random(100);
        macierz[i][j] := macierz[i][j] * temp;
        if macierz[i][i] <= 0 then
        begin
          while macierz[i][i] = 0 do
          begin
            macierz[i][i] := random(1000)/10;
          end;
        end;
      end;
      if i > 1 then
      begin
        for k:=1 to i-1 do
        begin
          suma := suma + power(macierz[i][k],2);
        end;
        while (sqr(macierz[i][i]-suma))<=0 do
        begin
          macierz[i][i] := random(1000)/10;
        end;
      end;
    end;
  end;

  for i:=1 to n-1 do
  begin
    for j:=i+1 to n do
    begin
      macierz[i][j] := macierz[j][i];
    end;
  end;

  Result := macierz;
end;
0
Loko napisał(a)

Myślicie, że takie coś jest ok? (dla rzędów odległych)

...
        macierz[i][j] := macierz[i][j] * temp; // tu powinno być - zamiast * (żeby czasami ujemna liczba się pojawiła)
0

Z powyższym problemem już sobie poradziłem. Teraz mam kolejny, tylko prosiłbym o jakiś odzew ;)
Otóż badam 3 algorytmy rozwiązywania układów równań liniowych: Gaussa bez wyboru elementu podstawowego, z pełnym wyborem elementu podstawowego i metodę Jacobiego (iteracyjna). Oto jakie wyniki otrzymuję dla losowych liczb:

Metoda Gaussa bez wyboru elementu podstawowego:
x[1]=
1,033560328949244E+0000

x[2]=
-1,534213654960321E-0003

x[3]=
-2,883601055257695E-0007

x[4]=
-1,568095095313095E-0007

Metoda Gaussa z pelnym wyborem elementu podstawowego:
x[1]=
3,753231244925910E-0009

x[2]=
3,900409362544491E-0009

x[3]=
9,550183292753239E-0005

x[4]=
-1,225537594121185E-0008

Iteracyjna metoda Jacobiego:
x[1]=
1,033544563250626E+0000

x[2]=
-1,534190291827654E-0003

x[3]=
-2,883610800672860E-0007

x[4]=
-1,568202377991280E-0007

Jak widać metoda z pełnym wyborem elementu podstawowego, która powinna być najdokładniejsza znacznie odbiega wynikami od reszty. Sama procedura obliczania x-ów jest ok. Wydaje mi się, że wszystko co złe, znajduje się w funkcji przekształcania wylosowanej macierzy na macierz górnotrójkątną. Może mi ktoś pomóc?

 function macierzU2(n : Integer; macierz : matrix; out zamiana : swaptable; out osobliwa : boolean) : matrix;
var
i, j, k, wiersz, kolumna : Integer;
temp, max : Extended;
a : matrix;
b  : vector;
temp2 : Integer;
begin
  a := wyciagnijA(n, macierz);
  b := wyciagnijB(n, macierz);
  setLength(zamiana, n+1);
  osobliwa := false;

  for i:= 1 to n do
    zamiana[i] := i;

  for i:=1 to n do
  begin
    max := a[i,i];
    wiersz := i;
    kolumna := i;
    for j:=i to n do
    begin
      for k:=i to n do
      begin
        if abs(a[j,k]) > max then
        begin
          max := abs(a[j,k]);
          wiersz := j;
          kolumna := k;
        end;
      end;
    end;

    for j:=i+1 to n do
    begin
      temp := a[i,j];
      a[i,j] := a[wiersz,j];
      a[wiersz,j] := temp;
    end;
    for j:=i+1 to n do
    begin
      temp := a[j,i];
      a[j,i] := a[j,kolumna];
      a[j,kolumna] := temp;

      temp := b[i];
      b[i] := b[wiersz];
      b[wiersz] := temp;
    end;

    temp2 := zamiana[i];
    zamiana[i] := zamiana[kolumna];
    zamiana[kolumna] := temp2;

    for j:=i+1 to n do
    begin
      temp:=a[j,i]/a[i,i];
      for k:=i to n do
      begin
        a[j,k]:=a[j,k]-temp*a[i,k];
      end; 
      b[j]:=b[j]-temp*b[i];
    end;
  end;

  for i:=1 to n do
  begin
    if a[i,i] = 0 then
    begin
      osobliwa := true;
    end;
  end;

  a := Scal(n,a,b);

  Result := a;
end;
0

Może mi ktoś pomóc?

Nie ktoś, tylko coś: DEBUGGER. Dodatkowo twój umysł.

Nie zauważyłeś że nikt nie odpisuje? Nie wiesz dlaczego? To ja ci pomogę: Nikomu nie chce się analizować twojego długiego algorytmu i kombinować jak to poprawić. Więc może zamiast naiwnie pytać, po prostu naucz się używać debuggera, zaparz sobie herbatę i walcz z kodem. (Tak, każdy normalny programista tak robi)
Pytania o algorytmy (zwłaszcza te niebanalne) to prosta droga aby nie otrzymać odpowiedzi (lub otrzymać zupełnie złe), więc nie rozumiem czemu o nie pytacie...

1

A jak niby w tym przypadku ma mi pomóc debugger? Kod analizowałem już wiele razy i nie znalazłem rozwiązania. Internet też mi wiele nie pomógł. Dlatego pytam. Podobno kto pyta nie błądzi... Jak nie odpowiesz Ty, to może w końcu kto inny. Nie widzę sensu pisania zbędnych komentarzy.
Ja napisałem pytanie i jeżeli nie dostanę odpowiedzi to trudno, ale spróbować moim zdaniem warto.

0

A jak niby w tym przypadku ma mi pomóc debugger? Kod analizowałem już wiele razy i nie znalazłem rozwiązania.

Jeżeli kod nie działa mimo usilnych prób to usunąłbym go i napisał jeszcze raz. Wbrew pozorom często działa.

A debugger może pomóc, bo możesz wykryć niezgodność działania do algorytmu lub ewentualną głupawość algorytmu, czyż nie? A jeżeli algorytm jest zły, to bym zapytał gdzieś, gdzie tłucze się algorytmy, to bym miał większą szansę na otrzymanie odpowiedzi. Ale widać według ciebie jest to bezsensowne, tak samo jak używanie debuggera. Najlepiej po prostu zaspam wszelkie fora tym pytaniem, 'może gdzieś odpowiedzą'... Tylko problem w tym że więcej czasu zmarnujesz na pytanie, odpowiadanie (np. takim użyszkodnikom jak 123) i czekanie niż zużyłbyś na znalezienie odpowiedzi samemu.

Internet też mi wiele nie pomógł. Dlatego pytam. Podobno kto pyta nie błądzi...

Kto pyta wielbłądzi...
Po prostu stwierdziłem że masz wyjątkowo małe szanse na odpowiedź. Nie moja wina że tak jest. A takie pytanie według mnie jest stratą czasu. Ja bym raczej szukał miejsca gdzie mam szansę na odpowiedź. To tak jakbym nagle zaczął tutaj wrzucać moje pytania o dajmy na przykład, 'Dll injection w kontekście pauzowania procesu'. Domyślam się że nie dostałbym żadnej odpowiedzi, a jeżeli bym jakąś dostał, na pewno by nie odpowiadała na moje pytanie. Dlatego generalnie pytam na paru innych zaufanych stronach, gdzie są prawdziwi eksperci (nie żebym nie doceniał tutejszych, ale cóż..).

P.S. Oho, widzę niepopularna opinia więc będę minusowany. Życie...

1
-pB_No- napisał(a):

A jak niby w tym przypadku ma mi pomóc debugger? Kod analizowałem już wiele razy i nie znalazłem rozwiązania.

Jeżeli kod nie działa mimo usilnych prób to usunąłbym go i napisał jeszcze raz. Wbrew pozorom często działa.

A debugger może pomóc, bo możesz wykryć niezgodność działania do algorytmu lub ewentualną głupawość algorytmu, czyż nie?

Moja wina, bo nie napisałem, że algorytm działa dla liczb całkowitych... nawet dla macierzy 3x3 daje rade. Problem zaczyna się od 4x4 i w górę. Pisałem kilka razy go od nowa. Nie napisałbym na forum skoro uważałbym to za stratę czasu. Poważnie siedzę nad tym trochę i już nie mam pomysłów.

-pB_No- napisał(a):

A jeżeli algorytm jest zły, to bym zapytał gdzieś, gdzie tłucze się algorytmy, to bym miał większą szansę na otrzymanie odpowiedzi.

Myślałem, że to jest takie miejsce.

-pB_No- napisał(a):

Najlepiej po prostu zaspam wszelkie fora tym pytaniem, 'może gdzieś odpowiedzą'...

Napisałem tylko tu, bo zazwyczaj trafiał się ktoś życzliwy z podpowiedzią. Może faktycznie, gdzieś odpowiedź dostałbym szybciej, ale faktycznie nie mam czasu szukać forów, gdzie porusza się takie kwestie. To nie jedyne zadanie, które muszę wykonać.

0
  1. random(1000)/10 zwraca liczby rzeczywiste a nie całkowite. Czy tak właśnie ma być?
  2. podczas obliczania suma:= suma+ power(macierz[i][k],2) dla liczby rzeczywistej będzie ci narastał błąd związany z precyzją. Musisz użyć odpowiedniej precyzji np. przytnij liczbę do ósmego miejsca po przecinku przykładowo uses math funkcja roundto
0
maszynaz napisał(a)
  1. random(1000)/10 zwraca liczby rzeczywiste a nie całkowite. Czy tak właśnie ma być?
  2. Funkcja power(macierz[i][k],2) nawet dla liczby rzeczywistej wyliczy ci wynik z błędem, musisz użyć odpowiedniej precyzji np. przytnij liczbę Trunciem do ósmego miejsca po przecinku przykładowo.

Tak, mają być liczby rzeczywiste. Co do błędu, to właśnie zadanie polega na porównaniu błędu obliczeń stosując poszczególny algorytm.

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