Ta strona wykorzystuje ciasteczka ("cookies") w celu zapewnienia maksymalnej wygody w korzystaniu z naszego serwisu. Czy wyrażasz na to zgodę?

Czytaj więcej
< All Topics
Print

Liczby i obiekty losowe

Liczby pseudolosowe

 

Losowość kojarzymy z totalnym bałaganem, na przykład rozsypanymi cukierkami różnych rodzajów, które ktoś zmiótł do kosza nie próbując ich segregować. Biorąc taki cukierek z kosza bez patrzenia, nie wiemy czy trafimy na landrynkę, krówkę czy pomadkę czekoladową. Istnienie jakiegokolwiek algorytmu, który ułożyłby te cukierki w koszu, wydaje się negować ich losowe ułożenie. Mimo to nie znając tego algorytmu nadal nie będziemy wiedzieć na jaki rodzaj cukierka trafimy i nadal będziemy mogli mówić o losowości trafienia na czekoladkę. Dotyczy to zwłaszcza takich algorytmów, które mieszają ze sobą różne rodzaje cukierków.

Idea tworzenia liczb losowych za pomocą algorytmu wynikła właśnie z takich rozważań. Należy po prostu znaleźć taki algorytm, którego wyniki dają w ciągi pomieszanych za sobą liczb, tak że bez znajomości algorytmu nie można będzie przewidzieć, jaka będzie liczba następna. Najprostszymi takimi algorytmami są ciągi rekurencyjne:

x0(xn+1)=reszta z dzielenia (a·xn+b) przez cdla a i b większych od c (tak aby wynik działania a·xn+b wielokrotnie przewyższał c). Dla liczb a i b nie mających wspólnego dzielnika na ogół powstaje ciąg liczb, aczkolwiek okresowy, który ma w obrębie jednego okresu (wielokrotnie dłuższego niż liczba c) wyniki przemieszane tak, że odgadnięcie następnej bez znajomości a, b i c, jest niemożliwe.

 

Współczesne programy stosują bardziej zaawansowane algorytmy wyliczające liczby pseudolosowe, Ich opis albo literaturę źródłową można znaleźć w dokumentacji. Ważne jest to, że spełniają one testy losowości. To znaczy, że wykonując teoretyczne przewidywania jaki będzie wynik jakiś symulowanych zdarzeń losowych w komputerze i porównując go z wynikiem uzyskanym w wyniku symulacji z użyciem liczb pseudolosowych, otrzymujemy dużą zgodność. Dla tak sprawdzonych algorytmów mówimy, że generują one liczby losowe. Zawsze jednak trzeba zacząć od jakiegoś x0 zwanego ziarnem (seed). Ciagi generowane od tego samego “ziarna” będą identyczne. Dlatego też często za seed przyjmuje się odczyt aktualnego czasu przez zegar systemowy (który jest liczbą sekund jaka minęła od dnia 1.01.1977, godz.00:00:00 BST), co zapewnia różne wyniki po powtarzaniu symulacji, o ile nie robi się tego w czasie krótszym niż sekunda.

 

 

Generowanie liczb losowych

Funkcje generujące liczby losowe z różnych rozkładów znajdują się w bibliotece ‘random’, która trzeba zaimportować. Każdy z poniższych programów inicjowany jest przez wskazania zegara systemowego.

Funkcja ‘random()’ generuje liczby zmiennoprzecinkowe z przedziału (0,1]. Każda z tych liczb może pojawić się z jednakowym prawdopodobieństwem.

 

import random
print(random.random())
import random
print(random.random())
import random
print(random.random())
>>>
3
>>>
3
>>>
2

Funkcja randint(k,n) umożliwia losowanie liczb całkowitych ze zbioru {k,k+1,k+2,…,n-1}. Każda z tych liczb losowana jest z jednakowym prawdopodobieństwem.

 

import random
print(random.randint(0,5))
import random
print(random.randint(0,5))
import random
print(random.randint(0,5))
>>>
0.9628533308567098
>>>
0.15607168471794952
>>>
0.1441307995034934

Losowe wybieranie liczb całkowitych z zakresu od k do n można realizować za pomocą funkcji random.randrange(). Randrange(n) oznacza wybieranie jednej liczby spośród {0,1,…,n-1}, randrange(k,n) oznacza wybieranie jednej liczby spośród {k,k+1,…,n-1} natomiast randrange(k,n,m) oznacza wybieranie jednej liczby spośród: {k,k+m,k+2m,…,k+im} gdzie k+im<n. Funkcja randint() wybiera liczbę x z zakresu k≤x≤n. Można to prześledzić uruchamiając następujące skrypty.

from random import randrange
print(randrange(5))
print(randrange(5))
print(randrange(5))
from random import randrange
print(randrange(1,5))
print(randrange(1,5))
print(randrange(1,5))
from random import randrange
print(randrange(2,15,2))
print(randrange(2,15,2))
print(randrange(2,15,2))
>>>
0
4
1
>>>
3
3
4
>>>
4
10
6

W modelach często trzeba wybrać losowy element z listy. Służy do tego funkcja choice(). Każdy z elementów listy wybierany jest z jednakowym prawdopodobieństwem.

