Przybliżone za pomocą symulacji Monte Carlo


35

Ostatnio przyglądałem się symulacji Monte Carlo i używałem jej do przybliżania stałych, takich jak (okrąg wewnątrz prostokąta, obszar proporcjonalny).π

Nie jestem jednak w stanie wymyślić odpowiedniej metody aproksymacji wartości e [liczby Eulera] przy użyciu integracji Monte Carlo.

Czy masz jakieś wskazówki, jak to zrobić?


7
Jest na to wiele sposobów. To, że tak jest, może stać się oczywiste, rozważając, co robi Rpolecenie 2 + mean(exp(-lgamma(ceiling(1/runif(1e5))-1))). (Jeśli przeszkadza Ci korzystanie z funkcji log Gamma, zastąp ją 2 + mean(1/factorial(ceiling(1/runif(1e5))-2)), która używa tylko dodawania, mnożenia, dzielenia i obcinania, i ignoruj ​​ostrzeżenia o przepełnieniu). Bardziej interesujące mogą być wydajne symulacje: czy możesz zminimalizować liczbę kroki obliczeniowe potrzebne do oszacowania e do dowolnej dokładności?
whuber

4
Cóż za wspaniałe pytanie! Z niecierpliwością czekam na odpowiedzi innych. Jednym ze sposobów, w jaki naprawdę możesz zwrócić uwagę na to pytanie - być może kolejne pół tuzina odpowiedzi - byłoby zrewidowanie pytania i poproszenie o skuteczne odpowiedzi, jak sugeruje whuber. To jest jak kocimiętka dla użytkowników CV.
Sycorax mówi Przywróć Monikę

1
@EngrStudent Nie jestem pewien, czy geometryczny analog istnieje dla e . Po prostu nie jest to naturalnie (zamierzona gra słów) wielkość geometryczna, taka jak π .
Aksakal

6
@Aksakal e jest wyjątkowo geometryczną wielkością. Na najbardziej elementarnym poziomie pojawia się naturalnie w wyrażeniach dotyczących obszarów związanych z hiperbolami. Na nieco bardziej zaawansowanym poziomie jest ściśle związany ze wszystkimi funkcjami okresowymi, w tym funkcjami trygonometrycznymi, których zawartość geometryczna jest oczywista. Prawdziwym wyzwaniem jest to, że tak łatwo symulować wartości związane z e !
whuber

2
@StatsStudent: e sam w sobie nie jest interesujący. Jeśli jednak prowadzi to do obiektywnych estymatorów wielkości, takich jak
exp{0xf(y)dG(y)}
może się to okazać najbardziej przydatne w algorytmach MCMC.
Xi'an

Odpowiedzi:


34

W tym artykule opisano prosty i elegancki sposób oszacowania przez Monte Carlo . Artykuł dotyczy nauczania . Dlatego podejście wydaje się idealnie pasować do twojego celu. Pomysł opiera się na ćwiczeniu z popularnego rosyjskiego podręcznika teorii prawdopodobieństwa autorstwa Gnedenko. Patrz przykład 22 na str. 183eee

Zdarza się tak, że , gdzie jest zmienną losową, która jest zdefiniowana w następujący sposób. Jest to minimalna liczba taka, że i są liczbami losowymi z rozkładu równomiernego na . Piękne, prawda ?!ξ n n i = 1 r i > 1 r i [ 0 , 1 ]E[ξ]=eξni=1nri>1ri[0,1]

Ponieważ jest to ćwiczenie, nie jestem pewien, czy fajnie jest dla mnie opublikować rozwiązanie (dowód) tutaj :) Jeśli chcesz sam to udowodnić, oto wskazówka: rozdział nazywa się „Chwile”, które powinny wskazywać jesteś we właściwym kierunku.

Jeśli chcesz wdrożyć go samodzielnie, nie czytaj dalej!

Jest to prosty algorytm do symulacji Monte Carlo. Narysuj jednolity losowy, a następnie kolejny i tak dalej, aż suma przekroczy 1. Liczba losowanych losów jest twoją pierwszą próbą. Powiedzmy, że masz:

 0.0180
 0.4596
 0.7920

Potem twoja pierwsza próba sprawiła, że ​​3. Kontynuuj te próby, a zauważysz, że średnio dostajesz .e

