Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Optymalizacja na podstawie zestawu danych

24 Gru 2012 11:33 2445 20
  • Poziom 10  
    Problem trochę nietypowy - prosty dla mnie od strony matematycznej, ale nie wiem jak to "skleić" w makrze VBA (pisania makr się dopiero uczę).

    W załączonym pliku są 4 najważniejsze kolumny (X, przedziały X, Y, Z). Celem jest dobrać tak wartości X (jest ich 9), aby po przemnożeniu przez wartości Y otrzymać iloczyny najbardziej zbliżone do siebie. Iloczyny będą zapisywane jako wartości Z (X*Y=Z).

    Główne założenia "optymalizacji":
    - wartości Z mają być jak najbardziej zbliżone do siebie (być może użyć trzeba metody "różnicy kwadratów dwóch liczb"), jednocześnie postarać się aby same wartości Z były jak największe,
    - liczby X są zmiennymi, a ich wartości mają mieścić się w podanych przedziałach (przedziały są domknięte)
    - wartości X mogą zmieniać się co 0,25 (step=0,25) w podanych przedziałach (więc pewnie nie obędzie sie bez rozpisywania wszystkich możliwych wartości dla każdej zmiennej X - to jest główny problem przy tak dużej liczbie kombinacji),
    - suma wszystkich wartości X musi być równa 34,
    - wartości Y są stałe (moje dane pomiarowe).

    Przykładowo wstawiłem już w tabeli jakies wartości X, które spełniają opisywane warunki oraz w załączniku kawałek kodu VBA jaki sam do tej pory "skleciłem".

    Wielkie dzięki za zainteresowanie i naprowadzenie na dobry trop :-D

    Optymalizacja na podstawie zestawu danych
  • Poziom 40  
    Owszem stowrzyłeś "coś" w VBA ale przemyślałeś co ten kod właściwie robi?
    Każda pętla po kolei robi swoje do końca co daje efekt że przypisuje każdemu X ostatnią możliwą wartość.

    Tu, jeżeli już, trzeba zapętlić pętle w pętli (dla 9 pętli po kolei)

    Wbrew pozorom ilość kombinacji wyniku 34 z iksów to najmniejszy problem (to tylko kwestia klasy komputera i czasu wykonania procedury).

    Piszesz że od strony matematycznej wiesz jak to zrobić więc jakbyś mógł zasugeruj jak od strony matematycznej ustalić że 9 liczb "Z" są "najbardziej zbliżone do siebie" i jednocześnie jak największe.

    Dawno miałem statystykę i w chwili obecnej nie za bardzo pamiętam co można do tego zastosować.
    Może odchylenie średnie (lub standardowe) z dziewięciu liczb i by było jak najmniejsze... ale nie wiem.

    Tzn.:

    Poprzez "pętle w pętlach" generuje różne kombinacje dziewięciu iksów (x)

    Sprawdzam jednocześnie czy suma iksów jest 34 i x2 jest połową x3.
    Jeżeli spełnia warunek zapisuje kombinację do jakiejś tabeli i dalej.

    Jak już mam wszystkie kombinacje to tworze pod każdą zbiór wartości Z (to można robić jednocześnie w poprzednim kroku) i teraz:

    Czy najpierw sprawdzam czy wartości Z są największe (suma wszystkich Z największa z wszystkich kombinacji - wtedy mam pewność że są największe) czy może najpierw sprawdzam czy wartości są jak najbliższe sobie (najmniejsze odchylenie średnie/standardowe)

    A może jeszcze inaczej?

    Że tak wesoło podsumuje:
    :) Zasugeruj coś "matematyku" :) bo ja na tą chwilę przedświąteczną za mały jestem, ale jak już będzie jasne od strony matematycznej to kod VBA moment się zrobi.
  • Poziom 10  
    pętle zagnieżdżone - dobra, spróbuje tak jak mówisz

    kombinacji X jest mnóstwo (ok. 1,5 miliarda - liczę tak w pamięci w przybliżeniu). Jak tylko później zapisywać te wartości X, które spełniają warunek sumy=34?
    Tych "dobrych" kombinacji będzie pewnie z kilkadziesiąt milionów (jedna z nich jest już podana w załączniku) i jakoś to trzeba zebrać (tabela?).

    Podejrzewam, że tabeli o przykładowych wymiarach 9x50000000 (50 milionów kombinacji dla 9 wyliczonych zmiennych) nie przetrawi, jeśli jeszcze później ma ze sobą to porównać metoda odchylenia standardowego (lub każdą inną, podobną).


    Dobra, jest coś z pętlami zagnieżdżonymi w załączniku VBA_2 poniżej mojego autorstwa. Miało to "coś" wpisywać wyniki prawidłowych X (czyli z sumą całkowitą 34) do komórek tabeli, ale ilość komórek jest wpisana z palca - z naszego założenia wynika, że nie znamy przecież ilości kombinacji na początku.

    Coś mi się obiło o uszy, że można też używac "Range" - może coś w tę stronę?
  • Poziom 10  
    Właściwie do zakończenia (tak mi się wydaje) brakuje 2 rzeczy - wpisanie wyłapanych kombinacji do tabeli (będzie miała 9 wierszy i "n" kolumn, gdzie "n" to liczba kombinacji liczona w milionach), druga sprawa to sposób porównania każdej z kolumn względem pozostałych.
    To drugie dotyczy wartości wynikowej Z, bo cały kod jest pisany do odszukania tych wartości.
    Szukanie zmiennych X jest potrzebne do tego, aby suma w kolumnie X byla równa 34 (dla podanych przedziałów) i oczywiście do późniejszego przemnożenia przez Y (żeby dostać wartość Z).
  • Użytkownik usunął konto  
  • Poziom 10  
    U mnie pokazuje tylko wyniki z ostatniego message boxa dla x1, x2, x3, x4, x5, x6, x7, x8, x9, ale dzięki za to co jest.
  • Pomocny post
    Użytkownik usunął konto  
  • Poziom 10  
    Dobra, dzięki
  • Poziom 40  
    Jakby było tylko 236221 wierszy/kombinacji spełniających warunek to nie było by źle.
    U mnie wychodzi 2.549.518 takich kombinacji i jak już wspomniano zaczyna się kłopot z ograniczeniami VBA.
    Samo generowanie tabeli z kombinacjami trwa ok 10 minut (Pentium IV 2,4 MHz, 1,5 GB)
    Jak spróbowałem metody kolegi e-mega z tworzeniem pliku zamiast tabeli. Zajęło mi to 40 minut a plik ma 82 Mb (statystyka worda też pokazała 2.549.518 wierszy [powinna pokazać o 1 więcej bo jest jeszcze nagłówek - ale już nie będę się spierał z wordem])

    Poniżej mój kod (bez sprawdzeń czy dane wejściowe są poprawne)

    Wyrzuca zbiór iksów o największej średniej i najmniejszym odchyleniu standardowym Dla danych Z.

    ZAZNACZAM na moim sprzęcie trwa to ok 15 minut
    Code:
    Sub Wybierz()
    

    Dim poczatek(1 To 9) As Integer, koniec(1 To 9) As Integer, x As Integer
    Dim zakres As String, wartosc() As String, tekst1 As String, tekst2 As String
    Dim krok As Single, x1 As Single, x2 As Single, x3 As Single, x4 As Single, x5 As Single, x6 As Single, x7 As Single, x8 As Single, x9 As Single
    Dim tablicaX() As Single, tablicaZ() As Single, tablicaY(1 To 9) As Single
    Dim i As Long, k As Long, kom1 As Long, kom2 As Long



    start1 = Time


    krok = 0.25


    For x = 1 To 9
        zakres = Cells(2 + x, 3)
        zakres = Replace(zakres, "<", "")
        zakres = Replace(zakres, ">", "")
        wartosc = Split(zakres, ";", 2)
        poczatek(x) = Val(wartosc(0))
        koniec(x) = Val(wartosc(1))
        tablicaY(x) = Cells(2 + x, 4)
    Next x




    ReDim tablicaX(1 To 4000000, 1 To 9)

    ReDim tablicaZ(1 To 4000000, 1 To 11)


    i = 0

    For x1 = poczatek(1) To koniec(1) Step krok
     For x2 = poczatek(2) To koniec(2) Step krok
      For x3 = poczatek(3) To koniec(3) Step krok
       For x4 = poczatek(4) To koniec(4) Step krok
        For x5 = poczatek(5) To koniec(5) Step krok
         For x6 = poczatek(6) To koniec(6) Step krok
          For x7 = poczatek(7) To koniec(7) Step krok
           For x8 = poczatek(8) To koniec(8) Step krok
            For x9 = poczatek(9) To koniec(9) Step krok
           
                If x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 = 34 And x2 * 2 = x3 Then
                    i = i + 1
                   
                    tablicaX(i, 1) = x1
                    tablicaX(i, 2) = x2
                    tablicaX(i, 3) = x3
                    tablicaX(i, 4) = x4
                    tablicaX(i, 5) = x5
                    tablicaX(i, 6) = x6
                    tablicaX(i, 7) = x7
                    tablicaX(i, 8) = x8
                    tablicaX(i, 9) = x9
                   
                    tablicaZ(i, 1) = x1 * tablicaY(1)
                    tablicaZ(i, 2) = x2 * tablicaY(2)
                    tablicaZ(i, 3) = x3 * tablicaY(3)
                    tablicaZ(i, 4) = x4 * tablicaY(4)
                    tablicaZ(i, 5) = x5 * tablicaY(5)
                    tablicaZ(i, 6) = x6 * tablicaY(6)
                    tablicaZ(i, 7) = x7 * tablicaY(7)
                    tablicaZ(i, 8) = x8 * tablicaY(8)
                    tablicaZ(i, 9) = x9 * tablicaY(9)
                   
                    suma = 0
                    For x = 1 To 9
                        suma = suma + tablicaZ(i, x)
                    Next x
                   
                    'średnia
                    tablicaZ(i, 10) = suma / 9
                   
                    'odchylenie standardowe
                    tablicaZ(i, 11) = Application.WorksheetFunction.StDev(tablicaZ(i, 1), tablicaZ(i, 2), tablicaZ(i, 3), tablicaZ(i, 4), tablicaZ(i, 5), tablicaZ(i, 6), tablicaZ(i, 7), tablicaZ(i, 8), tablicaZ(i, 9))
                   
                End If
           
           
           
            Next x9
           Next x8
          Next x7
         Next x6
        Next x5
       Next x4
      Next x3
     Next x2
    Next x1
           



    'Maksymalna średnia
    m = 0
    For k = 1 To i
        If tablicaZ(k, 10) > m Then
            m = tablicaZ(k, 10)
            kom1 = k
        End If
    Next k

    'minimalne odchylenie standardowe

    For k = 1 To i
        If tablicaZ(k, 10) < m Then
            m = tablicaZ(k, 11)
            kom2 = k
        End If
    Next k

    For x = 1 To 9
        tekst1 = tekst1 & "x" & x & ": " & tablicaX(kom1, x) & Chr(10)
        tekst2 = tekst2 & "x" & x & ": " & tablicaX(kom2, x) & Chr(10)
    Next x

    stop1 = Time



    MsgBox "Zestaw X'ów dla najwięksazej średniej: " & Chr(10) & tekst1 & vbNewLine & "Zestaw X'ów dla najmniejszego odchylenia standardowego: " & Chr(10) & tekst2, vbInformation



    MsgBox "Czas: " & Format(stop1 - start1, "hh:mm:ss") & vbNewLine & "Ilość kombinacji: " & i, vbInformation


    End Sub
  • Poziom 22  
    Jeżeli warunkiem podstawowym jest suma=34, to ilość obliczeń można istotnie zredukować unikając niektórych pętli. Skoro suma wartości minimalnych z zakresów wynosi 17, a maksymalnych 43 to można wstawić PRZED ostatnimi dwiema/trzema pętlami dodatkowe warunki:
    - jeśli dotychczasowa suma + maksymalne wartości z następnych pętli nie osiągają 34, to w ogóle tam głębiej nie wchodź
    - jeśli dotychczasowa suma + minimalne wartości z następnych pętli przekraczają 34, to w ogóle tam nie wchodź

    Można też wcześniej obliczyć sumę z pierwszych pętli (wynik częściowy), żeby tego samego działania nie powtarzać setki tysięcy razy.
  • Poziom 40  
    Po wykorzystaniu pierwszej sugestii kolegi Aldrina czas wykonania procedury skrócił się z 10 minut do 1,01 minuty

    Niesamowite. :)

    Co do:
    Cytat:
    Można też wcześniej obliczyć sumę z pierwszych pętli (wynik częściowy)...

    to nie za bardzo rozumiem jakby to miało wyglądać w kodzie by było efektywne


    Poprawiony kod:
    Code:
    Sub Wybierz()
    

    Dim poczatek(1 To 9) As Integer, koniec(1 To 9) As Integer, x As Integer
    Dim zakres As String, wartosc() As String, tekst1 As String, tekst2 As String
    Dim krok As Single, x1 As Single, x2 As Single, x3 As Single, x4 As Single, x5 As Single, x6 As Single, x7 As Single, x8 As Single, x9 As Single, sum1 As Single, sum2 As Single
    Dim tablicaX() As Single, tablicaZ() As Single, tablicaY(1 To 9) As Single
    Dim i As Long, k As Long, kom1 As Long, kom2 As Long



    start1 = Time


    krok = 0.25


    For x = 1 To 9
        zakres = Cells(2 + x, 3)
        zakres = Replace(zakres, "<", "")
        zakres = Replace(zakres, ">", "")
        wartosc = Split(zakres, ";", 2)
        poczatek(x) = Val(wartosc(0))
        koniec(x) = Val(wartosc(1))
        tablicaY(x) = Cells(2 + x, 4)
    Next x




    ReDim tablicaX(1 To 4000000, 1 To 9)

    ReDim tablicaZ(1 To 4000000, 1 To 11)


    i = 0

    For x1 = poczatek(1) To koniec(1) Step krok
     sum1 = x1 + koniec(2) + koniec(3) + koniec(4) + koniec(5) + koniec(6) + koniec(7) + koniec(8) + koniec(9)
     sum2 = x1 + poczatek(2) + poczatek(3) + poczatek(4) + poczatek(5) + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
     If sum1 < 34 Or sum2 > 34 Then GoTo d1
     
     For x2 = poczatek(2) To koniec(2) Step krok
      sum1 = x1 + x2 + koniec(3) + koniec(4) + koniec(5) + koniec(6) + koniec(7) + koniec(8) + koniec(9)
      sum2 = x1 + x2 + poczatek(3) + poczatek(4) + poczatek(5) + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
      If sum1 < 34 Or sum2 > 34 Then GoTo d2
     
      For x3 = poczatek(3) To koniec(3) Step krok
       sum1 = x1 + x2 + x3 + koniec(4) + koniec(5) + koniec(6) + koniec(7) + koniec(8) + koniec(9)
       sum2 = x1 + x2 + x3 + poczatek(4) + poczatek(5) + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
       If sum1 < 34 Or sum2 > 34 Or x2 * 2 <> x3 Then GoTo d3
       
       For x4 = poczatek(4) To koniec(4) Step krok
        sum1 = x1 + x2 + x3 + x4 + koniec(5) + koniec(6) + koniec(7) + koniec(8) + koniec(9)
        sum2 = x1 + x2 + x3 + x4 + poczatek(5) + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
        If sum1 < 34 Or sum2 > 34 Then GoTo d4
       
        For x5 = poczatek(5) To koniec(5) Step krok
         sum1 = x1 + x2 + x3 + x4 + x5 + koniec(6) + koniec(7) + koniec(8) + koniec(9)
         sum2 = x1 + x2 + x3 + x4 + x5 + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
         If sum1 < 34 Or sum2 > 34 Then GoTo d5
         
         For x6 = poczatek(6) To koniec(6) Step krok
          sum1 = x1 + x2 + x3 + x4 + x5 + x6 + koniec(7) + koniec(8) + koniec(9)
          sum2 = x1 + x2 + px3 + x4 + x5 + x6 + poczatek(7) + poczatek(8) + poczatek(9)
          If sum1 < 34 Or sum2 > 34 Then GoTo d6
         
          For x7 = poczatek(7) To koniec(7) Step krok
           sum1 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + koniec(8) + koniec(9)
           sum2 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + poczatek(8) + poczatek(9)
           If sum1 < 34 Or sum2 > 34 Then GoTo d7
           
           For x8 = poczatek(8) To koniec(8) Step krok
            sum1 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + koniec(9)
            sum2 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + poczatek(9)
            If sum1 < 34 Or sum2 > 34 Then GoTo d8
             
             For x9 = poczatek(9) To koniec(9) Step krok
                If x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 = 34 Then
                    i = i + 1
                   
                    tablicaX(i, 1) = x1
                    tablicaX(i, 2) = x2
                    tablicaX(i, 3) = x3
                    tablicaX(i, 4) = x4
                    tablicaX(i, 5) = x5
                    tablicaX(i, 6) = x6
                    tablicaX(i, 7) = x7
                    tablicaX(i, 8) = x8
                    tablicaX(i, 9) = x9
                   
                    tablicaZ(i, 1) = x1 * tablicaY(1)
                    tablicaZ(i, 2) = x2 * tablicaY(2)
                    tablicaZ(i, 3) = x3 * tablicaY(3)
                    tablicaZ(i, 4) = x4 * tablicaY(4)
                    tablicaZ(i, 5) = x5 * tablicaY(5)
                    tablicaZ(i, 6) = x6 * tablicaY(6)
                    tablicaZ(i, 7) = x7 * tablicaY(7)
                    tablicaZ(i, 8) = x8 * tablicaY(8)
                    tablicaZ(i, 9) = x9 * tablicaY(9)
                   
                    suma = 0
                    For x = 1 To 9
                        suma = suma + tablicaZ(i, x)
                    Next x
                   
                    'średnia
                    tablicaZ(i, 10) = suma / 9
                   
                    'odchylenie standardowe
                    tablicaZ(i, 11) = Application.WorksheetFunction.StDev(tablicaZ(i, 1), tablicaZ(i, 2), tablicaZ(i, 3), tablicaZ(i, 4), tablicaZ(i, 5), tablicaZ(i, 6), tablicaZ(i, 7), tablicaZ(i, 8), tablicaZ(i, 9))
                   
                End If
           
           
           
            Next x9
    d8:
           Next x8
    d7:
          Next x7
    d6:
         Next x6
    d5:
        Next x5
    d4:
       Next x4
    d3:
      Next x3
    d2:
     Next x2
    d1:
    Next x1
           



    'Maksymalna średnia
    m = 0
    For k = 1 To i
        If tablicaZ(k, 10) > m Then
            m = tablicaZ(k, 10)
            kom1 = k
        End If
    Next k

    'minimalne odchylenie standardowe

    For k = 1 To i
        If tablicaZ(k, 10) < m Then
            m = tablicaZ(k, 11)
            kom2 = k
        End If
    Next k

    For x = 1 To 9
        tekst1 = tekst1 & "x" & x & ": " & tablicaX(kom1, x) & Chr(10)
        tekst2 = tekst2 & "x" & x & ": " & tablicaX(kom2, x) & Chr(10)
    Next x

    stop1 = Time



    MsgBox "Zestaw X'ów dla najwięksazej średniej: " & Chr(10) & tekst1 & vbNewLine & "Zestaw X'ów dla najmniejszego odchylenia standardowego: " & Chr(10) & tekst2, vbInformation



    MsgBox "Czas: " & Format(stop1 - start1, "hh:mm:ss") & vbNewLine & "Ilość kombinacji: " & i, vbInformation


    End Sub
  • Pomocny post
    Poziom 22  
    marek003 napisał:
    czas wykonania procedury skrócił się z 10 minut do 1,01 minuty

    Aż za bardzo ;)

    marek003 napisał:

    Cytat:
    Można też wcześniej obliczyć sumę z pierwszych pętli (wynik częściowy)...

    to nie za bardzo rozumiem jakby to miało wyglądać w kodzie by było efektywne


    Myślałem o tej linii:
    Cytat:
    If x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 = 34 Then

    Ty poszedłeś po całości ;)

    Jeśli zapamiętalibyśmy sumę np. (x1 + x2 + x3 + x4 + x5) przed wejściem do x6, to dla wielu wielu pętli nie trzeba jej znowu liczyć: dodajemy "tylko" ostatnie "iksy" z najbardziej zagnieżdżonych pętli.
    ***
    Poszczególnych sum wartości minimalnych i maksymalnych dla danego poziomu nie trzeba liczyć za każdym razem - pętle głębiej położone będą mieć stałe wartości dla analizy na danym poziomie => można je więc policzyć wcześniej i zapisać w tablicy.
    Takie sprawdzanie możnaby wdrożyć niekoniecznie od pierwszej pętli/poziomu - suma wartości maksymalnych na czwartym poziomie wynosi 16; wcześniejsze są chyba zbyt małe, żeby dużo zyskać, a obliczenia trzeba wykonać.

    W sumie to i tak najważniejsze jest ominięcie (szeroko pojętych) wewnętrznych/najgłębszych pętli ;)
  • Pomocny post
    Poziom 40  
    Odbijając na chwilę od skrócenia czasu wykonania procedury.

    Zauważyłem błąd. Żle obliczał najmniejsze odchylenie standardowe - nie te zmienne były analizowane.
    Poprawiłem i dodałem do wyników by pokazywał wartości Z.

    Jak widać największa średnia nie do końca spełnia warunek by liczby były w miarę "blisko siebie"
    Natomiast najmniejsze odchylenie standardowe nie daje pewności że jest to "największy komplet"

    Code:
    Sub Wybierz()
    

    Dim poczatek(1 To 9) As Integer, koniec(1 To 9) As Integer, x As Integer
    Dim zakres As String, wartosc() As String, tekst1 As String, tekst2 As String, tekst3 As String
    Dim krok As Single, x1 As Single, x2 As Single, x3 As Single, x4 As Single, x5 As Single, x6 As Single, x7 As Single, x8 As Single, x9 As Single, sum1 As Single, sum2 As Single
    Dim tablicaX() As Single, tablicaZ() As Single, tablicaY(1 To 9) As Single
    Dim i As Long, k As Long, kom1 As Long, kom2 As Long, kom3 As Long



    start1 = Time


    krok = 0.25


    For x = 1 To 9
        zakres = Cells(2 + x, 3)
        zakres = Replace(zakres, "<", "")
        zakres = Replace(zakres, ">", "")
        wartosc = Split(zakres, ";", 2)
        poczatek(x) = Val(wartosc(0))
        koniec(x) = Val(wartosc(1))
        tablicaY(x) = Cells(2 + x, 4)
    Next x




    ReDim tablicaX(1 To 4000000, 1 To 9)

    ReDim tablicaZ(1 To 4000000, 1 To 12)


    i = 0

    For x1 = poczatek(1) To koniec(1) Step krok
     sum1 = x1 + koniec(2) + koniec(3) + koniec(4) + koniec(5) + koniec(6) + koniec(7) + koniec(8) + koniec(9)
     sum2 = x1 + poczatek(2) + poczatek(3) + poczatek(4) + poczatek(5) + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
     If sum1 < 34 Or sum2 > 34 Then GoTo d1
     
     For x2 = poczatek(2) To koniec(2) Step krok
      sum1 = x1 + x2 + koniec(3) + koniec(4) + koniec(5) + koniec(6) + koniec(7) + koniec(8) + koniec(9)
      sum2 = x1 + x2 + poczatek(3) + poczatek(4) + poczatek(5) + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
      If sum1 < 34 Or sum2 > 34 Then GoTo d2
     
      For x3 = poczatek(3) To koniec(3) Step krok
       sum1 = x1 + x2 + x3 + koniec(4) + koniec(5) + koniec(6) + koniec(7) + koniec(8) + koniec(9)
       sum2 = x1 + x2 + x3 + poczatek(4) + poczatek(5) + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
       If sum1 < 34 Or sum2 > 34 Or x2 * 2 <> x3 Then GoTo d3
       
       For x4 = poczatek(4) To koniec(4) Step krok
        sum1 = x1 + x2 + x3 + x4 + koniec(5) + koniec(6) + koniec(7) + koniec(8) + koniec(9)
        sum2 = x1 + x2 + x3 + x4 + poczatek(5) + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
        If sum1 < 34 Or sum2 > 34 Then GoTo d4
       
        For x5 = poczatek(5) To koniec(5) Step krok
         sum1 = x1 + x2 + x3 + x4 + x5 + koniec(6) + koniec(7) + koniec(8) + koniec(9)
         sum2 = x1 + x2 + x3 + x4 + x5 + poczatek(6) + poczatek(7) + poczatek(8) + poczatek(9)
         If sum1 < 34 Or sum2 > 34 Then GoTo d5
         
         For x6 = poczatek(6) To koniec(6) Step krok
          sum1 = x1 + x2 + x3 + x4 + x5 + x6 + koniec(7) + koniec(8) + koniec(9)
          sum2 = x1 + x2 + px3 + x4 + x5 + x6 + poczatek(7) + poczatek(8) + poczatek(9)
          If sum1 < 34 Or sum2 > 34 Then GoTo d6
         
          For x7 = poczatek(7) To koniec(7) Step krok
           sum1 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + koniec(8) + koniec(9)
           sum2 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + poczatek(8) + poczatek(9)
           If sum1 < 34 Or sum2 > 34 Then GoTo d7
           
           For x8 = poczatek(8) To koniec(8) Step krok
            sum1 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + koniec(9)
            sum2 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + poczatek(9)
            If sum1 < 34 Or sum2 > 34 Then GoTo d8
             
             For x9 = poczatek(9) To koniec(9) Step krok
                If x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 = 34 Then
                    i = i + 1
                   
                    tablicaX(i, 1) = x1
                    tablicaX(i, 2) = x2
                    tablicaX(i, 3) = x3
                    tablicaX(i, 4) = x4
                    tablicaX(i, 5) = x5
                    tablicaX(i, 6) = x6
                    tablicaX(i, 7) = x7
                    tablicaX(i, 8) = x8
                    tablicaX(i, 9) = x9
                   
                    tablicaZ(i, 1) = x1 * tablicaY(1)
                    tablicaZ(i, 2) = x2 * tablicaY(2)
                    tablicaZ(i, 3) = x3 * tablicaY(3)
                    tablicaZ(i, 4) = x4 * tablicaY(4)
                    tablicaZ(i, 5) = x5 * tablicaY(5)
                    tablicaZ(i, 6) = x6 * tablicaY(6)
                    tablicaZ(i, 7) = x7 * tablicaY(7)
                    tablicaZ(i, 8) = x8 * tablicaY(8)
                    tablicaZ(i, 9) = x9 * tablicaY(9)
                   
                    suma = 0
                    For x = 1 To 9
                        suma = suma + tablicaZ(i, x)
                    Next x
                   
                    'średnia
                    tablicaZ(i, 10) = suma / 9
                   
                    'odchylenie standardowe
                    tablicaZ(i, 11) = Application.WorksheetFunction.StDev(tablicaZ(i, 1), tablicaZ(i, 2), tablicaZ(i, 3), tablicaZ(i, 4), tablicaZ(i, 5), tablicaZ(i, 6), tablicaZ(i, 7), tablicaZ(i, 8), tablicaZ(i, 9))
                   
                    'suma
                    tablicaZ(i, 12) = suma
                End If
           
           
           
            Next x9
    d8:
           Next x8
    d7:
          Next x7
    d6:
         Next x6
    d5:
        Next x5
    d4:
       Next x4
    d3:
      Next x3
    d2:
     Next x2
    d1:
    Next x1
           



    'Maksymalna średnia
    m = 0
    For k = 1 To i
        If tablicaZ(k, 10) > m Then
            m = tablicaZ(k, 10)
            kom1 = k
        End If
    Next k

    'minimalne odchylenie standardowe

    m = tablicaZ(1, 11)
    For k = 1 To i
        If tablicaZ(k, 11) < m Then
            m = tablicaZ(k, 11)
            kom2 = k
        End If
    Next k

    'maksymalna suma
    m = 0
    For k = 1 To i
        If tablicaZ(k, 12) > m Then
            m = tablicaZ(k, 12)
            kom3 = k
        End If
    Next k



    For x = 1 To 9
        tekst1 = tekst1 & "x" & x & ": " & tablicaX(kom1, x) & vbTab & vbTab & "z" & x & ": " & Format(tablicaZ(kom1, x), "# ##0.00") & Chr(10)
        tekst2 = tekst2 & "x" & x & ": " & tablicaX(kom2, x) & vbTab & vbTab & "z" & x & ": " & Format(tablicaZ(kom2, x), "# ##0.00") & Chr(10)
        tekst3 = tekst3 & "x" & x & ": " & tablicaX(kom3, x) & vbTab & vbTab & "z" & x & ": " & Format(tablicaZ(kom3, x), "# ##0.00") & Chr(10)
    Next x

    stop1 = Time



    MsgBox "Zestaw X'ów dla największej średniej: " & Chr(10) & tekst1 & vbNewLine & "Zestaw X'ów dla najmniejszego odchylenia standardowego: " & Chr(10) & tekst2 & vbNewLine & "Zestaw X'ów dla największej sumy: " & Chr(10) & tekst3, vbInformation



    MsgBox "Czas: " & Format(stop1 - start1, "hh:mm:ss") & vbNewLine & "Ilość kombinacji: " & i, vbInformation


    End Sub
  • Poziom 10  
    ok, dzięki za starania

    Jeszcze takie pytanie - czy przy zwiększeniu kroku z 0,25 do 0,5 dla każdej zmiennej X, ilość obliczeń w praktyce zmniejszyłaby się 2^9 raza (około 500 razy)?


    Generalnie całe to makro VBA miałoby ułatwić pracę biurową, bo m.in. tego typu rzeczy robię na produkcji jako technolog (tyle że ręcznie dla kilkudziesięciu plików Excela z takimi tabelami). Ale widzę po ilości potrzebnego czasu na pokazanie wyniku, że bardziej będzie to przydatne w domu do "rozważań", bo sprzęt w tamtym biurze jest wolniejszy niż jakiekolwiek Pentium IV (a i ramu tam tylko 1GB). Chociaż może jak się wszystko inne wyłączy, to kilka minut może i na tamtym sprzęcie wystarczy do policzenia jednego pliku z taką tabelą.
  • Poziom 40  
    bambi7 napisał:
    Jeszcze takie pytanie - czy przy zwiększeniu kroku z 0,25 do 0,5 dla każdej zmiennej X, ilość obliczeń w praktyce zmniejszyłaby się 2^9 raza (około 500 razy)?


    Ponieważ w kodzie zastosowałem opuszczenia kolejnych obliczeń które z góry skazane są na niepowodzenie wyliczenie dokładnie ile jest obliczeń w moim kodzie należy przeprowadzić doświadczalnie.

    Ale w czystej teorii (gdyby nie było wykoluczeń i przy zakresach jak na wstępie) byłoby tak:
    W przypadku kroku 0,25 ilość wszystkich kombinacji 1.536.215.625
    a przy dodatkowym warunku 34 i x2*x=x3 ilość kombinacji wynosi 2.549.518


    W przypadku kroku co 0,5 ilość wszystkich kombinacji 13.030.875 (ok 120 razy mniej), a przy dodatkowym warunku 34 i x2*x=x3 ilość kombinacji wynosi tylko 47.666

    Ale jak zaznaczyłem w kodzie zastosowano pewne wyłączenia niepotrzebnych wyliczeń (ograniczono ilość kombinacji z góry gdy wiadomo że nie spełnią głównych warunków) więc ilośći i czas obliczeń należy sprawdzić empirycznie.

    Na początku mojego kodu jest deklaracja krok=0.25 wystarczy ją zmienić na krok= 0.5 (Tam jest kropka nie przecinek) i bedzie ci liczył wg nowych założeń.
    U mnie skraca się czas obliczeń do 3 sekund.
  • Pomocny post
    Użytkownik usunął konto  
  • Poziom 10  
    Dzięki.
    A z tym kodem źródłowym to fajnie by bylo jakbyś udostępnił.
  • Poziom 10  
    W którym pliku jest możliwość edycji kodu źródłowego? Otwieram projekt, biorę opcję "view code" dla plików, ale widzę w nich tylko parametry dotyczące interfejsu, numeru wersji pliku - generalnie wszystko poza kodem głównym.

    Mam akurat Visual Basic 2010 EE

    I co z licencją na ten projekt? Też to widzę w treści.
  • Użytkownik usunął konto