Im folgenden sollen die Eigenschaften von Generatoren mit verschiedenen Parametersets untersucht werden.
Dazu benötigt man zunächst einen Zufallsgenerator, den man einfach als C++ Klasse implementieren kann (file MyRnd.C).
Die Implementation des Zufallsgenerators als C++ Klasse hat wesentliche Vorteile gegenüber einer konventionellen Implementation als Funktion: alle Instanzen von MyRnd sind völlig unabhängig, d.h. man kann beliebig viele Zufallsgeneratoren mit unterschiedlichen Seeds und Parametern verwenden.
Einfache Tests von Zufallsgeneratoren sind die Überprüfung der Gleichverteilung in 1, 2 oder 3 Dimensionen.
Beispielprogramm tRnd.C:
Aufgabe a:
Testen Sie verschiedene Parameter für den Zufallsgenerator:
(a)
(b)
(c)
Als seed sollte man eine Zahl verwenden.
(a) und (b) sind `kurze' Generatoren. Sie nutzen die Länge voll aus,
zeigen aber deutliche Unterschiede in ihrer Qualität in 2 D.
(c) ist der Generator randu von IBM, der in den 60er und 70er
Jahren weitverbreitet war. Er hat zwar eine hohe Periode (),
aber ist lausig gewählt, schon in 3 D zeigen sich
deutliche Abweichungen von der Gleichverteilung.
Viele wissenschaftliche Arbeiten haben darunter gelitten ...
Zum Vergleich können Sie auch den ROOT Standard Generator mit gRandom->Rndm() betrachten.
Testen Sie zunächst das Programm für verschiedene Parameter. Dann ändern Sie das Programm so ab, daß Sie viele solcher Experimente durchführen und zusätzlich die Zahl der zerfallenen Teilchen für einige Zeitintervalle histogrammieren.
// simulate radioactive decay void tdecay( Float_t lambda = 0.5, Float_t dt = 0.01, Float_t t = 20, Int_t n0 = 1000 ) { TH1F * hdec = new TH1F("hdec", "radioactive decay", t/dt, 0, t); // loop over time for ( Float_t tnow = 0.; tnow < t; tnow += dt ) { // loop over remaining particles Int_t ndec = 0; for ( int ie = 0; ie < n0; ie++ ) { if ( gRandom->Rndm() < dt*lambda ) { ndec ++; hdec->Fill(tnow); }} n0 -= ndec; // subtract decayed particles } }
Erzeugen Sie eine beliebige Zufallsverteilung nach dem Hit&Miss Verfahren, z.B. für die Breit-Wigner Funktion (BreitWig.C).
Hinweis: Funktionen als Macros
Neben der direkten Art Funktionen zu definieren,
wie in
TF1 *f1 = new TF1("f1","sin(x)", 0, 10 );
kann man auch eine Funtkion als Adresse angeben, z.B.:
// file BreitWig.C Double_t BreitWig( Double_t *x, Double_t *par) { // Breit- Wigner function Double_t mw = par[0], gw = par[1], mw2, gw2, eb2; mw2 = mw*mw; gw2 = gw*gw; eb2 = x[0]*x[0]; return( gw2*mw2 / ( pow( eb2 - mw2, 2 ) + mw2 * gw2 ) ); } root [0] .L BreitWig.C root [3] TF1 *f1 = new TF1("f1",BreitWig,50,100,2) root [4] f1->SetParameters( 80., 2.); root [5] f1->Draw();
Als 5. Argument von TF1(..) muss die Zahl der Parameter
stehen. Die Parameter können dann per f1->SetParameters()
gesetzt werden.
Zufallszahlen die gemäss einer Funktion verteilt sind
können in ROOT mit der Methode TF1::GetRandom() erzeugt
werden, also z.B.:
root [5] f1->GetRandom()
GDuckeck 2018-04-10