2011-01-24 4 views
8

Vorrei ripristinare le sequenze casuali utilizzando numeri seme diversi. Quando si esegue questo codice di prova:Impostazione boost di serie :: casuale

boost::mt19937 gener(1); 
boost::normal_distribution<> normal(0,1); 
boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > rng(gener, normal); 
cout << rng() << endl; 
cout << rng() << endl; 
cout << rng() << endl; 
gener.seed(2); 
cout << rng() << endl; 
cout << rng() << endl; 
gener.seed(1); 
cout << rng() << endl; 
gener.seed(2); 
cout << rng() << endl; 
gener.seed(3); 
cout << rng() << endl; 

ottengo il seguente output:

# seed(1) via constructor 
-2.971829031 
1.706951063 
-0.430498971 
# seed(2) 
-2.282022417 
-0.5887503675 
# seed(1) 
0.2504171986 
# seed(2) 
-0.5887503675 
# seed(3) 
0.2504171986 

Ovviamente sto facendo qualcosa di molto sbagliato. Come posso superare questo problema?

risposta

14

seguito Jim, Alan e Igor suggerimenti apportato alcune modifiche al codice: rng.engine().seed() invece di gener.seed(), e chiamato rng.distribution().reset() dopo la chiamata a rng.engine().seed() e ha funzionato come un fascino.

Grazie mille!

+3

Felice che abbia funzionato! A proposito, ti è permesso (e incoraggiato) di accettare la tua risposta, specialmente se ci sono volute una combinazione di diverse idee per risolvere il tuo problema. –

1

Credo che boost::variate_generator<> faccia una copia dell'oggetto boost::mt19937 gener. Pertanto, quando si effettua il resezione della propria copia di gener, non ha alcun effetto sull'oggetto rng che è già stato creato . La creazione di un nuovo oggetto rng ogni volta che si esegue la resezione dovrebbe fornire il comportamento desiderato (dichiarazione di non responsabilità: non testato!)

+0

Credo che risemina sta avendo qualche effetto sulla RNG, perché io sono sempre valori ripetuti -0.5887503675 e ,2504,171986 millions. Ma sfortunatamente non è affatto quello che mi aspetterei. –

+0

Ottimo per vedere risolto il problema, ma posso chiedere perché 'boost :: variate_generator <>' fa una copia di 'gener' in questo caso? Penso che l'OP abbia passato il riferimento durante la scrittura di 'boost :: variate_generator >', mi manca qualcosa? ... – Vokram

5

È necessario chiamare normal.reset() dopo la chiamata a gener.seed(). Questo è specificato per garantire che l'output di normale non dipenda da alcun output precedente generato da gener.

(la distribuzione è probabilmente il caching uno stato che è necessario per cancellare.)

+0

Sì, sembra un problema di cache. Ho fatto ciò che mi hai suggerito, ma sto ancora ottenendo gli stessi risultati ... –

+2

Gli RNG normalmente distribuiti usano la [modifica Box-Muller] (http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) che genera numeri casuali in coppie (vedi: [Esempi di ricette numeriche] (http://dimacs.rutgers.edu/~graham/code.html)) – Mike

1

Ottimo per vedere risolto il problema! Ma credo che ho appena capito perché il metodo di Alan non avrebbe funzionato ...

Quando si scrive boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > rng(gener, normal), non hai creato un'altra copia gener perché è una chiamata per riferimento, ma si fatto creare un'altra copia del normal con variate_generate.

Quindi anziché normal.reset, che ripristina solo l'originale normal, è necessario utilizzare rng.distribution().reset(). Ma puoi semplicemente mantenere gener.seed(), che a mio avviso avrà lo stesso effetto di rng.engine().seed().

L'ho provato nel mio codice e ha funzionato come previsto.

Ebbene, nel caso in cui qualcuno si sarebbe preso cura :)