2016-06-15 9 views
0

類似の質問が見つかりませんでしたので、既に尋ねられている場合は謝ります。私は機能でそれを行うと :私は発電機のいずれかからの関数呼び出しを経由してランダム化し、それが正常に動作どこ同じ番号を返すC++ STL乱数生成

#ifndef OPTIMALIZATION_HPP 
#define OPTIMALIZATION_HPP 

#include<utility> 
#include<random> 
#include<experimental/random> 
#include<functional> 
#include<experimental/functional> 
#include<experimental/tuple> 
#include<algorithm> 
#include<type_traits> 
#include<iostream> 

namespace numerics{ 
    template< 
     std::size_t population_size, std::size_t generations, 
     typename Func, 
     typename Compare, 
     typename Generator=std::default_random_engine, 
     template<typename> 
      typename RealDistribution=std::uniform_real_distribution, 
     template<typename> 
      typename IntegerDistribution=std::uniform_int_distribution, 
     typename ...Ts 
    > 
    auto optimize(
      const Func& function, const Compare& comp, 
      const std::pair<Ts,Ts>&... ranges 
    ){ 

     constexpr std::size_t range_argument_count=sizeof...(ranges); 
     static_assert(range_argument_count>2, 
       "Function needs at least two range arguments" 
     ); 

     //RANDOM NUMBER GENERATORS LAMPDA FUNCTIONS 
     auto real_random_generator=[&](const std::pair<auto,auto> range){ 
      return std::bind(
        RealDistribution<decltype(range.first)>(range.first,range.second), 
        Generator() 
      ); 
     }; 

     auto integer_random_generator=[&](const std::pair<auto,auto>& range){ 
      return std::bind(
        IntegerDistribution<decltype(range.first)>(range.first,range.second), 
        Generator() 
      ); 
     }; 

     //MAKING TUPLE OF GENERATORS FOR SPECIFIC RANGES ARGUMENTS 
     auto generator_objects=std::make_tuple(
       integer_random_generator, 
       real_random_generator 
     ); 
     auto generators=std::make_tuple(
       std::get<std::is_floating_point<decltype(ranges.first)>::value> //UPDATE FOR C++17 
       (generator_objects)(ranges)... 
     ); 
     //RANDOMIZES NUMBERS FINE! 
     std::cout << std::get<0>(generators)() << std::endl; 
     std::cout << std::get<0>(generators)() << std::endl; 

     //SINGLE RANDOM INDIVIDUAL GENERATOR 
     auto generate_random_individual=[&](const auto& gen){ 
      auto genotype=std::experimental::apply(
        [&](auto... x){ 
         return std::make_tuple(x()...); 
        }, 
        gen 
      ); 
      return std::make_pair(
        std::experimental::apply(function,genotype), 
        genotype 
      ); 
     }; 
     //RETURN THE SAME NUMBER! 
     auto foo=generate_random_individual(generators); 
     auto foo2=generate_random_individual(generators); 
     auto foo3=generate_random_individual(generators); 
     auto foo4=generate_random_individual(generators); 
     std::cout << std::get<0>(foo.second) << std::endl; 
     std::cout << std::get<0>(foo2.second) << std::endl; 
     std::cout << std::get<0>(foo3.second) << std::endl; 
     std::cout << std::get<0>(foo4.second) << std::endl; 
     return 1.; 
}} 
#endif 

最も興味深い部分がある(// NUMBERSのFINEをランダムライン:!)とにかく、ここで私の関数でありますgenerate_random_individual(特定の範囲を持つ少数のジェネレータオブジェクトを使用)を、非常に同じオブジェクトセットで同じ関数呼び出しを介して実行します(私は新しいジェネレータを作成しません)。

誰かがテストケースを望む場合は、テストケースを提供することができますが、それらを含めるべきかどうかはわかりませんでした。

編集:これは例として残していますが、正確にバグがあった場所を知りたい場合は、私の答えをご覧ください。

+3

TL; DR;シードは一度だけ。 –

+0

私はあなたのジェネレータを播種する場所は見ません(私は何かを見逃しているかもしれません)。あなたが種を蒔かないと、いつも同じシーケンスが得られます。 –

+0

@JesperJuhl私はそれを播種する必要がありますか?私はランダムなライブラリを使用しており、generate_random_individualの呼び出しごとに異なる出力が必要です。このlampda関数はlampda関数を使用しているため、同じジェネレータを使用していると思われますので、異なるランダム値を返す必要があります(2つの呼び出しを参照してください:std :: cout << std::get<0>(generators)()<< std :: endl;ポストの最後の4つのコールより)。 – MostLovelyRollOnThePlanet

答えて

4

乱数を使用するたびに新しい発電機を作成しています。私はこれらのジェネレータのためにシードがどのように生成されるのかわかりませんが、作成するジェネレータインスタンスごとに同じシードを使用しています。あなたが代わりにすべきことは、すべてのディストリビューションが使用する単一のジェネレータを作成することです。

ブーストランダムクラスが提供するものを見て、そこでいくつかのサンプルを調べることができます。解決

+2

_ "ブーストランダムクラスが提供するものを見たいかもしれません" _現行の標準IMOより優れたものはありません。 –

+1

はい。ジェネレータを再生成しないでください。それらを再使用してください。 –

+0

私は本当にジェネレータを再生成しますか?あなたが私のためにそれを指摘できたら、私はどこでそうするのですか? – MostLovelyRollOnThePlanet

2

問題 - 私はつまり、ここで、私の機能の一つに渡すとき&を追加するのを忘れ:

auto genotype=std::experimental::apply(
        [&](auto&... x){ //THIS LINE! 
         return std::make_tuple(x()...); 
        }, 
        gen 
      ); 

その結果、あなたのほとんどは、入力に感謝を述べたように、発電機をコピーしました。

関連する問題