2012-03-31 5 views
2

Ich kann nicht viel Dokumentation der Boost-Version von discrete_distribution finden. Nach viel Google-Suche kann ich noch nicht einmal eine Liste von Methoden finden, die diese Klasse hat, und ob einer von ihnen funktioniert, um die Wahrscheinlichkeiten neu zuzuordnen.Ist boost :: random :: discrete_distribution dynamisch resizierbar?

In meinem Fall schreibe ich einen evolutionären Dynamikalgorithmus. Bei jedem Zeitschritt können Mitglieder der Population zufällig ausgewählt werden, um entweder zu sterben oder sich zu vermehren. Aus diesem Grund wird die Gesamtzahl der Einträge in meiner diskreten Distribution fast jede Iteration ändern.

Ich möchte ein einzelnes Objekt haben, das ich vor dem Start der Simulation definiere, genannt gillespie_dist (die diskrete Verteilung, die diesen Gillespie-Algorithmus steuert). Aber ich möchte am Ende jeder Iteration möglicherweise spezifische Werte ändern und/oder neue Werte zu gillespie_dist hinzufügen und insbesondere keine neuen Instanzen der diskreten_Distribution bei jeder Iteration erstellen.

Was ist ein guter Ansatz dafür. Gibt es Methoden, um einen neuen Wert auf das Objekt discrete_distribution zu schieben, Methoden, um den Wert einer Distribution an einem bestimmten Index zu ändern, oder noch besser, die gesamte Distribution "neu zu initialisieren", indem die Vektoriterator-Idee here verwendet wird?

+0

'std :: discrete_distribution' kann mit der Memberfunktion [' param'] (http://en.cppreference.com/w/cpp/numeric/random/discrete_distribution/param) vollständig re-initialisiert werden wäre kaum günstiger als eine neue "diskrete Verteilung".Ich glaube nicht, dass diese Klassen kleine Updates effizient unterstützen sollen. – leftaroundabout

+0

Wie aus dem vorherigen Kommentar hervorgeht, ist std :: discrete_distribution eine Standardfunktion von C++ seit dem letzten Jahr: http://en.cppreference.com/w/cpp/numeric/random/discrete_distribution –

+0

Bekannt, aber wie in meinem Kommentar zu der Antwort unten, ich denke, das war ein Versions-Problem. Ich bekomme 'Fehler:' diskrete_verteilung 'ist kein Mitglied von' std ', wenn ich versuche, 'std :: diskret_distribution' zu verwenden. Ich werde in Kürze aktualisieren und die Dinge sollten dann glatter sein. – ely

Antwort

1

Ich schaute in den Code des gcc libstdC++ 4.7 Implementierung von std :: discrete_distribution.

Die Gewichte werden als vector<double> in einem privaten Mitglied gespeichert. Auf die resize-Methode in der öffentlichen Schnittstelle kann nicht zugegriffen werden.

Ich werde versuchen und die Implementierung seines Operators() ausgraben (was in der cpp aussieht wie es aussieht), sollte es kein Problem sein, Ihre eigenen zu rollen.

Hier ist die Hauptsache, und meine Erklärung folgende:

template<typename _IntType> 
    void 
    discrete_distribution<_IntType>::param_type:: 
    _M_initialize() 
    { 
     if (_M_prob.size() < 2) 
     { 
      _M_prob.clear(); 
      return; 
     } 

     const double __sum = std::accumulate(_M_prob.begin(), 
              _M_prob.end(), 0.0); 
     // Now normalize the probabilites. 
     __detail::__transform(_M_prob.begin(), _M_prob.end(), _M_prob.begin(), 
          std::bind2nd(std::divides<double>(), __sum)); 
     // Accumulate partial sums. 
     _M_cp.reserve(_M_prob.size()); 
     std::partial_sum(_M_prob.begin(), _M_prob.end(), 
         std::back_inserter(_M_cp)); 
     // Make sure the last cumulative probability is one. 
     _M_cp[_M_cp.size() - 1] = 1.0; 
    } 

    template<typename _IntType> 
    template<typename _UniformRandomNumberGenerator> 
     typename discrete_distribution<_IntType>::result_type 
     discrete_distribution<_IntType>:: 
     operator()(_UniformRandomNumberGenerator& __urng, 
       const param_type& __param) 
     { 
     if (__param._M_cp.empty()) 
      return result_type(0); 

     __detail::_Adaptor<_UniformRandomNumberGenerator, double> 
      __aurng(__urng); 

     const double __p = __aurng(); 
     auto __pos = std::lower_bound(__param._M_cp.begin(), 
             __param._M_cp.end(), __p); 

     return __pos - __param._M_cp.begin(); 
     } 

Also im Grunde berechnet sie einen auxilary Vektor _M_cp bei der Initialisierung, die im Wesentlichen eine discete kumulative Dichtefunktion der Gewichte ist. Das Erzeugen eines Samples bedeutet also nur das Erzeugen einer einheitlichen Zufallsvariablen und das Suchen nach dem ersten Vorkommen dieses in der kumulativen Verteilung (das ist der Aufruf unter oben), der seinen Index zurückgibt.

zB wenn die Gewichte Vektor ist:

{ 1, 2, 1, 3 } 

dann wird der cp berechnet als:

{ 1, 1+2, 1+2+1, 1+2+1+3 } 
= 
{ 1, 3, 4, 7 } 

so gleichmäßig I Auswählen von 0..6 und 4, so dass ich die Pick dritte.

0

After much Google searching, I still can't even find a list of methods that this class has, and whether any of them function to re-assign the probabilities.

http://www.boost.org/doc/html/boost/random/discrete_distribution.html

und

void param(const param_type & param); 

Sets the parameters of the distribution.

+0

Ich verstehe. Das Problem war, dass mein System Boost 1.42 hat, und es scheint, dass dieses Zeug in Boost :: random in dieser Version nicht existiert. Ich werde auf die aktuelle Boost-Version upgraden und dann wird die Dokumentation, auf die Sie mich hingewiesen haben, angewendet und sollte das Problem lösen. Sobald ich das funktioniert habe, werde ich die Antwort sicher akzeptieren. Vielen Dank. – ely

+0

Ich kann diese Methode nicht funktionieren. Gibt es eine Dokumentation darüber, was als "Param" -Typ akzeptiert wird? Ich habe 'std :: vector ' versucht, das ist, was rechts von Beispielen scheint, aber es gibt Fehler, dass es eine 'param()' Methode mit diesem Typ als das Argument nicht finden kann. – ely

+0

Es will eigentlich einen param_type, der auf verschiedene Arten initialisiert werden kann, aber Vektor ist keiner von ihnen. Ein mit {1.0, 2.0, 1.3} initialisiertes Array würde funktionieren, aber das ist nicht sehr flexibel. Es gibt auch den Iterator, Iterator-Formular, das für Sie arbeiten könnte. – DRVic