Skip to content

Commit

Permalink
Add gogui-analyze support
Browse files Browse the repository at this point in the history
  • Loading branch information
zakki committed May 27, 2017
1 parent 0b35292 commit f5dbf50
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 39 deletions.
129 changes: 95 additions & 34 deletions src/Gtp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <fstream>
#include <vector>
#include <random>
#include <sstream>
#include <iomanip>

#include "DynamicKomi.h"
#include "Gtp.h"
Expand Down Expand Up @@ -67,8 +69,14 @@ static void GTP_final_status_list( void );
static void GTP_set_free_handicap( void );
// fixed_handicapコマンドを処理
static void GTP_fixed_handicap( void );
// GOGUI
static void GTP_gogui_analyze_commands( void );
//
static void GTP_ray_analyze(void);
static void GTP_ray_toggle_live_best_sequence();
//
static void GTP_ray_best_sequence();
//
static void GTP_ray_stat();
//
static void GTP_features_planes_file(void);
//
Expand Down Expand Up @@ -107,7 +115,10 @@ const GTP_command_t gtpcmd[GTP_COMMAND_NUM] = {
{ "place_free_handicap", GTP_fixed_handicap },
{ "set_free_handicap", GTP_set_free_handicap },
{ "kgs-genmove_cleanup", GTP_kgs_genmove_cleanup },
{ "ray_analyze", GTP_ray_analyze },
{ "gogui-analyze_commands", GTP_gogui_analyze_commands },
{ "ray-toggle_live_best_sequence", GTP_ray_toggle_live_best_sequence },
{ "ray-best_sequence", GTP_ray_best_sequence },
{ "ray-stat", GTP_ray_stat },
{ "_clear", GTP_features_clear },
{ "_store", GTP_features_store },
{ "_dump", GTP_features_planes_file },
Expand Down Expand Up @@ -782,12 +793,32 @@ GTP_kgs_genmove_cleanup( void )
GTP_response(pos, true);
}

/////////////////////////////////////////
// void GTP_gogui_analyze_commands() //
/////////////////////////////////////////
static void
GTP_gogui_analyze_commands()
{
GTP_response(
"none/Togle Live Best Sequence/ray-toggle_live_best_sequence\n"
"gfx/Print Best Sequence/ray-best_sequence %m\n"
"hpstring/Print Moves/ray-stat %m\n"
"",
true);
}

//////////////////////////
// void GTP_genmove() //
//////////////////////////
static void
GTP_ray_analyze(void)
GTP_ray_toggle_live_best_sequence()
{
ToggleLiveBestSequence();
GTP_response(brank, true);
}

