diff options
| author | Aiden Woodruff <woodra@rpi.edu> | 2025-11-16 23:38:16 -0500 |
|---|---|---|
| committer | Aiden Woodruff <woodra@rpi.edu> | 2025-11-16 23:38:16 -0500 |
| commit | f7d2e7c8a70e4d96c5cbc4e8774599f351e59216 (patch) | |
| tree | 214525435c077203944fdaa0a273801f5b381aea | |
| parent | e3b2c19dae58430823913c5b6dc0e45617ca6116 (diff) | |
| download | tipping-points-f7d2e7c8a70e4d96c5cbc4e8774599f351e59216.tar.gz tipping-points-f7d2e7c8a70e4d96c5cbc4e8774599f351e59216.tar.bz2 tipping-points-f7d2e7c8a70e4d96c5cbc4e8774599f351e59216.zip | |
add strategy_record
- src/NameGame.h: add strategy record as vector of tuples.
- src/NameGame.cc (runRound): remove each round printout but update the
strategy record.
- fix speaker memory update.
- (clearRecord): add function.
- (writeRecord): add function to output CSV file with record info.
- (NameGame::run): print average strategy.
- src/main.cc: clear memory and run 1000 rounds.
- TASKS.md: update tasks
Signed-off-by: Aiden Woodruff <woodra@rpi.edu>
| -rw-r--r-- | TASKS.md | 2 | ||||
| -rw-r--r-- | src/NameGame.cc | 42 | ||||
| -rw-r--r-- | src/NameGame.h | 5 | ||||
| -rw-r--r-- | src/main.cc | 3 |
4 files changed, 44 insertions, 8 deletions
| @@ -3,5 +3,7 @@ | |||
| 3 | ## To do | 3 | ## To do |
| 4 | 4 | ||
| 5 | - Collect stats on game rounds. | 5 | - Collect stats on game rounds. |
| 6 | - Add round number so that the tipping point can be found in time. | ||
| 7 | - Add group size, cm size, memory length. | ||
| 6 | - Output data for graphing. | 8 | - Output data for graphing. |
| 7 | 9 | ||
diff --git a/src/NameGame.cc b/src/NameGame.cc index 8ea3dcf..022b951 100644 --- a/src/NameGame.cc +++ b/src/NameGame.cc | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | #include <fstream> | ||
| 1 | #include <iostream> | 2 | #include <iostream> |
| 2 | #include <map> | 3 | #include <map> |
| 3 | #include <stdexcept> | 4 | #include <stdexcept> |
| @@ -75,9 +76,16 @@ void NameGame::run(int rounds) { | |||
| 75 | for (int i = 0; i < rounds; ++i) runRound(); | 76 | for (int i = 0; i < rounds; ++i) runRound(); |
| 76 | // Track all plays and plays by non-CM. | 77 | // Track all plays and plays by non-CM. |
| 77 | // Report average plays. | 78 | // Report average plays. |
| 79 | float avg = 0; | ||
| 80 | for (const auto r : strategy_record) { | ||
| 81 | avg += std::get<2>(r) + std::get<3>(r); | ||
| 82 | } | ||
| 83 | avg /= strategy_record.size(); | ||
| 84 | std::cout << avg << std::endl; | ||
| 78 | } | 85 | } |
| 79 | 86 | ||
| 80 | void NameGame::runRound() { | 87 | void NameGame::runRound() { |
| 88 | bool verbose_flag = false; | ||
| 81 | // Select random speaker and hearer. | 89 | // Select random speaker and hearer. |
| 82 | auto speaker = graph.GetNI(dist(rng)); | 90 | auto speaker = graph.GetNI(dist(rng)); |
| 83 | auto hearer = graph.GetNI( | 91 | auto hearer = graph.GetNI( |
| @@ -86,21 +94,26 @@ void NameGame::runRound() { | |||
| 86 | 94 | ||
| 87 | // Speaker chooses best strategy. | 95 | // Speaker chooses best strategy. |
| 88 | int s_strategy = best_move(speaker.GetId()); | 96 | int s_strategy = best_move(speaker.GetId()); |
| 89 | std::cout << "speaker (" << speaker.GetId() << " " | 97 | if (verbose_flag) { |
| 90 | << std::boolalpha << speaker().Val1 | 98 | std::cout << "speaker (" << speaker.GetId() << " " |
| 91 | << ") chose: " << s_strategy << std::endl; | 99 | << std::boolalpha << speaker().Val1 |
| 100 | << ") chose: " << s_strategy << std::endl; | ||
| 101 | } | ||
| 92 | 102 | ||
| 93 | // Listener updates memory. | 103 | // Listener updates memory. |
| 94 | update_memory(hearer.GetId(), s_strategy); | 104 | update_memory(hearer.GetId(), s_strategy); |
| 95 | 105 | ||
| 96 | // Listener chooses best strategy. | 106 | // Listener chooses best strategy. |
| 97 | int h_strategy = best_move(hearer.GetId()); | 107 | int h_strategy = best_move(hearer.GetId()); |
| 98 | std::cout << "hearer (" << hearer.GetId() << " " | 108 | if (verbose_flag) { |
| 99 | << std::boolalpha << hearer().Val1 | 109 | std::cout << "hearer (" << hearer.GetId() << " " |
| 100 | << ") chose: " << h_strategy << std::endl; | 110 | << std::boolalpha << hearer().Val1 |
| 111 | << ") chose: " << h_strategy << std::endl; | ||
| 112 | } | ||
| 101 | 113 | ||
| 102 | // Speaker updates memory. | 114 | // Speaker updates memory. |
| 103 | update_memory(speaker.GetId(), s_strategy); | 115 | update_memory(speaker.GetId(), h_strategy); |
| 116 | strategy_record.emplace_back(speaker.GetId(), hearer.GetId(), s_strategy, h_strategy); | ||
| 104 | } | 117 | } |
| 105 | 118 | ||
| 106 | int NameGame::best_move(int nId) const { | 119 | int NameGame::best_move(int nId) const { |
| @@ -127,4 +140,19 @@ void NameGame::update_memory(int nId, int strategy) { | |||
| 127 | } | 140 | } |
| 128 | } | 141 | } |
| 129 | 142 | ||
| 143 | void NameGame::clearRecord() { | ||
| 144 | strategy_record.clear(); | ||
| 145 | } | ||
| 146 | |||
| 147 | void NameGame::writeRecord(const char* fname) { | ||
| 148 | std::ofstream f(fname); | ||
| 149 | f << "speaker,hearer,speaker_strategy,hearer_strategy\n"; | ||
| 150 | int speaker, hearer, s_strategy, h_strategy; | ||
| 151 | for (const auto& r : strategy_record) { | ||
| 152 | std::tie(speaker, hearer, s_strategy, h_strategy) = r; | ||
| 153 | f << speaker << ',' << hearer << ',' << s_strategy << ',' | ||
| 154 | << h_strategy << '\n'; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 130 | } // namespace tp | 158 | } // namespace tp |
diff --git a/src/NameGame.h b/src/NameGame.h index 8a817ce..73f5630 100644 --- a/src/NameGame.h +++ b/src/NameGame.h | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | #define TIPPING_POINTS_NAMEGAME_H | 2 | #define TIPPING_POINTS_NAMEGAME_H |
| 3 | 3 | ||
| 4 | #include <random> | 4 | #include <random> |
| 5 | #include <tuple> | ||
| 6 | #include <vector> | ||
| 5 | 7 | ||
| 6 | #include <Snap.h> | 8 | #include <Snap.h> |
| 7 | 9 | ||
| @@ -15,7 +17,9 @@ public: | |||
| 15 | 17 | ||
| 16 | void initGraph(); | 18 | void initGraph(); |
| 17 | void initMemory(); | 19 | void initMemory(); |
| 20 | void clearRecord(); | ||
| 18 | void run(int rounds); | 21 | void run(int rounds); |
| 22 | void writeRecord(const char* fname); | ||
| 19 | 23 | ||
| 20 | protected: | 24 | protected: |
| 21 | int best_move(int nId) const; | 25 | int best_move(int nId) const; |
| @@ -27,6 +31,7 @@ private: | |||
| 27 | std::mt19937 rng; | 31 | std::mt19937 rng; |
| 28 | std::uniform_int_distribution<> dist; | 32 | std::uniform_int_distribution<> dist; |
| 29 | TNodeNet<TPair<TBool, TIntV>> graph; | 33 | TNodeNet<TPair<TBool, TIntV>> graph; |
| 34 | std::vector<std::tuple<int, int, int, int> > strategy_record; | ||
| 30 | }; // class NameGame | 35 | }; // class NameGame |
| 31 | 36 | ||
| 32 | } // namespace tp | 37 | } // namespace tp |
diff --git a/src/main.cc b/src/main.cc index e41f4ff..9f47446 100644 --- a/src/main.cc +++ b/src/main.cc | |||
| @@ -7,10 +7,11 @@ int main(int argc, char* argv[]) { | |||
| 7 | tp::NameGame namegame(group_size, 0); | 7 | tp::NameGame namegame(group_size, 0); |
| 8 | for (int cmperc = 18; cmperc < 28; cmperc += 2) { | 8 | for (int cmperc = 18; cmperc < 28; cmperc += 2) { |
| 9 | int cmsize = group_size * cmperc / 100; | 9 | int cmsize = group_size * cmperc / 100; |
| 10 | namegame.clearRecord(); | ||
| 10 | namegame.setCMsize(cmsize); | 11 | namegame.setCMsize(cmsize); |
| 11 | namegame.initMemory(); | 12 | namegame.initMemory(); |
| 12 | std::cout << "CM " << cmsize << " / " << group_size << std::endl; | 13 | std::cout << "CM " << cmsize << " / " << group_size << std::endl; |
| 13 | namegame.run(10); | 14 | namegame.run(1000); |
| 14 | } | 15 | } |
| 15 | return 0; | 16 | return 0; |
| 16 | } | 17 | } |
