52
Algorytmy i struktury danych Wykład 4 Algorytmy i ich analiza Janusz Szwabiński Plan wykładu: Co to jest algorytm? Analiza algorytmów motywacja Cele analizy Analiza eksperymentalna Studium przypadku 3SUM

Algorytmy i struktury danychprac.im.pwr.wroc.pl/~szwabin/assets/algo/lectures/4.pdf · 2016. 10. 5. · In total: 1 Overwriting 3sum.py. In [19]:!python3 3sum.py 10 Krok 2 pomiar

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

  • Algorytmy i struktury danych

    Wykład 4  Algorytmy i ich analiza

    Janusz Szwabiński

    Plan wykładu:

    Co to jest algorytm?Analiza algorytmów  motywacjaCele analizyAnaliza eksperymentalnaStudium przypadku  3SUM

  • Co to jest algorytm?Algorytm to skończony ciąg jasno zdefiniowanych czynności, koniecznych do wykonania pewnego rodzajuzadań. Innymi słowy to przepis na rozwiązanie problemu lub osiągnięcie jakiegoś celu.

    Istnieje kilka różnych metod zapisu algorytmu. Załóżmy, że naszym zadaniem jest obliczenie funkcji

    przy założeniu, że  .

    Słowny opis algorytmu

    1. dla liczb ujemnych  , więc  ,2. dla liczb dodatnich  , więc  ,3. jeśli  , to z definicji $f(0)=0.

    Opis słowny czasami da się w prosty sposób wyrazić wzorem matematycznym:

    Lista kroków

    1. Wczytaj wartość danej  .2. Jeśli  , to  . Zakończ algorytm.3. Jeśli  , to  . Zakończ algorytm.4. Jeśli  , to  . Zakończ algorytm.

    Schemat blokowy

    Poszczególne elementy na powyższym schemacie mają następujące znaczenie:

    f(x) =x

    |x|f(0) = 0

    |x| = −x f(x) = x/(−x) = −1|x| = x f(x) = x/x = 1

    x = 0

    f(x) =⎧⎩⎨⎪⎪

    −1,0,1,

    x < 0x = 0x > 0

    xx > 0 f(x) = 1x = 0 f(x) = 0x < 0 f(x) = −1

  • Drzewo algorytmu

    Program komputerowy to nic innego jak algorytm zapisany w wybranym języku programowania. Powyższyalgorytm zapisany w Pythonie mógłby mieć postać:

  • Dlaczego warto poznać algorytmy?

    cały obszar IT opiera się na algorytmachniektóre z nich są ponadczasowe:

    Euklides z Aleksandrii zajmował się badaniem algorytmów już w IV w p.n.e.

    (Źródło: Wikipedia)

    jego algorytm wyznaczania największego wspólnego dzielnika dwóch liczb (NWD) jestznany do dziśNWD jest stosowany w algorytmie RSA  najpopularniejszym obecnie asymetrycznymalgorytmie kryptograficznym z kluczem publicznym(https://pl.wikipedia.org/wiki/Kryptografia_klucza_publicznego(https://pl.wikipedia.org/wiki/Kryptografia_klucza_publicznego))

    pozwalają rozwiązać zagadnienia, które inaczej pozostałyby nierozwiązane:problem komiwojażera, np. wyznaczenie najkrótszej trasy pozwalającej na zwiedzeniewszystkich stolic województw

    pozwalają stać się profesjonalnym programistą

    I will, in fact, claim that the difference between a bad programmer and a good one iswhether he considers his code or his data structures more important. Badprogrammers worry about the code. Good programmers worry about data structuresand their relationships. (Linus Torvalds, twórca Linuksa)

    stymulują intelektualnieprzynoszą zysk  (Źródło: http://www.marketwatch.com)

    https://pl.wikipedia.org/wiki/Kryptografia_klucza_publicznego

  • Analiza algorytmów  motywacjaCzęsto bywa tak, że ten sam algorytm zaimplementowany jest na wiele różnych sposobów. Nasuwa sięwtedy pytanie, która z implementacji jest lepsza od pozostałych. Dla przykładu porównajmy dwa programy:

    In [1]:

    def sumOfN(n): theSum = 0 for i in range(1,n+1): theSum = theSum + i

    return theSum

    print(sumOfN(10))

    In [2]:

    def foo(tom): fred = 0 for bill in range(1,tom+1): barney = bill fred = fred + barney

    return fred

    print(foo(10))

    Mimo, że na pierwszy rzut oka tego nie widać, oba robią to samo  sumują liczby od   do  , i na dodatekrobią to w ten sam sposób. Mimo to powiemy, że pierwszy program jest lepszy ze względu na czytelność.

    Ogólnie rzecz biorąc, aby dokonać porównania między programami, musimy zdefiniować odpowiedniekryteria. Oprócz czytelności mogą to być:

    liczba operacji niezbędnych do wykonania"zasobożerność"wydajnośćczas wykonania

    Analiza algorytmów zajmuje się właśnie ich porównywaniem pod względem nakładów obliczeniowychniezbędnych do uzyskania rozwiązania. Wróćmy jeszcze raz do pierwszego z powyższych programów izmodyfikujmy go tak, aby wyliczał jeszcze czas sumowania:

    1 n

    55

    55

  • In [3]:

    import time

    def sumOfN2(n): start = time.time()

    theSum = 0 for i in range(1,n+1): theSum = theSum + i

    end = time.time()

    return theSum,end-start

    Wyniki pięciu wywołań funkcji sumOfN2 dla   są następujące:

    In [4]:

    for i in range(5): print("Suma wynosi %d, czas wykonania: %10.7f sekund"%sumOfN2(10000))

    Czasy wykonania poszczególnych wywołań różnią się nieznacznie od siebie (zależą od chwilowegoobciążenia komputera), jednak rząd wielkości pozostaje ten sam. Zobaczmy, co stanie się, jeżeli zwiększymy o jeden rząd:

    In [5]:

    for i in range(5): print("Suma wynosi %d, czas wykonania: %10.7f sekund"%sumOfN2(100000))

    I znowu, czasy wykonania są dość podobne do siebie, jednak w porównaniu z poprzednim przykłademwzrosły mniej więcej dziesięciokrotnie. Dla jeszcze większego   otrzymamy:

    In [6]:

    for i in range(5): print("Suma wynosi %d, czas wykonania: %10.7f sekund"%sumOfN2(1000000))

    n = 10000

    n

    n

    Suma wynosi 50005000, czas wykonania: 0.0010314 sekundSuma wynosi 50005000, czas wykonania: 0.0009410 sekundSuma wynosi 50005000, czas wykonania: 0.0009718 sekundSuma wynosi 50005000, czas wykonania: 0.0010254 sekundSuma wynosi 50005000, czas wykonania: 0.0009537 sekund

    Suma wynosi 5000050000, czas wykonania: 0.0113173 sekundSuma wynosi 5000050000, czas wykonania: 0.0105736 sekundSuma wynosi 5000050000, czas wykonania: 0.0092735 sekundSuma wynosi 5000050000, czas wykonania: 0.0099654 sekundSuma wynosi 5000050000, czas wykonania: 0.0109329 sekund

    Suma wynosi 500000500000, czas wykonania: 0.0880532 sekundSuma wynosi 500000500000, czas wykonania: 0.0663662 sekundSuma wynosi 500000500000, czas wykonania: 0.0571766 sekundSuma wynosi 500000500000, czas wykonania: 0.0511684 sekundSuma wynosi 500000500000, czas wykonania: 0.0486953 sekund

  • Widzimy, że czas wykonania ponownie wzrósł.

    Zauważmy teraz, że program sumOfN2 wylicza sumę częściową ciągu arytmetycznego o różnicy   iwyrazie początkowym  . Korzystając z własności ciągu sumę tę możemy wyliczyć przy pomocy wyrażenia:

    In [7]:

    def sumOfN3(n): start = time.time()

    theSum = n*(n+1)/2

    end = time.time()

    return theSum,end-start

    In [8]:

    for n in (10000,100000,1000000,10000000): print("Suma wynosi %d, czas wykonania: %10.7f sekund"%sumOfN3(n))

    Analizując te wyniki dochodzimy do dwóch wniosków:

    1. sumOfN3 wykonuje się dużo szybciej niż sumOfN22. w przypadku sumOfN3czas wykonania funkcji nieznacznie zależy od 

    Cele analizyprzewidywanie wydajności algorytmów

    kiedy program się zakończy?ile pamięci będzie potrzebował?

    porównywanie algorytmówco zmienić, aby program działał szybciej?czy wprowadzenie zmiany spowoduje, że program zadziała szybciej?

    gwarancja poprawności algorytmówczy program się zakończy?czy dla prawidłowych danych zwróci prawidłowy wynik?

    zrozumienie algorytmówunikanie błędów wykonania

    r = 11

    i =∑i=1

    n n(n + 1)2

    n

    Suma wynosi 50005000, czas wykonania: 0.0000021 sekundSuma wynosi 5000050000, czas wykonania: 0.0000012 sekundSuma wynosi 500000500000, czas wykonania: 0.0000007 sekundSuma wynosi 50000005000000, czas wykonania: 0.0000007 sekund

  • Analiza eksperymentalnaobserwacja pewnych własności świata naturalnego, np. czasu pracy programu na komputerzeopracowanie hipotezy (modelu), który jest zgodny z obserwacjamiprzewidywanie zdarzeń za pomocą opracowanej hipotezy, np. czasu pracy programu dla danychwejściowych o dużych rozmiarach lub czasu wykonania na innym komputerzeweryfikacja przewidywań poprzez dalsze obserwacjewalidacja poprzez powtarzanie weryfikacji do momentu, kiedy hipotezy i obserwacje są zgodne

    Zasady

    powtarzalność eksperymentów  ktoś inny powinien być w stanie je przeprowadzićfalsyfikowalność hipotez  można wykazać fałszywość hipotezy przez wskazanie przypadku, któryjej nie spełnia

    Studium przypadku  3SUM3SUM (https://en.wikipedia.org/wiki/3SUM (https://en.wikipedia.org/wiki/3SUM)) to znany problem w teoriizłożoności obliczeniowej: czy dla danego zbioru liczb   naturalnych istnieją elementy  ,   i   z tego zbiorutakie, że

    Jeśli tak, to ile ich jest?

    Dla zainteresowanych (jeden z nierozwiązanych problemów w informatyce):

    Czy istnieje algorytm rozwiązujący zagadnienie 3SUM w czasie   dla pewnego ?

    In [9]:

    import random

    In [13]:

    tab = []

    for i in range(8): tab.append(random.randint(-50,50))

    In [14]:

    tab

    Metoda naiwna:

    N a b c

    a + b + c = 0

    O( )n2−ϵ

    ϵ > 0

    Out[14]:

    [-41, -45, -22, 23, -30, 11, 30, -25]

    https://en.wikipedia.org/wiki/3SUM

  • In [15]:

    count = 0for i in range(len(tab)): for j in range(i+1, len(tab)): for k in range(j+1, len(tab)): if (tab[i]+tab[j]+tab[k]==0): count = count + 1 print(tab[i],tab[j],tab[k])print("In total: %d"%count)

    Krok 1  ProgramStwórzmy program w oparciu o powyższy algorytm. Program ten powinien wczytywać wielkość zbioru liczb zlinii poleceń:

    In [18]:

    %%writefile 3sum.py"""3SUM problem solved with brute-force algorithm"""

    def countTriplets(tab): count = 0 triplets = [] for i in range(len(tab)): for j in range(i+1, len(tab)): for k in range(j+1, len(tab)): if (tab[i]+tab[j]+tab[k]==0): count = count + 1 triplets.append((tab[i],tab[j],tab[k])) return triplets

    if __name__ == "__main__": import sys import random n = int(sys.argv[1]) tab = [] for i in range(n): tab.append(random.randint(-50,50)) triplets = countTriplets(tab) if triplets: for t in triplets: print(t) print("In total: %d"%len(triplets)) else: print("No triplets found")

    -41 11 30In total: 1

    Overwriting 3sum.py

  • In [19]:

    !python3 3sum.py 10

    Krok 2  pomiar czasu pracy programu

    Metoda 1  pomiar ręczny

    możliwe do przeprowadzenia, ale uciążliwew zasadzie nie po to używamy komputerów

    Metoda 2  pomiar z poziomu systemu operacyjnego

    In [20]:

    !time python3 3sum.py 10

    (-4, 12, -8)(4, 12, -16)In total: 2

    No triplets found

    real 0m0.037suser 0m0.032ssys 0m0.004s

  • In [21]:

    !time python3 3sum.py 20

    (32, -3, -29)(32, -45, 13)(32, -49, 17)(-3, -41, 44)(-3, 37, -34)(-3, 37, -34)(-25, 13, 12)(-13, 19, -6)(45, -39, -6)(-49, 12, 37)(12, 17, -29)In total: 11

    real 0m0.035suser 0m0.028ssys 0m0.004s

  • In [22]:

    !time python3 3sum.py 100

  • (-31, 38, -7)(-31, 38, -7)(-31, -17, 48)(-31, -1, 32)(-31, 49, -18)(-31, 37, -6)(-31, 30, 1)(-31, 9, 22)(-31, -5, 36)(-31, 36, -5)(-31, 37, -6)(-31, -8, 39)(-31, 25, 6)(-31, 25, 6)(-31, 22, 9)(-31, 14, 17)(-31, 25, 6)(-31, 25, 6)(-31, 17, 14)(-31, 37, -6)(-31, 37, -6)(-31, -1, 32)(-31, 37, -6)(-31, -10, 41)(-31, 0, 31)(-31, 31, 0)(-31, 49, -18)(-31, 37, -6)(-12, -34, 46)(-12, -34, 46)(-12, -20, 32)(-12, -27, 39)(-12, -25, 37)(-12, -25, 37)(-12, -25, 37)(-12, -25, 37)(-12, -25, 37)(-12, -25, 37)(-12, 8, 4)(-12, 3, 9)(-12, 3, 9)(-12, -29, 41)(-12, -17, 29)(-12, -17, 29)(-12, -27, 39)(-12, 49, -37)(-12, 49, -37)(-12, 37, -25)(-12, 30, -18)(-12, 9, 3)(-12, 9, 3)(-12, 48, -36)(-12, 48, -36)(-12, -5, 17)(-12, 20, -8)(-12, 37, -25)(-12, -37, 49)(-12, 12, 0)(-12, 12, 0)(-12, -8, 20)(-12, 22, -10)

  • (-12, 14, -2)(-12, 3, 9)(-12, -2, 14)(-12, -25, 37)(-12, -25, 37)(-12, -25, 37)(-12, -25, 37)(-12, 17, -5)(-12, 8, 4)(-12, 41, -29)(-12, -27, 39)(-12, 9, 3)(-12, 6, 6)(-12, 12, 0)(-12, 12, 0)(-12, 49, -37)(-12, -27, 39)(-34, 38, -4)(-34, 38, -4)(-34, 38, -4)(-34, 8, 26)(-34, 3, 31)(-34, -7, 41)(-34, 30, 4)(-34, 40, -6)(-34, 9, 25)(-34, 9, 25)(-34, -5, 39)(-34, 36, -2)(-34, 44, -10)(-34, -7, 41)(-34, 20, 14)(-34, 20, 14)(-34, 12, 22)(-34, -8, 42)(-34, -8, 42)(-34, 25, 9)(-34, 22, 12)(-34, 14, 20)(-34, 3, 31)(-34, 25, 9)(-34, 34, 0)(-34, 34, 0)(-34, -5, 39)(-34, 20, 14)(-34, 8, 26)(-34, 44, -10)(-34, 31, 3)(46, -25, -21)(46, -29, -17)(46, -17, -29)(46, -5, -41)(46, -36, -10)(46, -46, 0)(46, -46, 0)(46, -40, -6)(46, -21, -25)(46, -41, -5)(46, -10, -36)(46, -50, 4)(46, -6, -40)

  • (38, -20, -18)(38, 8, -46)(38, 3, -41)(38, -7, -31)(38, -17, -21)(38, -1, -37)(38, -1, -37)(38, -5, -33)(38, -7, -31)(38, -36, -2)(38, -46, 8)(38, -37, -1)(38, 12, -50)(38, -41, 3)(38, -41, 3)(38, -2, -36)(38, -5, -33)(38, -1, -37)(38, -48, 10)(38, -48, 10)(38, -50, 12)(50, -27, -23)(50, -25, -25)(50, -7, -43)(50, -7, -43)(50, -29, -21)(50, -17, -33)(50, -27, -23)(50, -43, -7)(50, -43, -7)(50, -46, -4)(50, -46, -4)(50, -46, -4)(50, -40, -10)(50, -21, -29)(50, -2, -48)(50, -10, -40)(50, -23, -27)(50, -23, -27)(50, -50, 0)(50, -50, 0)(-20, 8, 12)(-20, 8, 12)(-20, 3, 17)(-20, -29, 49)(-20, -29, 49)(-20, -17, 37)(-20, -17, 37)(-20, -17, 37)(-20, -17, 37)(-20, -17, 37)(-20, -17, 37)(-20, 49, -29)(-20, 30, -10)(-20, -5, 25)(-20, -5, 25)(-20, 20, 0)(-20, 20, 0)(-20, 12, 8)(-20, 25, -5)(-20, -21, 41)

  • (-20, 22, -2)(-20, 14, 6)(-20, 14, 6)(-20, 3, 17)(-20, 25, -5)(-20, 17, 3)(-20, 20, 0)(-20, 20, 0)(-20, 8, 12)(-20, 10, 10)(-20, 6, 14)(-20, 6, 14)(-20, 49, -29)(-20, -6, 26)(-27, 7, 20)(-27, 7, 20)(-27, -7, 34)(-27, -17, 44)(-27, -17, 44)(-27, 37, -10)(-27, 48, -21)(-27, -5, 32)(-27, -7, 34)(-27, 20, 7)(-27, 37, -10)(-27, -4, 31)(-27, -2, 29)(-27, -2, 29)(-27, 17, 10)(-27, 17, 10)(-27, -5, 32)(-27, 37, -10)(-27, 1, 26)(-27, 20, 7)(-27, 37, -10)(-27, 37, -10)(-27, -10, 37)(-27, -23, 50)(-27, -4, 31)(-27, 31, -4)(-25, 8, 17)(-25, 3, 22)(-25, -7, 32)(-25, -17, 42)(-25, -17, 42)(-25, -1, 26)(-25, 30, -5)(-25, 30, -5)(-25, 48, -23)(-25, -7, 32)(-25, 25, 0)(-25, 25, 0)(-25, -21, 46)(-25, 22, 3)(-25, 22, 3)(-25, 25, 0)(-25, 25, 0)(-25, -4, 29)(-25, -4, 29)(-25, -25, 50)(-25, 17, 8)

  • (-25, 29, -4)(-25, 29, -4)(-25, -1, 26)(-25, -4, 29)(-25, 31, -6)(-25, 29, -4)(8, -7, -1)(8, -7, -1)(8, -17, 9)(8, -17, 9)(8, -1, -7)(8, 40, -48)(8, -7, -1)(8, -37, 29)(8, -37, 29)(8, -8, 0)(8, -8, 0)(8, -40, 32)(8, 25, -33)(8, 25, -33)(8, -4, -4)(8, -4, -4)(8, -2, -6)(8, -25, 17)(8, 42, -50)(8, 29, -37)(8, 10, -18)(8, -50, 42)(8, 10, -18)(8, -4, -4)(8, 29, -37)(8, 32, -40)(3, 7, -10)(3, -7, 4)(3, -29, 26)(3, -17, 14)(3, -17, 14)(3, -1, -2)(3, -43, 40)(3, 37, -40)(3, 37, -40)(3, 30, -33)(3, 40, -43)(3, -7, 4)(3, 20, -23)(3, 37, -40)(3, 37, -40)(3, -37, 34)(3, -40, 37)(3, -40, 37)(3, -40, 37)(3, -40, 37)(3, 22, -25)(3, 3, -6)(3, -4, 1)(3, -2, -1)(3, 34, -37)(3, 37, -40)(3, 1, -4)(3, 1, -4)(3, 20, -23)

  • (3, 37, -40)(3, 37, -40)(3, -35, 32)(3, -10, 7)(3, 37, -40)(3, 3, -6)(3, 26, -29)(7, -7, 0)(7, -7, 0)(7, -29, 22)(7, -17, 10)(7, -17, 10)(7, -27, 20)(7, -27, 20)(7, -1, -6)(7, -43, 36)(7, 30, -37)(7, 30, -37)(7, -5, -2)(7, 36, -43)(7, -7, 0)(7, -7, 0)(7, 20, -27)(7, 20, -27)(7, -36, 29)(7, -36, 29)(7, -46, 39)(7, -8, 1)(7, -21, 14)(7, -21, 14)(7, 22, -29)(7, -41, 34)(7, 3, -10)(7, -2, -5)(7, 20, -27)(7, 20, -27)(7, 29, -36)(7, -1, -6)(7, -48, 41)(7, -33, 26)(7, -10, 3)(7, 29, -36)(-7, -29, 36)(-7, -27, 34)(-7, -1, 8)(-7, -43, 50)(-7, 30, -23)(-7, 40, -33)(-7, 9, -2)(-7, 48, -41)(-7, -5, 12)(-7, -5, 12)(-7, 36, -29)(-7, 44, -37)(-7, 44, -37)(-7, -43, 50)(-7, -7, 14)(-7, -7, 14)(-7, -37, 44)(-7, 12, -5)(-7, 25, -18)

  • (-7, 3, 4)(-7, 25, -18)(-7, -2, 9)(-7, 34, -27)(-7, 34, -27)(-7, -25, 32)(-7, 17, -10)(-7, -5, 12)(-7, 1, 6)(-7, 1, 6)(-7, 42, -35)(-7, 8, -1)(-7, 44, -37)(-7, -35, 42)(-7, 0, 7)(-7, 4, 3)(-7, 0, 7)(-29, -17, 46)(-29, -1, 30)(-29, 37, -8)(-29, 30, -1)(-29, 9, 20)(-29, 9, 20)(-29, -5, 34)(-29, 36, -7)(-29, 20, 9)(-29, 37, -8)(-29, 12, 17)(-29, -8, 37)(-29, -8, 37)(-29, -8, 37)(-29, -8, 37)(-29, 25, 4)(-29, -21, 50)(-29, 22, 7)(-29, 3, 26)(-29, 25, 4)(-29, -2, 31)(-29, 34, -5)(-29, 17, 12)(-29, 20, 9)(-29, 29, 0)(-29, 29, 0)(-29, -10, 39)(-29, 0, 29)(-29, 29, 0)(-29, 3, 26)(-17, -27, 44)(-17, -27, 44)(-17, 40, -23)(-17, 9, 8)(-17, 48, -31)(-17, -5, 22)(-17, 44, -27)(-17, 44, -27)(-17, -8, 25)(-17, -8, 25)(-17, 22, -5)(-17, 14, 3)(-17, 14, 3)(-17, 3, 14)

  • (-17, -25, 42)(-17, -25, 42)(-17, 46, -29)(-17, 17, 0)(-17, 17, 0)(-17, 8, 9)(-17, 44, -27)(-17, 44, -27)(-17, -33, 50)(-17, 10, 7)(-17, 10, 7)(-17, 3, 14)(-27, 37, -10)(-27, 48, -21)(-27, -5, 32)(-27, -7, 34)(-27, 20, 7)(-27, 37, -10)(-27, -4, 31)(-27, -2, 29)(-27, -2, 29)(-27, 17, 10)(-27, 17, 10)(-27, -5, 32)(-27, 37, -10)(-27, 1, 26)(-27, 20, 7)(-27, 37, -10)(-27, 37, -10)(-27, -10, 37)(-27, -23, 50)(-27, -4, 31)(-27, 31, -4)(-1, 49, -48)(-1, -43, 44)(-1, -43, 44)(-1, 37, -36)(-1, 37, -36)(-1, 30, -29)(-1, 9, -8)(-1, -5, 6)(-1, -5, 6)(-1, 36, -35)(-1, 44, -43)(-1, -43, 44)(-1, -7, 8)(-1, 37, -36)(-1, 37, -36)(-1, -36, 37)(-1, -36, 37)(-1, -36, 37)(-1, -36, 37)(-1, -8, 9)(-1, -40, 41)(-1, -31, 32)(-1, -21, 22)(-1, -41, 42)(-1, -41, 42)(-1, 3, -2)(-1, -2, 3)(-1, 34, -33)

  • (-1, -25, 26)(-1, -5, 6)(-1, -5, 6)(-1, 37, -36)(-1, 1, 0)(-1, 1, 0)(-1, 37, -36)(-1, 37, -36)(-1, -48, 49)(-1, 41, -40)(-1, 37, -36)(-1, -6, 7)(49, -43, -6)(49, -43, -6)(49, -8, -41)(49, -31, -18)(49, 1, -50)(49, -1, -48)(-43, 37, 6)(-43, 37, 6)(-43, 40, 3)(-43, 40, 3)(-43, 9, 34)(-43, 48, -5)(-43, 48, -5)(-43, 36, 7)(-43, 44, -1)(-43, -7, 50)(-43, 37, 6)(-43, 37, 6)(-43, 12, 31)(-43, 14, 29)(-43, 14, 29)(-43, 34, 9)(-43, 17, 26)(-43, 37, 6)(-43, 37, 6)(-43, 1, 42)(-43, 1, 42)(-43, 37, 6)(-43, 37, 6)(-43, 29, 14)(-43, -1, 44)(-43, 37, 6)(-43, 37, 6)(-43, 6, 37)(-43, 12, 31)(-43, 4, 39)(-43, 6, 37)(-43, 49, -6)(-43, 29, 14)(37, 9, -46)(37, -43, 6)(37, -43, 6)(37, -36, -1)(37, -46, 9)(37, -37, 0)(37, -37, 0)(37, -8, -29)(37, -40, 3)(37, -40, 3)

  • (37, -31, -6)(37, -41, 4)(37, 3, -40)(37, -4, -33)(37, -2, -35)(37, -1, -36)(37, -33, -4)(37, -33, -4)(37, -10, -27)(37, -10, -27)(37, 0, -37)(37, 3, -40)(37, -37, 0)(30, -5, -25)(30, -7, -23)(30, 20, -50)(30, -36, 6)(30, -36, 6)(30, -37, 7)(30, -40, 10)(30, -40, 10)(30, -31, 1)(30, 3, -33)(30, -25, -5)(30, 20, -50)(30, -1, -29)(30, -33, 3)(30, 10, -40)(30, 10, -40)(30, 6, -36)(30, 6, -36)(30, -37, 7)(40, -5, -35)(40, -43, 3)(40, -43, 3)(40, -7, -33)(40, -36, -4)(40, -36, -4)(40, -36, -4)(40, -46, 6)(40, -46, 6)(40, -40, 0)(40, -40, 0)(40, -41, 1)(40, -4, -36)(40, -5, -35)(40, 8, -48)(40, 10, -50)(40, -50, 10)(40, -4, -36)(40, 0, -40)(40, -36, -4)(40, 0, -40)(9, -5, -4)(9, -5, -4)(9, -5, -4)(9, -43, 34)(9, -7, -2)(9, 20, -29)(9, 37, -46)(9, -46, 37)

  • (9, -46, 37)(9, -46, 37)(9, -46, 37)(9, 12, -21)(9, -8, -1)(9, -40, 31)(9, -31, 22)(9, -21, 12)(9, -41, 32)(9, 14, -23)(9, -4, -5)(9, -5, -4)(9, -5, -4)(9, 1, -10)(9, 20, -29)(9, -48, 39)(9, -35, 26)(9, -23, 14)(9, 41, -50)(9, 9, -18)(9, 31, -40)(48, -5, -43)(48, -43, -5)(48, -7, -41)(48, -46, -2)(48, -8, -40)(48, -8, -40)(48, -21, -27)(48, -21, -27)(48, -25, -23)(48, -48, 0)(48, -48, 0)(-5, 36, -31)(-5, -7, 12)(-5, -7, 12)(-5, -36, 41)(-5, -37, 42)(-5, -37, 42)(-5, -21, 26)(-5, -41, 46)(-5, -4, 9)(-5, -2, 7)(-5, 34, -29)(-5, -5, 10)(-5, -5, 10)(-5, 1, 4)(-5, 42, -37)(-5, -1, 6)(-5, -1, 6)(-5, 41, -36)(-5, -27, 32)(-5, 9, -4)(-5, 9, -4)(-5, 32, -27)(-5, -37, 42)(36, -43, 7)(36, -7, -29)(36, -36, 0)(36, -36, 0)(36, -46, 10)(36, -46, 10)

  • (36, -37, 1)(36, 12, -48)(36, -40, 4)(36, -31, -5)(36, 14, -50)(36, 1, -37)(36, -1, -35)(36, -48, 12)(36, -50, 14)(36, 0, -36)(36, 4, -40)(36, -36, 0)(44, -43, -1)(44, -7, -37)(44, -7, -37)(44, -36, -8)(44, -8, -36)(44, -40, -4)(44, -40, -4)(44, -40, -4)(44, -21, -23)(44, -4, -40)(44, -48, 4)(44, -50, 6)(44, -50, 6)(44, -4, -40)(44, -4, -40)(-43, -7, 50)(-43, 37, 6)(-43, 37, 6)(-43, 12, 31)(-43, 14, 29)(-43, 14, 29)(-43, 34, 9)(-43, 17, 26)(-43, 37, 6)(-43, 37, 6)(-43, 1, 42)(-43, 1, 42)(-43, 37, 6)(-43, 37, 6)(-43, 29, 14)(-43, -1, 44)(-43, 37, 6)(-43, 37, 6)(-43, 6, 37)(-43, 12, 31)(-43, 4, 39)(-43, 6, 37)(-43, 49, -6)(-43, 29, 14)(-7, -37, 44)(-7, 12, -5)(-7, 25, -18)(-7, 3, 4)(-7, 25, -18)(-7, -2, 9)(-7, 34, -27)(-7, 34, -27)(-7, -25, 32)(-7, 17, -10)

  • (-7, -5, 12)(-7, 1, 6)(-7, 1, 6)(-7, 42, -35)(-7, 8, -1)(-7, 44, -37)(-7, -35, 42)(-7, 0, 7)(-7, 4, 3)(-7, 0, 7)(20, -46, 26)(20, -37, 17)(20, -40, 20)(20, -21, 1)(20, 3, -23)(20, -2, -18)(20, 17, -37)(20, 20, -40)(20, -23, 3)(20, -27, 7)(20, 9, -29)(20, -27, 7)(37, -36, -1)(37, -46, 9)(37, -37, 0)(37, -37, 0)(37, -8, -29)(37, -40, 3)(37, -40, 3)(37, -31, -6)(37, -41, 4)(37, 3, -40)(37, -4, -33)(37, -2, -35)(37, -1, -36)(37, -33, -4)(37, -33, -4)(37, -10, -27)(37, -10, -27)(37, 0, -37)(37, 3, -40)(37, -37, 0)(-36, -8, 44)(-36, 22, 14)(-36, 22, 14)(-36, 46, -10)(-36, -5, 41)(-36, 37, -1)(-36, 42, -6)(-36, 37, -1)(-36, 29, 7)(-36, -1, 37)(-36, -1, 37)(-36, 10, 26)(-36, 10, 26)(-36, 4, 32)(-36, 29, 7)(-36, -6, 42)(-46, 12, 34)(-46, 14, 32)(-46, -4, 50)

  • (-46, 34, 12)(-46, 46, 0)(-46, 46, 0)(-46, 17, 29)(-46, 17, 29)(-46, 37, 9)(-46, 20, 26)(-46, 42, 4)(-46, 37, 9)(-46, 37, 9)(-46, 50, -4)(-46, 50, -4)(-46, 9, 37)(-46, 4, 42)(-46, 32, 14)(-46, 39, 7)(-37, 12, 25)(-37, 12, 25)(-37, 25, 12)(-37, 3, 34)(-37, 25, 12)(-37, -4, 41)(-37, -2, 39)(-37, 34, 3)(-37, 17, 20)(-37, -5, 42)(-37, -5, 42)(-37, 37, 0)(-37, 37, 0)(-37, 8, 29)(-37, 8, 29)(-37, 37, 0)(-37, 37, 0)(-37, 37, 0)(-37, 37, 0)(-37, 41, -4)(-37, 41, -4)(-37, 6, 31)(-37, 0, 37)(-37, 31, 6)(-37, 37, 0)(12, -8, -4)(12, -8, -4)(12, -8, -4)(12, 25, -37)(12, -21, 9)(12, -41, 29)(12, -41, 29)(12, 25, -37)(12, -2, -10)(12, 17, -29)(12, 6, -18)(12, 6, -18)(-8, -31, 39)(-8, -21, 29)(-8, -21, 29)(-8, -41, 49)(-8, 14, -6)(-8, -4, 12)(-8, -2, 10)(-8, -2, 10)

  • (-8, 37, -29)(-8, 1, 7)(-8, 8, 0)(-8, 8, 0)(-8, 37, -29)(-8, -1, 9)(-8, 37, -29)(-8, 44, -36)(-8, -33, 41)(-8, -23, 31)(-8, -4, 12)(-8, 12, -4)(-8, 37, -29)(-8, 14, -6)(-8, 26, -18)(-40, 14, 26)(-40, 3, 37)(-40, 3, 37)(-40, 3, 37)(-40, 3, 37)(-40, -4, 44)(-40, -2, 42)(-40, -2, 42)(-40, 34, 6)(-40, 34, 6)(-40, 46, -6)(-40, 37, 3)(-40, 1, 39)(-40, 8, 32)(-40, 37, 3)(-40, -1, 41)(-40, 37, 3)(-40, 44, -4)(-40, 44, -4)(-40, -10, 50)(-40, 9, 31)(-40, 37, 3)(-40, 14, 26)(-31, 25, 6)(-31, 25, 6)(-31, 22, 9)(-31, 14, 17)(-31, 25, 6)(-31, 25, 6)(-31, 17, 14)(-31, 37, -6)(-31, 37, -6)(-31, -1, 32)(-31, 37, -6)(-31, -10, 41)(-31, 0, 31)(-31, 31, 0)(-31, 49, -18)(-31, 37, -6)(25, -21, -4)(25, -21, -4)(25, -21, -4)(25, 25, -50)(25, -2, -23)(25, -25, 0)(25, -25, 0)

  • (25, 8, -33)(25, -35, 10)(25, -35, 10)(25, 12, -37)(25, 4, -29)(-21, 22, -1)(-21, 14, 7)(-21, 25, -4)(-21, 25, -4)(-21, 25, -4)(-21, -25, 46)(-21, 17, 4)(-21, -5, 26)(-21, 1, 20)(-21, 44, -23)(-21, -10, 31)(-21, 50, -29)(-21, 9, 12)(-21, 14, 7)(-21, 39, -18)(22, 14, -36)(22, 3, -25)(22, -4, -18)(22, -25, 3)(22, 1, -23)(22, -48, 26)(22, -4, -18)(22, -36, 14)(22, -4, -18)(22, -29, 7)(-41, 34, 7)(-41, 46, -5)(-41, 37, 4)(-41, 42, -1)(-41, 37, 4)(-41, 29, 12)(-41, -1, 42)(-41, 37, 4)(-41, 10, 31)(-41, 41, 0)(-41, 41, 0)(-41, 9, 32)(-41, 10, 31)(-41, 12, 29)(-41, 4, 37)(14, -4, -10)(14, 34, -48)(14, -10, -4)(14, -10, -4)(14, -23, 9)(14, 4, -18)(14, -40, 26)(3, -4, 1)(3, -2, -1)(3, 34, -37)(3, 37, -40)(3, 1, -4)(3, 1, -4)(3, 20, -23)(3, 37, -40)(3, 37, -40)

  • (3, -35, 32)(3, -10, 7)(3, 37, -40)(3, 3, -6)(3, 26, -29)(25, -2, -23)(25, -25, 0)(25, -25, 0)(25, 8, -33)(25, -35, 10)(25, -35, 10)(25, 12, -37)(25, 4, -29)(-4, -2, 6)(-4, -2, 6)(-4, -25, 29)(-4, -25, 29)(-4, -5, 9)(-4, 37, -33)(-4, 1, 3)(-4, 8, -4)(-4, 8, -4)(-4, 37, -33)(-4, 37, -33)(-4, 44, -40)(-4, -35, 39)(-4, -33, 37)(-4, -10, 14)(-4, 10, -6)(-4, 41, -37)(-4, -27, 31)(-4, 10, -6)(-4, 0, 4)(-4, 4, 0)(-4, 31, -27)(-2, -5, 7)(-2, 37, -35)(-2, 20, -18)(-2, 42, -40)(-2, 8, -6)(-2, 37, -35)(-2, 29, -27)(-2, 29, -27)(-2, -1, 3)(-2, 37, -35)(-2, -48, 50)(-2, -35, 37)(-2, -10, 12)(-2, -27, 29)(-2, -4, 6)(-2, -4, 6)(-2, 6, -4)(-2, 31, -29)(-2, 6, -4)(-2, 29, -27)(-2, -37, 39)(-2, -40, 42)(34, -5, -29)(34, 1, -35)(34, -1, -33)(34, -48, 14)

  • (34, 6, -40)(34, 6, -40)(34, 3, -37)(-25, 17, 8)(-25, 29, -4)(-25, 29, -4)(-25, -1, 26)(-25, -4, 29)(-25, 31, -6)(-25, 29, -4)(46, -10, -36)(46, -50, 4)(46, -6, -40)(17, 1, -18)(17, 20, -37)(17, -48, 31)(17, 10, -27)(17, 10, -27)(17, -23, 6)(17, -23, 6)(17, -27, 10)(17, 10, -27)(17, 12, -29)(-5, 1, 4)(-5, 42, -37)(-5, -1, 6)(-5, -1, 6)(-5, 41, -36)(-5, -27, 32)(-5, 9, -4)(-5, 9, -4)(-5, 32, -27)(-5, -37, 42)(37, -1, -36)(37, -33, -4)(37, -33, -4)(37, -10, -27)(37, -10, -27)(37, 0, -37)(37, 3, -40)(37, -37, 0)(1, -1, 0)(1, -1, 0)(1, -33, 32)(1, -10, 9)(1, -27, 26)(1, -50, 49)(1, -4, 3)(1, 3, -4)(1, -27, 26)(1, 39, -40)(20, -23, 3)(20, -27, 7)(20, 9, -29)(20, -27, 7)(42, 8, -50)(42, -48, 6)(42, -48, 6)(42, -36, -6)(8, 29, -37)(8, 10, -18)

  • (8, -50, 42)(8, 10, -18)(8, -4, -4)(8, 29, -37)(8, 32, -40)(37, -1, -36)(37, -33, -4)(37, -33, -4)(37, -10, -27)(37, -10, -27)(37, 0, -37)(37, 3, -40)(37, -37, 0)(29, -35, 6)(29, -35, 6)(29, -33, 4)(29, -23, -6)(29, 0, -29)(29, -36, 7)(29, 0, -29)(-1, 37, -36)(-1, -48, 49)(-1, 41, -40)(-1, 37, -36)(-1, -6, 7)(37, -33, -4)(37, -33, -4)(37, -10, -27)(37, -10, -27)(37, 0, -37)(37, 3, -40)(37, -37, 0)(44, -48, 4)(44, -50, 6)(44, -50, 6)(44, -4, -40)(44, -4, -40)(-48, 41, 7)(-48, 9, 39)(-48, 6, 42)(-48, 6, 42)(-35, 41, -6)(-35, 9, 26)(-35, -4, 39)(-35, 6, 29)(-35, 4, 31)(-35, 6, 29)(-35, 32, 3)(-35, 39, -4)(-33, -4, 37)(-33, 4, 29)(-33, 37, -4)(-33, 39, -6)(-33, 26, 7)(-10, 10, 0)(-10, 10, 0)(-10, -27, 37)(-10, 50, -40)(-10, 10, 0)(-10, 10, 0)(-10, -4, 14)

  • Uwaga! Użytkownicy Windowsa mają do dyspozycji Measure-Command w Powershellu.

    Korzystając z możliwości powłoki, nie musimy uruchamiać programu dla każdego rozmiaru ręcznie:

    (-10, 6, 4)(-10, 4, 6)(-10, 37, -27)(-10, 3, 7)(-10, 14, -4)(-10, 39, -29)(10, -4, -6)(10, -36, 26)(10, -6, -4)(-23, 41, -18)(-23, -27, 50)(-23, 50, -27)(-23, 9, 14)(-23, 29, -6)(41, 9, -50)(41, -4, -37)(41, -37, -4)(-27, -4, 31)(-27, 31, -4)(50, -50, 0)(50, -50, 0)(9, 31, -40)(10, -4, -6)(10, -36, 26)(10, -6, -4)(-4, 0, 4)(-4, 4, 0)(-4, 31, -27)(6, 12, -18)(6, 0, -6)(6, 31, -37)(6, -6, 0)(12, 6, -18)(0, 4, -4)(0, 6, -6)(0, 29, -29)(0, 37, -37)(4, 32, -36)(4, 14, -18)(4, -4, 0)(31, 6, -37)(31, -27, -4)(6, -6, 0)(29, -36, 7)(29, 0, -29)(37, 3, -40)(37, -37, 0)(3, 26, -29)(-36, -6, 42)(14, -40, 26)In total: 1209

    real 0m0.085suser 0m0.076ssys 0m0.008s

  • In [23]:

    !for N in 10 20 30 40 50; do time python3 3sum.py $N; done

  • (-31, 20, 11)(26, 9, -35)In total: 2

    real 0m0.039suser 0m0.036ssys 0m0.000s(-3, 45, -42)(-28, -10, 38)(-28, -10, 38)(-28, -10, 38)(0, 14, -14)(41, 1, -42)(1, -10, 9)(1, -10, 9)(1, 9, -10)(-10, 6, 4)(-10, -28, 38)(-10, 6, 4)(-10, -28, 38)(9, -42, 33)(9, 5, -14)(6, -10, 4)(-28, -10, 38)(-42, 4, 38)In total: 18

    real 0m0.035suser 0m0.028ssys 0m0.004s(41, -1, -40)(41, -1, -40)(41, -40, -1)(41, -45, 4)(41, -45, 4)(41, -49, 8)(41, -44, 3)(41, -1, -40)(-1, 39, -38)(-40, 37, 3)(-45, 35, 10)(-45, 10, 35)(-45, 37, 8)(-49, 10, 39)(-49, 12, 37)(35, 3, -38)(10, -18, 8)(10, -27, 17)(10, 3, -13)(35, 3, -38)(39, -1, -38)(39, 3, -42)(4, 11, -15)(12, 3, -15)(11, -15, 4)(37, -40, 3)(-27, 3, 24)In total: 27

    real 0m0.028suser 0m0.024s

  • sys 0m0.000s(15, 14, -29)(15, 17, -32)(15, -36, 21)(15, -36, 21)(15, -14, -1)(14, 17, -31)(14, 10, -24)(14, -24, 10)(11, -38, 27)(11, 5, -16)(11, -36, 25)(11, -36, 25)(11, -32, 21)(11, -32, 21)(11, 20, -31)(-22, -5, 27)(-22, 17, 5)(-22, -24, 46)(-22, -14, 36)(-22, -5, 27)(-22, -5, 27)(45, -16, -29)(45, -14, -31)(-5, -38, 43)(-5, 41, -36)(-5, 10, -5)(-5, 10, -5)(-5, -24, 29)(-5, -16, 21)(-5, -16, 21)(-5, -5, 10)(-5, -31, 36)(-5, -5, 10)(-38, 17, 21)(-38, 17, 21)(-38, -5, 43)(-38, -5, 43)(17, -16, -1)(-48, 5, 43)(-48, 21, 27)(-48, 21, 27)(41, -36, -5)(41, -36, -5)(10, -36, 26)(10, 21, -31)(10, -5, -5)(10, -31, 21)(-24, -16, 40)(-24, -1, 25)(-24, -1, 25)(-24, 29, -5)(-24, 29, -5)(-33, -11, 44)(46, -32, -14)(5, -32, 27)(5, 26, -31)(-36, 26, 10)(-36, -14, 50)(-16, -11, 27)(-16, 21, -5)

  • (-16, 21, -5)(-16, -5, 21)(-16, -5, 21)(-32, -11, 43)(-14, -11, 25)(-14, -11, 25)(-14, -29, 43)(-11, -33, 44)(-11, -29, 40)(21, -31, 10)(-5, -31, 36)(-5, -5, 10)(-31, -5, 36)(-31, 21, 10)In total: 74

    real 0m0.028suser 0m0.024ssys 0m0.000s(11, -18, 7)(11, -18, 7)(11, -4, -7)(11, -20, 9)(11, -20, 9)(11, -20, 9)(11, -20, 9)(11, -11, 0)(11, 7, -18)(11, 13, -24)(11, -18, 7)(-39, -4, 43)(-39, 1, 38)(-39, 48, -9)(-39, -11, 50)(-39, -9, 48)(-17, -4, 21)(-17, -20, 37)(-17, 10, 7)(-17, 10, 7)(-17, -20, 37)(-17, 10, 7)(-17, 10, 7)(-17, 31, -14)(-17, -14, 31)(-17, -24, 41)(-18, 40, -22)(-18, -20, 38)(-18, -20, 38)(-18, -27, 45)(-18, 9, 9)(-18, -13, 31)(-18, -13, 31)(-18, 27, -9)(-18, 42, -24)(-18, 42, -24)(-18, -24, 42)(-4, 40, -36)(-4, 40, -36)(-4, 48, -44)(-4, -27, 31)(-4, -27, 31)

  • (-4, -44, 48)(-4, 13, -9)(47, -20, -27)(47, -20, -27)(47, -36, -11)(47, -11, -36)(40, -20, -20)(40, -50, 10)(40, -50, 10)(40, 10, -50)(40, -27, -13)(40, 10, -50)(40, -22, -18)(-20, 10, 10)(-20, -27, 47)(-20, -27, 47)(-20, -11, 31)(-20, -11, 31)(-20, 7, 13)(-20, 13, 7)(-20, -22, 42)(-20, -22, 42)(-20, -22, 42)(-20, 27, -7)(-20, -18, 38)(-50, 49, 1)(-50, 43, 7)(-50, 43, 7)(-50, 9, 41)(-50, 37, 13)(-50, 9, 41)(-50, 0, 50)(49, 1, -50)(49, -36, -13)(49, -27, -22)(49, -13, -36)(10, 1, -11)(10, -20, 10)(1, 43, -44)(1, -11, 10)(1, 13, -14)(1, -22, 21)(43, -36, -7)(43, 7, -50)(43, -36, -7)(43, 7, -50)(-20, -27, 47)(-20, -27, 47)(-20, -11, 31)(-20, -11, 31)(-20, 7, 13)(-20, 13, 7)(-20, -22, 42)(-20, -22, 42)(-20, -22, 42)(-20, 27, -7)(-20, -18, 38)(-36, -11, 47)(-36, -11, 47)(-36, 9, 27)(-36, -14, 50)

  • Nie jest to zbyt przejrzyste, dlatego zmodyfikujemy nieco nasz program:

    (-36, 9, 27)(-36, -9, 45)(-27, -11, 38)(-27, -14, 41)(-27, 27, 0)(-27, -18, 45)(-11, 47, -36)(-11, -36, 47)(9, 13, -22)(9, 9, -18)(9, 27, -36)(9, -9, 0)(9, -50, 41)(-44, 7, 37)(-44, 37, 7)(-44, 31, 13)(-44, 13, 31)(7, -14, 7)(7, 0, -7)(37, -13, -24)(37, 13, -50)(-13, 31, -18)(-13, 13, 0)(-13, -14, 27)(-13, -18, 31)(31, -22, -9)(31, -7, -24)(13, -22, 9)(-22, -9, 31)(-14, -36, 50)(-14, 21, -7)(-14, 38, -24)(9, 27, -36)(9, -9, 0)(9, -50, 41)(27, -9, -18)(-36, -9, 45)(-18, 42, -24)(-18, 42, -24)(-18, -24, 42)(7, 0, -7)(0, -50, 50)(31, -7, -24)In total: 146

    real 0m0.033suser 0m0.024ssys 0m0.008s

  • In [24]:

    %%writefile 3sum_2.py"""3SUM problem solved with brute-force algorithm"""

    def countTriplets(tab): count = 0 triplets = [] for i in range(len(tab)): for j in range(i+1, len(tab)): for k in range(j+1, len(tab)): if (tab[i]+tab[j]+tab[k]==0): count = count + 1 triplets.append((tab[i],tab[j],tab[k])) return triplets

    if __name__ == "__main__": import sys import random n = int(sys.argv[1]) tab = [] for i in range(n): tab.append(random.randint(-50,50)) triplets = countTriplets(tab) print("\nSystem size: %d"%n)

    Overwriting 3sum_2.py

  • In [25]:

    !for N in 10 20 30 40 50; do time python3 3sum_2.py $N; done

    Metoda 3  pomiar z poziomu programu

    Jeżeli wyników pomiaru czasu chcemy potem używać do analiz, najwygodniejszy może okazać się pomiarczasu wykonywania z poziomu analizowanego programu.

    Najprościej jest użyć do tego modułu time:

    In [26]:

    import time

    System size: 10

    real 0m0.031suser 0m0.028ssys 0m0.000s

    System size: 20

    real 0m0.029suser 0m0.024ssys 0m0.004s

    System size: 30

    real 0m0.027suser 0m0.024ssys 0m0.000s

    System size: 40

    real 0m0.029suser 0m0.024ssys 0m0.004s

    System size: 50

    real 0m0.029suser 0m0.024ssys 0m0.004s

  • In [27]:

    #sekundy...time.time()

    In [28]:

    #... które upłynęły odtime.gmtime(0)[:6]

    In [29]:

    #jak mierzyć?def procedure(): time.sleep(2.5)

    In [30]:

    # czas procesora, jaki został skonsumowany# przez proces ("process time")t0 = time.clock()procedure()t1 = time.clock()print("Czas procesora:", t1-t0, "s")

    In [31]:

    # rzeczywisty czas ("wall time")t0 = time.time()procedure()t1 = time.time()print("Rzeczywisty czas:", t1-t0, "s")

    Warto wiedzieć, że nie wszystkie systemy (z Windows włącznie) mogą mierzyć czas procesora. Funkcja clock pokaże wówczas czas rzeczywisty.

    Wróćmy do naszego programu:

    Out[27]:

    1474631774.1989377

    Out[28]:

    (1970, 1, 1, 0, 0, 0)

    Czas procesora: 0.0019679999999999698 s

    Rzeczywisty czas: 2.5009217262268066 s

  • In [34]:

    %%writefile 3sum_3.py"""3SUM problem solved with brute-force algorithm"""

    def countTriplets(tab): count = 0 triplets = [] for i in range(len(tab)): for j in range(i+1, len(tab)): for k in range(j+1, len(tab)): if (tab[i]+tab[j]+tab[k]==0): count = count + 1 triplets.append((tab[i],tab[j],tab[k])) return triplets

    if __name__ == "__main__": import sys import time import random n = int(sys.argv[1]) tab = [] for i in range(n): tab.append(random.randint(-50,50)) t = time.clock() #czas start triplets = countTriplets(tab) t = time.clock() - t #ile trwało? print("%d %f"%(n,t))

    In [35]:

    !python3 3sum_3.py 10

    Overwriting 3sum_3.py

    10 0.000057

  • In [39]:

    !for N in 10 20 50 100 200 500 1000; do python3 3sum_3.py $N; done

    Zamiast wypisywać na ekran, zapiszmy te wyniki do pliku:

    In [40]:

    !for N in 10 20 50 100 200 500 1000 2000; do python3 3sum_3.py $N >> wyniki.dat; done

    In [32]:

    !cat wyniki.dat

    Krok 3  wykres czasu wykonania w funkcji rozmiaru danychwejściowych

    In [34]:

    %matplotlib inline

    In [36]:

    import matplotlib.pyplot as pltimport numpy as np

    x,y = np.loadtxt("wyniki.dat",unpack=True) #wczytujemy dane z plikuprint(x)print(y)

    10 0.00005920 0.00028250 0.003865100 0.025720200 0.174831500 2.6954561000 21.228454

    10 0.00006620 0.00029250 0.003632100 0.025550200 0.173205500 2.6653521000 22.3515712000 171.924855

    [ 10. 20. 50. 100. 200. 500. 1000. 2000.][ 6.60000000e-05 2.92000000e-04 3.63200000e-03 2.55500000e-02 1.73205000e-01 2.66535200e+00 2.23515710e+01 1.71924855e+02]

  • In [39]:

    plt.plot(x,y,'ro',label="Dane")plt.xlabel("Rozmiar")plt.ylabel("Czas wykonania")plt.legend(loc='upper left')plt.title("Zagadnienie 3SUM metodą brute-force")plt.show()

    Wykres logarytmiczny powinien być bardziej czytelny:

  • In [41]:

    plt.loglog(x,y,'ro',label="Dane")plt.xlabel("Rozmiar")plt.ylabel("Czas wykonania")plt.legend(loc='upper left')plt.title("Zagadnienie 3SUM metodą brute-force")plt.show()

  • Krok 4  hipotezaSpróbujmy teraz przybliżyć dane przedstawione na powyższym wykresie jakąś "prostą" funkcjąmatematyczną. Ponieważ na wykresie logarytmicznym układają się w linię prostą, spodziewamy sięzależności potęgowej:

    Rzeczywiście, jeśli zlogarytmujemy obustronnie powyższe równanie, otrzymamy

    czyli równanie prostej.

    Ponadto, algorytm użyty w programie 3sum wykorzystuje potrójne zagnieżdżenie. Dlatego przypuszczamy,że czas jego wykonania będzie proporcjonalny do  , gdzie   to rozmiar danych wejściowych.

    In [44]:

    from scipy.optimize import curve_fit

    def func(x, a, b): return a*x**3 + b

    popt, pcov = curve_fit(func, x, y)

    print("a = %s , b = %s" % (popt[0], popt[1]))

    Wynika stąd, że czas wykonania naszego algorytmu spełnia zależność:

    Porównajmy dane i funkcję aproksymującą na wykresie:

    y = axb

    log y = b log x + log a

    N 3 N

    T(N) = 0.0000000214886 ∗ + 0.108065N 3

    a = 2.1488626911e-08 , b = 0.108065584827

  • In [46]:

    x2 = np.arange(1,2000)

    plt.plot(x,y,'ro',label="Dane")plt.plot(x2, func(x2, *popt), label="Hipoteza") plt.xlabel("Rozmiar")plt.ylabel("Czas wykonania")plt.legend(loc='upper left')plt.title("Zagadnienie 3SUM metodą brute-force")plt.show()

    Krok 5  przewidywanieInteresuje nas, ile będzie wykonywał się program dla np.  :N = 1200

  • In [47]:

    func(1200,*popt)

    Krok 6  weryfikacja

    In [48]:

    !python3 3sum_3.py 1200

    Dane empiryczne potwierdzają naszą hipotezę.

    Hipoteza podwojeniaIstnieje sposób na szybkie oszacowanie współczynnika   w prawie potęgowym

    Hipoteza podwojenia (ang. doubling hypothesis) związana jest z próbą odpowiedzi na pytanie:

    Jaki wpływ na czas pracy programu ma podwojenie rozmiaru danych wejściowych?

    Sposób postępowania:

    przygotowujemy tabelę, która zawiera 4 kolumny:rozmiar danych czas wykonania stosunek czasów wykonania logarytm poprzedniej wielkości, tzn. 

    rozmiary wybieramy tak, aby kolejny był dwa razy większy od poprzedniegouruchamiamy program dla tych rozmiarów i mierzymy czasy jego wykonania

    In [59]:

    !for N in 16 32 64 128 256 512 1024; do python3 3sum_3.py $N >> podwojenie.dat; done

    In [61]:

    !cat podwojenie.dat

    b

    T(N) = aN b

    NT(N)

    T(2N)/T(N)(T(2N)/T(N))log2

    Out[47]:

    37.240412886967256

    1200 36.325262

    16 0.00023332 0.00123264 0.007805128 0.054047256 0.389704512 3.2211521024 24.491979

  • In [62]:

    xtab = []ytab = []with open("podwojenie.dat") as f: for line in f: x, y = line.split() xtab.append(int(x)) ytab.append(float(y))

    In [63]:

    xtab

    In [64]:

    ytab

    In [65]:

    ratio = [None]*len(ytab)

    In [66]:

    ratio

    In [67]:

    for i in range(1,len(ytab)): ratio[i] = ytab[i]/ytab[i-1]

    In [68]:

    ratio

    Out[63]:

    [16, 32, 64, 128, 256, 512, 1024]

    Out[64]:

    [0.000233, 0.001232, 0.007805, 0.054047, 0.389704, 3.221152, 24.491979]

    Out[66]:

    [None, None, None, None, None, None, None]

    Out[68]:

    [None, 5.28755364806867, 6.3352272727272725, 6.924663677130044, 7.210464965678021, 8.265637509494386, 7.603484405579122]

  • In [72]:

    import mathlratio = [None]

    In [73]:

    for val in ratio: if val: lratio.append(math.log(val,2))

    In [74]:

    lratio

    In [76]:

    print("{} \t {} \t {} \t {}".format("N", "T", "Ratio", "Log"))for i in range(len(ytab)): print("{} \t {} \t {} \t {}".format(xtab[i], ytab[i], ratio[i], lratio[i]))

    Kontynuując te obliczenia zobaczylibyśmy, że wartość   zbiega do wartości  , tzn.:

    Wartość stałej   możemy wyznaczyć rozwiązując to równanie dla wybranego rozmiaru danych, np.:

    czyli

    lo (T(2N)/T(N))g2 3T(N) = aN 3

    a

    3.221152 = a ∗ 5123

    a = 0, 000000024

    Out[74]:

    [None, 2.4026003960406213, 2.66339637617037, 2.7917440028413196, 2.8500922944243596, 3.0471260955389763, 2.9266607057458383]

    N T Ratio Log16 0.000233 None None32 0.001232 5.28755364806867 2.402600396040621364 0.007805 6.3352272727272725 2.66339637617037128 0.054047 6.924663677130044 2.7917440028413196256 0.389704 7.210464965678021 2.8500922944243596512 3.221152 8.265637509494386 3.04712609553897631024 24.491979 7.603484405579122 2.9266607057458383