2017-03-01 77 views
3

我在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; 
    } 
} 

而我請從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作爲一個基礎,它包含所有必須使用的方法和變量,並在繼承class A的基類的子類中定義不同的updateCoefficients方法。

編輯

OK,所以整個代碼可以在這裏找到OfflineHeuristic.hOfflineHeuristic.cc。類別State,ActionState,THTS中的信息是無關緊要的。我試過了可能的修正,但仍然,地圖heuristic不斷填充零值。從其他類中調用的方法是offlineHeuristic->learn(state, action, reward)

編輯2

誤差實際上是在另一個地方,在代碼邏輯。上面粘貼的代碼實際上是正確的。如果有人遇到類似問題,我會留下問題。或者,如果這不是一件好事,請讓我知道,所以我刪除了這個問題。

+0

您需要發佈一個MCVE。我們不知道其他代碼中發生了什麼。 –

+0

@ĐorđeRelić我只能重複RichardHodges,你需要發佈一個(http://stackoverflow.com/help/mcve)[Minimal,Complete,and Verifiable Example]。整個代碼很難「最小化」。爲了使它成爲你的工作,而不是我們的工作。 – Aziuth

+0

@ĐorđeRelić,不幸的是,我們沒有在這裏調試代碼。如果您很難從命令行使用GDB - 嘗試一些IDE(QTCreator是免費的,可以在沒有QT的情況下工作,CLion也是很好的選擇......)。你應該給我們一些最小的例子,它可以被複制粘貼並且在沒有變化的情況下運行 - 我們將會提供幫助,最好的方式是使用一些在線編譯器,比如IdeOne – Evgeniy

回答

2

啓發式不更新的原因是因爲您需要兩次調用A :: foo。首先調用它將被初始化爲零,並且只有下一次調用纔會更新它們;

這樣做可能會改變代碼將是一個解決方案:

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

@ĐorđeRelić將調試打印添加到updateCoefficients方法中,確保您調用了必要的方法。到處檢查你使用的參考。 – fandyushin

+0

我做到了。正如你可以在'GradualDescent :: updateCoefficients'中看到的那樣,在幾個地方有'SystemUtils :: log',這是創建的日誌:[log](https://gist.github.com/DjoleR/0ac38b002e6f7cee0fdf7ea7573600b7)。舊值始終爲0,即使它只應在第一次更新中。所以邏輯是「舊值」值(0 | 1),最後取決於向量中只有2個元素的向量中的索引。 –