////////////////////////////////////
// void GTP_ray_best_sequence() //
////////////////////////////////////
static void
GTP_ray_best_sequence()
{
char *command;
char c;
Expand All @@ -798,26 +829,20 @@ GTP_ray_analyze(void)
command = STRTOK(input_copy, DELIM, &next_token);

CHOMP(command);
if (!strcmp("genmove_black", command)) {
color = S_BLACK;
} else if (!strcmp("genmove_white", command)) {
command = STRTOK(NULL, DELIM, &next_token);
if (command == NULL) {
GTP_response(err_genmove, true);
return;
}
CHOMP(command);
c = (char)tolower((int)command[0]);
if (c == 'w') {
color = S_WHITE;
} else if (c == 'b') {
color = S_BLACK;
} else {
command = STRTOK(NULL, DELIM, &next_token);
if (command == NULL) {
GTP_response(err_genmove, true);
return;
}
CHOMP(command);
c = (char)tolower((int)command[0]);
if (c == 'w') {
color = S_WHITE;
} else if (c == 'b') {
color = S_BLACK;
} else {
GTP_response(err_genmove, true);
return;
}
GTP_response(err_genmove, true);
return;
}

player_color = color;
Expand All @@ -826,19 +851,55 @@ GTP_ray_analyze(void)
point = SimulationGenmove(game, color);
else
point = UctSearchGenmove(game, color);
/*
if (point != RESIGN) {
PutStone(game, point, color);

stringstream out;
PrintBestSequenceGFX(out, game, uct_node, current_root, color);
GTP_response(out.str().c_str(), true);
}

///////////////////////////
// void GTP_ray_stat() //
///////////////////////////
static void
GTP_ray_stat()
{
char *command;
char c;
char pos[10];
int color;
int point = PASS;

command = STRTOK(input_copy, DELIM, &next_token);

CHOMP(command);
command = STRTOK(NULL, DELIM, &next_token);
if (command == NULL) {
GTP_response(err_genmove, true);
return;
}
CHOMP(command);
c = (char)tolower((int)command[0]);
if (c == 'w') {
color = S_WHITE;
} else if (c == 'b') {
color = S_BLACK;
} else {
GTP_response(err_genmove, true);
return;
}

IntegerToString(point, pos);
*/
cout << "= ";
PrintLiveBestSequence(cerr, game, uct_node, current_root, color);
//GTP_response(pos, true);
cout << endl << endl;
player_color = color;

UctSearchPondering(game, FLIP_COLOR(color));
if (sim_move)
point = SimulationGenmove(game, color);
else
point = UctSearchGenmove(game, color);

stringstream out;
PrintMoveStat(out, game, uct_node, current_root);

GTP_response(out.str().c_str(), true);
//cout << endl << endl;
}

static int features_turn_count = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/Gtp.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef _GTP_H_
#define _GTP_H_

const int GTP_COMMAND_NUM = 30;
const int GTP_COMMAND_NUM = 33;
const int GTP_COMMAND_SIZE = 64;
const int BUF_SIZE = 256;

Expand Down
136 changes: 135 additions & 1 deletion src/Message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <iostream>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <numeric>

#include "Message.h"
#include "Point.h"
Expand Down Expand Up @@ -465,7 +467,7 @@ PrintBestSequence( const game_info_t *game, const uct_node_t *uct_node, const in


void
PrintLiveBestSequence(std::ostream& out, const game_info_t *game, const uct_node_t *uct_node, int current_root, int start_color)
PrintBestSequenceGFX(std::ostream& out, const game_info_t *game, const uct_node_t *uct_node, int current_root, int start_color)
{
int current = current_root;
int color = start_color;
Expand Down Expand Up @@ -558,6 +560,138 @@ PrintLiveBestSequence(std::ostream& out, const game_info_t *game, const uct_node
}


static void
PrintBestSequence(std::ostream& out, const game_info_t *game, const uct_node_t *uct_node, int current_root)
{
int current = current_root;

auto root = &uct_node[current_root];
auto statistic = root->statistic;
auto uct_child = uct_node[current].child;
int child_num = uct_node[current].child_num;

if (root->move_count == 0)
return;

int index = -1;
int max = 0;
for (int i = 0; i < child_num; i++) {
if (uct_child[i].move_count > max) {
max = uct_child[i].move_count;
index = i;
}
}
if (node_hash[current].color == S_BLACK) out << "b ";
else if (node_hash[current].color == S_WHITE) out << "w ";
out << FormatMove(uct_child[index].pos) << " ";

current = uct_child[index].index;

while (current != NOT_EXPANDED) {
uct_child = uct_node[current].child;
child_num = uct_node[current].child_num;

max = 50;
index = -1;

for (int i = 0; i < child_num; i++) {
if (uct_child[i].move_count > max) {
max = uct_child[i].move_count;
index = i;
}
}

if (index == -1) break;

if (node_hash[current].color == S_BLACK) out << "b ";
else if (node_hash[current].color == S_WHITE) out << "w ";
out << FormatMove(uct_child[index].pos) << " ";

current = uct_child[index].index;
}
}

void
PrintMoveStat( std::ostream& out, const game_info_t *game, const uct_node_t *uct_node, int current_root )
{
bool evaled = uct_node[current_root].evaled;
const child_node_t *uct_child = uct_node[current_root].child;
const int child_num = uct_node[current_root].child_num;
const double scale = std::max(0.2, std::min(1.0, 1.0 - (game->moves - 200) / 50.0)) * value_scale;

vector<size_t> idx(child_num);
iota(idx.begin(), idx.end(), 0);

auto idxComp = [&uct_child](size_t i1, size_t i2) {
return uct_child[i1].move_count > uct_child[i2].move_count;
};

sort(idx.begin(), idx.end(), idxComp);

out << "|Move|Count|Simulation|Policy |Value |Win |Best Sequence" << endl;
// UCB値最大の手を求める
for (int j = 0; j < std::min(10, child_num); j++) {
int i = idx[j];
if (uct_child[i].move_count == 0)
continue;
if (!uct_child[i].flag && !uct_child[i].open)
continue;
//double p2 = -1;
double value_win = 0;
double value_move_count = 0;

if (uct_child[i].index >= 0 && i != 0) {
auto node = &uct_node[uct_child[i].index];
if (node->value_move_count > 0) {
//p2 = 1 - (double)node->value_win / node->value_move_count;
value_win = node->value_win;
value_move_count = node->value_move_count;
value_win = value_move_count - value_win;
}
//cerr << "VA:" << (value_win / value_move_count) << " VS:" << uct_child[i].value << endl;
}
if (value_move_count == 0 && uct_child[i].value >= 0) {
value_move_count = 1;
value_win = uct_child[i].value;
}

double win = uct_child[i].win;
double move_count = uct_child[i].move_count;
double p0 = win / move_count;

out << "|" << setw(4) << FormatMove(uct_child[i].pos);
out << "|" << setw(5) << (int) move_count;

auto precision = out.precision();
out.precision(4);
out << "|" << setw(10) << fixed << (p0 * 100);
if (evaled) {
out << "|" << setw(10) << fixed << (uct_child[i].nnrate * 100);
if (value_move_count > 0) {
double p1 = value_win / value_move_count;
double p = p0 * (1 - scale) + p1 * scale;
out
<< "|" << setw(10) << fixed << (p1 * 100)
<< "|" << setw(10) << fixed << (p * 100);
} else {
out
<< "|"
<< "|";
}
} else {
out
<< "|"
<< "|"
<< "|";
}
out.precision(precision);
out << "|";
if (uct_child[i].index > 0)
PrintBestSequence(out, game, uct_node, uct_child[i].index);
out << endl;
}
}

///////////////////////
// 探索の情報の表示 //
///////////////////////
Expand Down
3 changes: 2 additions & 1 deletion src/Message.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ void PrintOwner( const uct_node_t *root, const int color, double *own );

// 最善応手列の表示
void PrintBestSequence( const game_info_t *game, const uct_node_t *uct_node, const int root, const int start_color );
void PrintLiveBestSequence( std::ostream& out, const game_info_t *game, const uct_node_t *uct_node, int root, int start_color );
void PrintBestSequenceGFX( std::ostream& out, const game_info_t *game, const uct_node_t *uct_node, int root, int start_color );
void PrintMoveStat( std::ostream& out, const game_info_t *game, const uct_node_t *uct_node, int current_root );

// 探索の情報の表示
void PrintPlayoutInformation( const uct_node_t *root, const po_info_t *po_info, const double finish_time, const int pre_simulated );
Expand Down
15 changes: 13 additions & 2 deletions src/UctSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ bool reuse_subtree = false;
// 自分の手番の色
int my_color;

//
static bool live_best_sequence = false;

const double pass_po_limit = 0.5;
const int policy_batch_size = 16;
const int value_batch_size = 64;
Expand Down Expand Up @@ -346,6 +349,14 @@ SetEarlyPass(bool pass)
early_pass = pass;
}

//////////////////////////////
// Toggle Live Best Sequece //
//////////////////////////////
void
ToggleLiveBestSequence()
{
live_best_sequence = !live_best_sequence;
}

////////////////////////////////////////////
// 盤の大きさに合わせたパラメータの設定 //
Expand Down Expand Up @@ -1708,8 +1719,8 @@ SelectMaxUcbChild( const game_info_t *game, int current, int color )
double ucb_bonus_weight = bonus_weight * sqrt(bonus_equivalence / (sum + bonus_equivalence));
const bool debug = current == current_root && sum % 10000 == 0 && GetDebugMessageMode();

if (current == current_root && sum % 1000 == 0) {
PrintLiveBestSequence(cerr, game, uct_node, current_root, color);
if (live_best_sequence && current == current_root && sum % 1000 == 0) {
PrintBestSequenceGFX(cerr, game, uct_node, current_root, color);
}
//if (evaled) {
//cerr << "use nn" << endl;
Expand Down
Loading

0 comments on commit f5dbf50

Please sign in to comment.