2017-03-01 6 views
3

I有しa.hに次の設計:マップに格納されたベクトルのベクトルを更新

class A { 
    virtual void updateCoefficients(std::string /*state*/, std::vector<std::vector<double>>& /*coefs*/, 
            double /*reward*/) {} 
protected: 
    std::map<std::string, std::vector<std::vector<double>>> heuristic; 
} 

class B : public A { 
    virtual void updateCoefficients(std::string state, std::vector<std::vector<double>>& coefs, 
            double reward) override; 
} 

a.ccで:

void B::updateCoefficients(std::string state, std::vector<std::vector<double>>& coefs, 
            double reward) { 
    for(unsigned i = 0; i < coefs.size(); i++) { 
     coefs[i][0] += 1; 
    } 

    for(unsigned i = 0; i < coefs.size(); i++) { 
     coefs[i][1] += 2; 
    } 
} 

Iはclass Aで定義されたメソッドからupdateCoefficients呼び出しつつ:

void A::foo(std::string state, std::string action, double const& reward) { 
     if (heuristic.count(action)) { 
      updateCoefficients(state, heuristic[action], reward); 
     } else { 
      std::vector<std::vector<double>> coefs(20, std::vector<double>(2, 0.0)); 
      heuristic[action] = coefs; 
    } 
} 

問題は、ベクターマップheuristicのは更新されていませんが、updateCoefficientsが呼び出されると、すべてのベクトルは初期化されたときと同じように0になります。私は間違って何をしていますか?

アイデアは、使用するとclass Aからベースを継承する子クラスで異なるupdateCoefficientsメソッドを定義する必要があり、すべてのメソッドと変数を含むベースとしてclass Aを持つことです。

EDIT

OK、全体のコードはここにOfflineHeuristic.hOfflineHeuristic.cc見つけることができるようにします。クラスStateActionStateTHTSの情報は無関係です。私は可能な修正を試みましたが、まだマップheuristicは常にゼロの値で満たされています。他のクラスから呼び出されているメソッドはofflineHeuristic->learn(state, action, reward)です。

EDIT 2

エラーコードロジックで、別の場所で実際にありました。上に貼り付けたコードを実際に正しいものにする。誰かがそのような問題に遭遇した場合に備えて質問を残しておきます。または、それが良いことでない場合は、私に質問を削除するように私に知らせてください。

+0

あなたはMCVEを投稿する必要があります。残りのコードで何が起こっているのかはわかりません。 –

+0