from random import choice
lista=[“Ala”,”Ola”,”Ela”,”Ula”] print(choice(lista))
from random import choice
lista=[“Ala”,”Ola”,”Ela”,”Ula”] print(choice(lista))
from random import choice
lista=[“Ala”,”Ola”,”Ela”,”Ula”] print(choice(lista))
>>>
Ula
>>>
Ela
>>>
Ala

Odmiana funkcji choice() jest funkcja choices(lista,praw,k=n), gdzie lista jest listą elementów, praw – listą prawdopodobieństw wyboru poszczególnych elementów (a przynajmniej proporcjonalną do prawdopodobieństw), a n liczbą wybieranych elementów. Parametr k= musi wystąpić, gdyż w przeciwnym przypadku generowany jest błąd. Wybieranie to robione jest ze zwracaniem.

from random import choices
lista=["Ala","Ola","Ela","Ula"]
prawd=[0.3, 0.2, 0.35, 0.15]
print(choices(lista,prawd,k=5)) 
from random import choices
lista=["Ala","Ola","Ela","Ula"]
prawd=[0.3, 0.2, 0.35, 0.15]
print(choices(lista,prawd,k=5)) 
from random import choices
lista=["Ala","Ola","Ela","Ula"]
prawd=[0.3, 0.2, 0.35, 0.15]
print(choices(lista,prawd,k=5)) 
>>>
['Ala', 'Ola', 'Ala', 'Ala', 'Ela']
>>>
['Ula', 'Ela', 'Ela', 'Ala', 'Ola']
>>>
['Ela', 'Ala', 'Ela', 'Ala', 'Ala']

Wybieranie różnoelementowej próby elementów spośród podanej listy można realizować za pomocą funkcji sample(lista,k). Gdy k jest równe liczbie elementów w liście to w efekcie funkcja ta zmienia losowo kolejność elementów. Trzeba ja przyporządkować innej liście by zobaczyć efekty.

import random
lista=[“Ala”,”Ola”,”Ela”,”Ula”,”Iga”, “Ada”, “Ewa”,”Iza”] lista2=random.sample(lista,8)
print(lista2)
import random
lista=[“Ala”,”Ola”,”Ela”,”Ula”,”Iga”, “Ada”, “Ewa”,”Iza”] lista2=random.sample(lista,8)
print(lista2)
>>>
[‘Ola’, ‘Ewa’, ‘Iga’, ‘Iza’, ‘Ula’]
>>>
[‘Iza’, ‘Ula’, ‘Ela’, ‘Iga’, ‘Ola’]

Metoda shuffle() służy do zamiany kolejności elementów w liście. Jej argumentem jest lista.

import random
lista=[“Ala”,”Ola”,”Ela”,”Ula”,”Iga”, “Ada”, “Ewa”,”Iza”] random.shuffle(lista)
print(lista)
import random
lista=[“Ala”,”Ola”,”Ela”,”Ula”,”Iga”, “Ada”, “Ewa”,”Iza”] random.shuffle(lista)
print(lista)
>>>
[‘Ala’, ‘Ada’, ‘Ewa’, ‘Iga’, ‘Ola’, ‘Ela’, ‘Iza’, ‘Ula’]
>>>
[‘Iza’, ‘Ewa’, ‘Ada’, ‘Iga’, ‘Ula’, ‘Ala’, ‘Ela’, ‘Ola’]

Metoda shuffle() działa tylko na listach liczących mniej niż 2080 elementów.

 

Generowanie liczb pochodzących z rozkładów definiowanych w matematyce

Do losowania liczb rzeczywistych z wybranych rozkładów liczbowych służą funkcje:

  • uniform(a,b) – liczba z rozkładu jednostajnego skoncentrowanego na odcinku [a,b]
  • triangular(a,m,b) – liczba z rozkładu trójkątnego skoncentrowanego na odcinku [a,b] o wartości maksymalnej w punkcie m.
  • betavariate(alpha,beta) – liczba z rozkładu beta o parametrach alpha i beta.
  • expovariate(lambda) – liczba z rozkładu wykładniczego o parametrze lambda.
  • gammavariate(alpha,beta) – liczba z rozkładu gamma o parametrach alpha, beta.
  • gauss(mu,sigma) – liczba z rozkładu normalnego o parametrach mu i sigma.
  • lognormvariate(mu,sigma) – liczba z rozkładu lognormalnego o parametrach mu i sigma.
  • normalvariate(mu, sigma) – liczba z rozkładu normalnego o parametrach mu i sigma. Wolniejsza niż random.gauss().
  • vonmisesvariate(mu,kappa) – kąt w radianach losowany z rozkładu von Mises’a (kołowy rozkład normalny) o parametrach mu i kappa.
  • paretovariate(alpha) – liczba z rozkładu Pareto o parametrze alpha.
  • weibullvariate(alpha,beta) – liczba z rozkładu Weibulla o parametrze alpha i beta.

Wszystkie te funkcje działają według schematu;

import random
print(random.gauss(sigma=20,mu=70))
import random
print(random.gauss(70,20))
>>>
40.81303619471783
>>>
91.65890526837195

Gdy przy wstawianiu parametrów stosuje się nazwy przypisane do danej funkcji, to można zmienić ich kolejność. Gdy pomija się te nazwy, przypisanie do określonych parametrów rozkładu następuje według właściwej kolejności.

Spis treści