2016-06-29 30 views
0

私は個人的なライブラリの学習アルゴリズムのセットを書いています。学習アルゴリズムには、探索する入力空間と、ある解を別の解と比較する方法の2つが必要です。入力空間を定義することは最も基本的なデータ転送ですが、私はそれに定格機能を渡すことが難しいです。C++引数として渡す関数を書く

現在、私は問題のコードは次のようになります。

RankineGenerator generator(tempHotWater,tempColdWater); 

int variablesSize = 2; 
Range minMaxVaporizer = { tempColdWater,tempHotWater }; 
Range minMaxCondenser = { tempColdWater,tempHotWater }; 
Range minMax[] = {minMaxVaporizer, minMaxCondenser}; 

auto phi = [&generator] (double * heatExchangerTemps) -> double 
{ 
generator.updateHeatExchangeTemps(heatExchangerTemps[0], heatExchangerTemps[1]); 
generator.runSim(); 
return generator.getSpecificWork()/(generator.getColdWaterRelativeMass()+generator.getHotWaterRelativeMass()); 
}; 

Twiddle twiddle(variablesSize,phi,minMax,0.001); 

そして、私のコンストラクタヘッダは次のようになります。「PHI」ラムダ関数は、私がしようとしているものです

Twiddle(int size, double(*phi)(double*), Range minMax[], double minRatioDeltaPhi); 

アルゴリズム "twiddle"に渡す

必ずしもそうである必要はありませんラムダ関数、任意のインライン関数が行います。懸念の

ポイント:

学習アルゴリズムの計算集約的になりがち非常に速く解決策は簡単に解決することが好ましいです。

渡される関数は、それが中で宣言された範囲からの情報の一部にアクセスするいくつかの方法が必要です。

学習アルゴリズムは、ユニバーサルである必要があります。問題の特定のデータを渡すことは選択肢ではありません。プラグインして問題なく再生できる必要があります。私がいくつかの混乱を引き起こしてきたようだ :

constructor(nVars, ratingFunction(vars[nVars]), ranges[nVars], minImprovementSpeed) 

更新:のように理想的にはコンストラクタは次の形式を取る必要があります。謝罪いたします。

まず、というインラインを使用しています。は、独立したエンティティではなくプログラムの途中で書かれた関数を意味します。必ずしも同じ名前のキーワードとは関係がありません。

第2に、ローカルデータにアクセスできる関数を渡すことです。建設ヘッダと

double(*phi)(double*) = [](double* heatExchangerTemps) { /*do something*/ }; 

Twiddle twiddle(variablesSize,phi,minMax,.001); 

:例えばこのため

Twiddle(int size, double (*phi)(double*) , Range minMax[], double minRatioDeltaPhi); 

はコンパイルが、オブジェクト "ジェネレータ" へのアクセスを与えないであろう。私はラムダ関数で「発電機」オブジェクトをキャプチャしようとすると、しかし、:

double(*phi)(double*) = [&generator](double* heatExchangerTemps) { /*do something*/ }; 

または

auto phi = [&generator] (double * heatExchangerTemps) -> double { /*do something*/ }; 

私はエラーを取得します。

double(*phi)(double*) = [](double* myArray) 
{ 
    Generator generator(/*stuff*/); 
    // do something 
}; 

をしかし、その後、クラス「ジェネレーター」の新しいオブジェクトは関数が呼び出されるたびに作成されます。

私はこれを行うことができます。この機能を1000倍以上呼び出すことは理想的ではありません。さらに、 "Twiddle"アルゴリズムにはGeneratorコンストラクタに固有の情報が必要です。これは、汎用アルゴリズムを持つという全目的を犠牲にします。

理想的には、関数内でローカルオブジェクト(この場合はジェネレータ)にアクセスし、その関数をコンストラクタの汎用引数として渡す必要があります。

また、必ずしもラムダ関数である必要はありません。これは最初に気になったことです。

+1

あなたの質問は明確ではありませんが、呼び出し可能なオブジェクトを関数に渡すことを望むなら、 'std :: function 'を使用してください。 –

+0

double(* phi)(double *)の代わりにstd :: function を使用します。 – AnatolyS

+1

また、コンパイラを強制する方法がないため、「インライン関数」は誤称または過度に楽観的です。関数をインライン化する。それはラムダをインラインにするかもしれないが、そうではないかもしれない。最適化と(複数のTUを使用する場合)特にLTOは、あなたのチャンスを大きくします。 –

答えて

1

私はこれを見つけたカップルの時間のためにチャンスをうかがっ後:コンストラクタヘッダーと

std::function<double(double*)> phi = [&generator] (double * heatExchangerTemps) -> double 
{ /*do someting*/ }; 
Twiddle twiddle(variablesSize,phi,minMax,1000000); 

:それは最良の答えだが、うまく動作しているようならば

​​

わかりません。

私のラムダ関数は、基本的にラムダのキャプチャ機能を維持しながら、コンストラクタが受け取っているものを理解できるようにするタイプstd::function<double(double*)>に準拠しています。

関連する問題