Upload
others
View
2
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