Poniżej znajduje się kod MATLAB, wynik symulacji i histogram.

N = 10000000;
n = N;
s = 0;
i = 0;
maxl = 0;
f = 0;
while n > 0
    s = s + rand;
    i = i + 1;
    if s > 1
        if i > maxl
            f(i) = 1;
            maxl = i;
        else
            f(i) = f(i) + 1;
        end
        i = 0;
        s = 0;
        n = n - 1;
    end
end

disp ((1:maxl)*f'/sum(f))
bar(f/sum(f))
grid on

f/sum(f)

Wynik i histogram:

2.7183


ans =

  Columns 1 through 8

         0    0.5000    0.3332    0.1250    0.0334    0.0070    0.0012    0.0002

  Columns 9 through 11

    0.0000    0.0000    0.0000

wprowadź opis zdjęcia tutaj

AKTUALIZACJA: Zaktualizowałem swój kod, aby pozbyć się szeregu wyników próbnych, aby nie zajmował pamięci RAM. Wydrukowałem również oszacowanie PMF.

Aktualizacja 2: Oto moje rozwiązanie Excel. Umieść przycisk w programie Excel i połącz go z następującym makrem VBA:

Private Sub CommandButton1_Click()
n = Cells(1, 4).Value
Range("A:B").Value = ""
n = n
s = 0
i = 0
maxl = 0
Cells(1, 2).Value = "Frequency"
Cells(1, 1).Value = "n"
Cells(1, 3).Value = "# of trials"
Cells(2, 3).Value = "simulated e"
While n > 0
    s = s + Rnd()
    i = i + 1
    If s > 1 Then
        If i > maxl Then
            Cells(i, 1).Value = i
            Cells(i, 2).Value = 1
            maxl = i
        Else
            Cells(i, 1).Value = i
            Cells(i, 2).Value = Cells(i, 2).Value + 1
        End If
        i = 0
        s = 0
        n = n - 1
    End If
Wend


s = 0
For i = 2 To maxl
    s = s + Cells(i, 1) * Cells(i, 2)
Next


Cells(2, 4).Value = s / Cells(1, 4).Value

Rem bar (f / Sum(f))
Rem grid on

Rem f/sum(f)

End Sub

Wprowadź liczbę prób, na przykład 1000, w komórce D1 i kliknij przycisk. Oto jak powinien wyglądać ekran po pierwszym uruchomieniu:

wprowadź opis zdjęcia tutaj

AKTUALIZACJA 3: Silverfish zainspirował mnie do innej drogi, nie tak eleganckiej jak pierwsza, ale wciąż fajnej. Obliczył objętości n-simpleksów przy użyciu sekwencji Sobola .

s = 2;
for i=2:10
    p=sobolset(i);
    N = 10000;
    X=net(p,N)';
    s = s + (sum(sum(X)<1)/N);
end
disp(s)

2.712800000000001

Przypadkowo napisał pierwszą książkę o metodzie Monte Carlo, którą przeczytałem w szkole średniej. Moim zdaniem jest to najlepsze wprowadzenie do metody.

AKTUALIZACJA 4:

Silverfish w komentarzach sugerował prostą implementację formuły Excel. Taki wynik uzyskuje się po jego podejściu po około 1 milionie losowych liczb i 185 000 prób:

wprowadź opis zdjęcia tutaj

Oczywiście jest to znacznie wolniejsze niż wdrożenie Excel VBA. Zwłaszcza jeśli zmodyfikujesz mój kod VBA, aby nie aktualizować wartości komórek w pętli i zrobisz to dopiero po zebraniu wszystkich statystyk.

AKTUALIZACJA 5

Xi'an za rozwiązanie nr 3 jest ściśle powiązany (lub nawet taki sam w pewnym sensie jako komentarz na JWG w wątku). Trudno powiedzieć, kto wpadł na ten pomysł jako pierwszy Forsythe lub Gnedenko. Oryginalna edycja Gnedenko z 1950 roku w języku rosyjskim nie zawiera sekcji Problemy w rozdziałach. Tak więc nie mogłem znaleźć tego problemu na pierwszy rzut oka, gdzie jest w późniejszych wydaniach. Może został dodany później lub zakopany w tekście.

Jak skomentowałem w odpowiedzi Xi'ana, podejście Forsythe'a wiąże się z innym interesującym obszarem: rozkładem odległości między pikami (ekstrema) w losowych sekwencjach (IID). Średnia odległość zdarza się wynosić 3. Sekwencja dolna w podejściu Forsythe'a kończy się na dole, więc jeśli będziesz kontynuować próbkowanie, w pewnym momencie dostaniesz kolejne dno, a potem inne. Możesz śledzić odległość między nimi i zbudować rozkład.


Wow, to super! Czy możesz dodać akapit lub dwa wyjaśniające, dlaczego to działa?
Sycorax mówi Przywróć Monikę

7
(+1) Genialne! Odpowiedź zasługuje na najwyższą ocenę, ponieważ opiera się tylko na jednolitych symulacjach. I nie używa żadnego przybliżenia, tylko z powodu Monte Carlo. To, że łączy się ponownie z Gnedenko, jest dodatkowym atutem.
Xi'an

2
Fajne! Oto kod Mathematica dla tego samego, jako
Mean[Table[ Length[NestWhileList[(Random[]+#) &, Random[], #<1&]], {10^6}]]
jednowierszowego

4
@wolfies Następujące bezpośrednie tłumaczenie Rrozwiązania, które zamieściłem w odpowiedzi n=10^6; 1. / Mean[UnitStep[Differences[Sort[RandomReal[{0, n}, n + 1]]] - 1]]
Xi'ana,

1
Opublikowałem „dlaczego to znaczy ?” pytanie samo w sobie ; Podejrzewam, że moje rozwiązanie szkicu (które natychmiast przyszło mi do głowy jako „oczywista” wizualizacja problemu) niekoniecznie jest tak, jak zamierzali to zrobić rosyjscy studenci! Dlatego alternatywne rozwiązania byłyby bardzo mile widziane. e
Silverfish,

19

Sugeruję, by głosować na odpowiedź Aksakala. Jest bezstronny i opiera się wyłącznie na metodzie generowania odchyleń jednostkowych jednostek.

Moja odpowiedź może być dowolnie sprecyzowana, ale nadal jest stronnicza od prawdziwej wartości .e

Odpowiedź Xi'ana jest poprawna, ale myślę, że jej zależność od funkcji lub sposobu generowania losowych odchyleń Poissona jest nieco okrągła, gdy celem jest przybliżenie .eloge

Oszacowanie przez ładowanie początkowee

Zamiast tego rozważ procedurę ładowania. Jeden ma dużą liczbę obiektów które są rysowane z zamianą na wielkość próbki . Przy każdym losowaniu prawdopodobieństwo nie rysowania określonego obiektu wynosi i jest takich losowań. Prawdopodobieństwo pominięcia określonego obiektu we wszystkich losowaniach wynosin i 1 - n - 1 n p = ( 1 - 1nni1n1np=(11n)n.

Ponieważ zakładam, że wiemy, że

exp(1)=limn(11n)n

więc możemy też napisać

exp(1)p^=i=1mIiBjm

Oznacza to, że nasze oszacowanie można znaleźć poprzez oszacowanie prawdopodobieństwa pominięcia konkretnej obserwacji w bootstrapie replikuje w wielu takich replikacjach - tj. występowania obiektu w bootstrapie.m B j ipmBji

Są dwa źródła błędów w tym przybliżeniu. Skończone zawsze oznacza, że ​​wyniki są przybliżone, tj. Oszacowanie jest stronnicze. Dodatkowo będzie oscylować wokół prawdziwej wartości, ponieważ jest to symulacja.tnp^

Uważam to podejście za urocze, ponieważ student lub inna osoba z wystarczającą ilością rzeczy do zrobienia może przybliżyć za pomocą talii kart, stosu małych kamieni lub innych dostępnych przedmiotów, w tym samym stylu, co osoba może oszacować używając kompasu, prostej krawędzi i drobinek piasku. Myślę, że to fajne, kiedy matematykę można oddzielić od nowoczesnych udogodnień, takich jak komputery.πeπ

Wyniki

Przeprowadziłem kilka symulacji dla różnej liczby replik ładowania początkowego. Standardowe błędy są szacowane w normalnych odstępach czasu.

Zauważ, że wybór liczby obiektów ładowanych początkowo ustanawia absolutną górną granicę dokładności wyników, ponieważ procedura Monte Carlo szacuje a zależy tylko od . Ustawienie niepotrzebnie dużej wartości tylko obciąży komputer, albo dlatego, że potrzebujesz tylko „przybliżonego” przybliżenia do albo dlatego, że odchylenie zostanie zatłoczone przez wariancję z powodu Monte Carlo. Te wyniki są dla a jest dokładne z dokładnością do trzeciego miejsca po przecinku.p p n n e n = 10 3 p - 1enppnnen=103p1e

Ten wykres pokazuje, że wybór ma bezpośrednie i głębokie konsekwencje dla stabilności w . Niebieska linia przerywana pokazuje a czerwona linia pokazuje . Zgodnie z oczekiwaniami, zwiększenie wielkości próby daje coraz dokładniejsze szacunki . s t e smp^pep^wprowadź opis zdjęcia tutaj

Napisałem do tego żenująco długi skrypt R. Sugestie dotyczące ulepszeń można przesłać na odwrocie rachunku za 20 USD.

library(boot)
library(plotrix)
n <- 1e3

## if p_hat is estimated with 0 variance (in the limit of infinite bootstraps), then the best estimate we can come up with is biased by exactly this much:
approx <- 1/((1-1/n)^n)

dat <- c("A", rep("B", n-1))
indicator <- function(x, ndx)   xor("A"%in%x[ndx], TRUE) ## Because we want to count when "A" is *not* in the bootstrap sample

p_hat <- function(dat, m=1e3){
    foo <- boot(data=dat, statistic=indicator, R=m) 
    1/mean(foo$t)
} 

reps <- replicate(100, p_hat(dat))

boxplot(reps)
abline(h=exp(1),col="red")

p_mean <- NULL
p_var <- NULL
for(i in 1:10){
    reps <- replicate(2^i, p_hat(dat))
    p_mean[i] <- mean(reps)
    p_var[i] <- sd(reps)
}
plotCI(2^(1:10), p_mean, uiw=qnorm(0.975)*p_var/sqrt(2^(1:10)),xlab="m", log="x", ylab=expression(hat(p)), main=expression(paste("Monte Carlo Estimates of ", tilde(e))))
abline(h=approx, col='red')

4
+1 Ma to sens. Czy jest szansa, że ​​możesz podzielić się swoim kodem, jeśli go napisałeś?
Antoni Parellada,

2
Choć może to być dowolnie dokładne, ostatecznie jest niezadowalająca, ponieważ tylko symuluje zbliżania się zamiast sama. eee
whuber

1
Pewnie. Zakończyłbyś się tylko jednym powtórzeniem wewnątrz drugiego, co jest w zasadzie takie samo jak teraz.
Sycorax mówi Przywróć Monikę

1
@ whuber Naprawdę nie widzę różnicy między arbitralnie dokładnym przybliżeniem do arbitralnie dokładnego przybliżenia do , a arbitralnie dokładnym przybliżeniem do samego . eee
jwg

1
@jwg Oprócz tego, że jest to ważne z punktu widzenia koncepcyjnego, jest także praktycznie ważne, ponieważ implementacja aproksymacji do aproksymacji wymaga śledzenia dokładności każdego z tych dwóch aproksymacji. Ale musiałbym się zgodzić, że gdy oba przybliżenia są akceptowalnie dobre, ogólne podejście rzeczywiście jest w porządku.
whuber

14

Rozwiązanie 1:

Dla Poissona dystrybucja Dlatego, jeśli , co oznacza, że ​​możesz oszacować za pomocą symulacji Poissona. Symulacje Poissona można uzyskać z generatora rozkładu wykładniczego (jeśli nie w najbardziej efektywny sposób).P (P.(λ) X P ( 1 ) P ( X = 0 ) = P ( X = 1 ) = e - 1 e - 1

P.(X=k)=λkk!mi-λ
XP.(1)
P.(X=0)=P.(X=1)=mi-1
mi-1

Uwaga 1: Jak omówiono w komentarzach, jest to dość skomplikowany argument, ponieważ symulowanie z rozkładu Poissona lub równoważnie rozkładu wykładniczego może być trudne do wyobrażenia bez udziału log lub funkcji exp ... Ale potem W. Huber doszedł do uratowanie tej odpowiedzi za pomocą najbardziej eleganckiego rozwiązania opartego na zamówionych mundurach. Co jest jednak przybliżeniem , ponieważ rozkład jednolitych odstępów jest Beta , co sugeruje, że który jest zbieżny do jakoU(ja:n)-U(ja-1:n)b(1,n)

P.(n{U(ja:n)-U(ja-1:n)}1)=(1-1n)n
mi-1nrośnie do nieskończoności. Oprócz tego, że odpowiada na komentarze, generator wykładniczy von Neumanna z 1951 r. Używa tylko generacji jednorodnych.

Rozwiązanie 2:

Innym sposobem uzyskania reprezentacji stałej jako całki jest przypomnienie, że gdy to który jest również rozkładem . Dlatego Drugie podejście do przybliżenia przez Monte Carlo ma zatem symulować pary normalne i monitorować częstotliwość razy . W pewnym sensie jest to przeciwieństwo aproksymacji Monte Carlo związane z częstotliwością razy ...mi

X1,X2iidN(0,1)
(X12+X22)χ12
E(1/2)
P(X12+X222)=1{1exp(2/2)}=e1
eX 2 1 + X 2 22 π X 2 1 + X 2 2(X1,X2)X12+X222πX12+X22<1

Rozwiązanie 3:

Mój kolega z Uniwersytetu w Warwick, M. Pollock, wskazał inne przybliżenie Monte Carlo zwane metodą Forsythe'a : chodzi o to, by uruchomić sekwencję ujednoliconych generacji aż do . Oczekiwanie na odpowiednią regułę zatrzymania, , która jest liczbą przypadków, w których jednorodna sekwencja spadła, wynosi wtedy podczas gdy prawdopodobieństwo, że jest nieparzyste, wynosi ! ( Metoda Forsythe'a faktycznie ma na celu symulację z dowolnej gęstości formy , stąd jest bardziej ogólna niż przybliżenie i .)u n + 1 > u n N e N e - 1 exp G ( x ) e eu1,u2,...un+1>unNeNe1expG(x)ee1

Jest to dość równoległe do podejścia Gnedenko zastosowanego w odpowiedzi Aksakala , więc zastanawiam się, czy jedno można wyprowadzić z drugiego. Przynajmniej oba mają ten sam rozkład z masą prawdopodobieństwadla wartości .n1/n!n

Szybka implementacja metody Forsythego R polega na rezygnacji z dokładnego wykonywania sekwencji mundurów na rzecz większych bloków, co pozwala na równoległe przetwarzanie:

use=runif(n)
band=max(diff((1:(n-1))[diff(use)>0]))+1
bends=apply(apply((apply(matrix(use[1:((n%/%band)*band)],nrow=band),
2,diff)<0),2,cumprod),2,sum)

12
Dopóki ktoś wie, jak przeprowadzić symulację Poissona, nie znając . e
Glen_b

5
Jeśli wywołam generator R rpoiss (), mogę udawać, że nie znam . Mówiąc poważniej, można wygenerować zmienne wykładnicze [używając funkcji zamiast ], dopóki suma nie przekroczy a wynikowa liczba minus jeden to Poisson . E ( 1 ) log e 1 P ( 1 )eE(1)loge1P(1)
Xi'an

5
logexpn <- 1e5; 1/mean(n*diff(sort(runif(n+1))) > 1)

3
xnnxixn1n1xi1nxi1n1xi

3
n+1n

7

To nie rozwiązanie ... tylko szybki komentarz, który jest za długi na pole komentarza.

Aksakal

Aksakal opublikował rozwiązanie, w którym obliczamy oczekiwaną liczbę standardowych rysunków Uniform, które należy pobrać, tak aby ich suma przekroczyła 1. W Mathematica moim pierwszym sformułowaniem było:

mrM := NestWhileList[(Random[] + #) &, Random[], #<1 &]

Mean[Table[Length[mrM], {10^6}]] 

EDYCJA: Właśnie się z tym pobawiłem, a następujący kod (ta sama metoda - także w Mma - tylko inny kod) jest około 10 razy szybszy:

Mean[Table[Module[{u=Random[], t=1},  While[u<1, u=Random[]+u; t++]; t] , {10^6}]]

Xian / Whuber

Whuber zasugerował szybki fajny kod do symulacji rozwiązania Xian 1:

Wersja R: n <- 1e5; 1/mean(n*diff(sort(runif(n+1))) > 1)

Wersja Mma: n=10^6; 1. / Mean[UnitStep[Differences[Sort[RandomReal[{0, n}, n + 1]]] - 1]]

który zauważa, że ​​jest 20 razy szybszy niż pierwszy kod (lub około dwa razy szybciej niż nowy kod powyżej).

Dla zabawy pomyślałem, że byłoby interesujące sprawdzić, czy oba podejścia są tak skuteczne (w sensie statystycznym). W tym celu wygenerowałem 2000 oszacowań e przy użyciu:

  • Metoda Aksakala: dane A.
  • Metoda Xiana 1 przy użyciu kodu Whuber: dataB

... oba w Mathematica . Poniższy diagram porównuje nieparametryczne oszacowanie gęstości jądra wynikowych zestawów danych dataA i dataB.

wprowadź opis zdjęcia tutaj

Tak więc, chociaż kod Whubera (czerwona krzywa) jest około dwa razy szybszy, metoda nie wydaje się być „niezawodna”.


Pionowa linia w miejscu prawdziwej wartości znacznie poprawiłaby ten obraz.
Sycorax mówi Przywróć Monikę

1
To bardzo interesujące spostrzeżenie, dziękuję. Ponieważ połowa szerokości będzie skalować się kwadratowo wraz z rozmiarem symulacji, a połowa szerokości metody Xi'ana jest około dwa razy większa niż metody Aksakala, a następnie wykonanie czterech razy większej liczby iteracji sprawi, że będą one równie dokładne. Pozostaje pytanie, ile wysiłku potrzeba w każdej iteracji: jeśli jedna iteracja metody Xi'ana zajmuje mniej niż jedną czwartą wysiłku, wówczas metoda ta byłaby jeszcze bardziej wydajna.
whuber

1
n

1
running four times as many iterations will make them equally accurate106106

1
Dobra robota z kodem - trudno będzie wiele poprawić.
whuber

2

Metoda wymagająca bezbożnej ilości próbek

f(x)=exx¯12n˙N(0,1)e

N(0,1)ex

N(0,1)ϕ^(x)ϕ((2))=(2π)1/2e1e=ϕ^(2)2π

22π

Metoda wymagająca bardzo niewielu próbek, ale powodująca bezbożną ilość błędów numerycznych

Całkowicie głupia, ale bardzo skuteczna odpowiedź na podstawie mojego komentarza:

Xuniform(1,1)Yn=|(x¯)n|e^=(1Yn)1/Yn

To zbiegnie się bardzo szybko, ale również napotka ekstremalny błąd numeryczny.

Yn1/YnnYnYn=0e


2
e

1
@ whuber: Nie korzystałem z Box-Mullera z powodu wymaganej transformacji dziennika zbyt bezpośrednio, aby wykładniczy w mojej książce. I to już odruchowo dozwolone cos i grzechu, ale to było tylko dlatego, że zapomniał o złożonej analizy przez chwilę, więc dobry punkt.
Cliff AB,

1
n1n2ϕ(2)n1n2en2n1

2

Oto inny sposób, w jaki można to zrobić, choć jest on dość wolny. Nie rości sobie pretensji do skuteczności, ale oferuję tę alternatywę w duchu kompletności.

nU1,,UnIID U(0,1)mi

mi(ja(Uja1/mi)Uja)=1/mi1reuu=1.

eu(1)u(n)

Sn(k)1ni=1k1u(i)for all k=1,..,n.

mmin{k|S(k)1}1/emi

e^2u(m)+u(m+1).

1/eee

Implementacja w R: Metodę można zaimplementować przy Rużyciu runifdo generowania jednolitych wartości. Kod jest następujący:

EST_EULER <- function(n) { U <- sort(runif(n), decreasing = TRUE);
                           S <- cumsum(1/U)/n;
                           m <- min(which(S >= 1));
                           2/(U[m-1]+U[m]); }

e

set.seed(1234);

EST_EULER(10^3);
[1] 2.715426

EST_EULER(10^4);
[1] 2.678373

EST_EULER(10^5);
[1] 2.722868

EST_EULER(10^6); 
[1] 2.722207

EST_EULER(10^7);
[1] 2.718775

EST_EULER(10^8);
[1] 2.718434

> exp(1)
[1] 2.718282

e

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.