@ĐorđeRelić私はRichardHodgesを繰り返すだけで、(http://stackoverflow.com/help/mcve)[Minimal、Complete、Verifiable Example]を投稿する必要があります。全体のコードは「最低限」です。それをMCVEにすることはあなたの仕事であり、我々の仕事ではありません。 – Aziuth

+0

@ĐorđeRelić、残念ながら、私たちはここでコードをデバッグしていません。コマンドラインからGDBを使用するのが難しい場合は、IDEを試してみてください。(QTCreatorは無料で、QTなしでも使えます。コピー&ペーストが可能で、変更なしで実行できる最小限の例を教えてください。私たちは助けてくれるでしょう。IdeOneのようなオンラインコンパイラを使うのがベストです。 – Evgeniy

答えて

2

ヒューリスティックが更新されない理由は、A :: fooを2回呼び出す必要があるためです。最初の呼び出しは0で初期化され、次の呼び出しでのみ更新されます。

だから、このようなコードを変更することができることは解決策になります。

void A::foo(std::string state, std::string action, double const& reward) { 
     if (!heuristic.count(action)) { 
      std::vector<std::vector<double>> coefs(20, std::vector<double>(2, 0.0)); 
      heuristic[action] = coefs; 
     } 
     updateCoefficients(state, heuristic[action], reward); 
} 

そして、あなたのコードの残りの部分は動作します - データが更新されます。することはできtry it here

A* instance = new B(); 
instance->foo("aaa", "bbb", 123); 
cout << "First call" << endl; 

for (auto h : instance->heuristic) 
    for (auto b : h.second) 
     for (auto c : b) 
      cout << c << " "; 
cout << endl;    
instance->foo("aaa", "bbb", 123); 
cout << "Second call" << endl; 

for (auto h : instance->heuristic) 
    for (auto b : h.second) 
     for (auto c : b) 
      cout << c << " "; 
cout << endl;    

出力:

First call 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
Updated 
1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 
+0

はい、これは私の間違いですが、ヒューリスティックが更新されていない理由はありません。 –

+0

@ĐorđeRelić、デバッガがお手伝いします:)私は自分の答えを更新しました - オンラインで試してください – Evgeniy

+0

GDBを使用するのは本当に嫌ですので、 "std :: cout <<"私が結論したところでは、メソッドの中でベクトルの値は更新されていますが、メソッドを再び入力すると、別のベクトルで作業している場合のように0になります。私は、問題を単純化しながら間違いを犯した場合に備えて、完全なコードで質問を更新しました。 –

1

あなたが、それは純粋仮想エラーを回避するために作る、基本クラスのメソッドを使用しているように私には思えます。 virtual void updateCoefficients(...) = 0;

期待どおりに動作します。

// Example program 
#include <iostream> 
#include <string> 
#include <vector> 
#include <map> 

class A { 
    virtual void updateCoefficients(std::string /*state*/, std::vector<std::vector<double>>& /*coefs*/, 
            double /*reward*/) = 0; 
protected: 
    std::map<std::string, std::vector<std::vector<double>>> heuristic; 
public: 
    void foo(std::string state, std::string action, double const& reward); 
    virtual ~A() {} 

}; 

void A::foo(std::string state, std::string action, double const& reward) { 
     if (heuristic.count(action)) { 
      updateCoefficients(state, heuristic[action], reward); 
      std::cout << "exist\n"; 
      std::cout << heuristic[action][0][0] << '\n'; 
      std::cout << heuristic[action][0][1] << '\n'; 
     } else { 
      std::vector<std::vector<double>> coefs(20, std::vector<double>(2, 0.0)); 
      heuristic[action] = coefs; 
      std::cout << "not exist\n"; 
    } 
} 

class B : public A { 
    virtual void updateCoefficients(std::string state, std::vector<std::vector<double>>& coefs, 
            double reward) override; 
public: 
    virtual ~B() {} 
}; 

void B::updateCoefficients(std::string state, std::vector<std::vector<double>>& coefs, 
            double reward) { 
    for(unsigned i = 0; i < coefs.size(); i++) { 
     coefs[i][0] += 1; 
     coefs[i][1] += 2; 
    } 
} 

int main() 
{ 
    A* a = new B(); 
    a->foo("aaa", "bbb", 2.0); 
    a->foo("aaa", "bbb", 2.0); 
    a->foo("aaa", "bbb", 2.0); 
    delete a; 
    return 0; 
} 
+0

私はあなたの修正を試みたが、それは役に立たなかった。最初にコードを単純化するのに間違いがあった場合に備えて、ヘッダーとソースファイルへのリンクを使って質問を更新しました。 –

+0

@deoribeRelićデバッグ印刷をupdateCoefficientsメソッドに追加するには、必要なメソッドを呼び出してください。あなたがrefを使用しているところはどこでも確認してください。 – fandyushin

+0

しました。 'GradualDescent :: updateCoefficients'にあるように、いくつかの場所に' SystemUtils :: log'があります。これは作成されたログです:[log](https://gist.github.com/DjoleR/0ac38b002e6f7cee0fdf7ea7573600b7)。最初の更新でのみ存在するはずですが、古い値は常に0です。したがって、論理は「古い値」の値(0 | 1)であり、2つの要素のみを持つベクトル内のベクトルのインデックスに依存します。 ĐorđeRelić@ –

関連する問題