board.c: merged board_undo.c
[pachi.git] / dcnn.cpp
blob1febf571eae7b72b7fa4b561cc491ed0344c1b6c
1 #define DEBUG
2 #include <assert.h>
3 #include <ctype.h>
4 #include <math.h>
5 #include <stdarg.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <sys/stat.h>
12 #define CPU_ONLY 1
13 #include <caffe/caffe.hpp>
14 using namespace caffe;
16 extern "C" {
17 #include "debug.h"
18 #include "board.h"
19 #include "dcnn.h"
20 #include "engine.h"
21 #include "uct/tree.h"
24 static shared_ptr<Net<float> > net;
26 bool
27 using_dcnn(struct board *b)
29 return (real_board_size(b) == 19 && net);
32 /* Make caffe quiet */
33 void
34 dcnn_quiet_caffe(int argc, char *argv[])
36 if (DEBUGL(7) || getenv("GLOG_minloglevel"))
37 return;
39 setenv("GLOG_minloglevel", "2", 1);
40 execvp(argv[0], argv); /* Sucks that we have to do this */
43 void
44 dcnn_init()
46 if (net)
47 return;
49 struct stat s;
50 const char *model_file = "golast19.prototxt";
51 const char *trained_file = "golast.trained";
52 if (stat(model_file, &s) != 0 || stat(trained_file, &s) != 0) {
53 if (DEBUGL(1))
54 fprintf(stderr, "No dcnn files found, will not use dcnn code.\n");
55 return;
58 Caffe::set_mode(Caffe::CPU);
60 /* Load the network. */
61 net.reset(new Net<float>(model_file, TEST));
62 net->CopyTrainedLayersFrom(trained_file);
64 if (DEBUGL(1))
65 fprintf(stderr, "Initialized dcnn.\n");
68 void
69 dcnn_get_moves(struct board *b, enum stone color, float result[])
71 assert(real_board_size(b) == 19);
73 int size = 19;
74 int dsize = 13 * size * size;
75 float *data = new float[dsize];
76 for (int i = 0; i < dsize; i++)
77 data[i] = 0.0;
79 for (int j = 0; j < size; j++) {
80 for(int k = 0; k < size; k++) {
81 int p = size * j + k;
82 coord_t c = coord_xy(b, j+1, k+1);
83 group_t g = group_at(b, c);
84 enum stone bc = board_at(b, c);
85 int libs = board_group_info(b, g).libs - 1;
86 if (libs > 3) libs = 3;
87 if (bc == S_NONE)
88 data[8*size*size + p] = 1.0;
89 else if (bc == color)
90 data[(0+libs)*size*size + p] = 1.0;
91 else if (bc == stone_other(color))
92 data[(4+libs)*size*size + p] = 1.0;
94 if (c == b->last_move.coord)
95 data[9*size*size + p] = 1.0;
96 else if (c == b->last_move2.coord)
97 data[10*size*size + p] = 1.0;
98 else if (c == b->last_move3.coord)
99 data[11*size*size + p] = 1.0;
100 else if (c == b->last_move4.coord)
101 data[12*size*size + p] = 1.0;
106 Blob<float> *blob = new Blob<float>(1,13,size,size);
107 blob->set_cpu_data(data);
108 vector<Blob<float>*> bottom;
109 bottom.push_back(blob);
110 assert(net);
111 const vector<Blob<float>*>& rr = net->Forward(bottom);
113 for (int i = 0; i < size * size; i++) {
114 result[i] = rr[0]->cpu_data()[i];
115 if (result[i] < 0.00001)
116 result[i] = 0.00001;
118 delete[] data;
119 delete blob;
122 void
123 find_dcnn_best_moves(struct board *b, float *r, coord_t *best, float *best_r)
125 for (int i = 0; i < DCNN_BEST_N; i++)
126 best[i] = pass;
128 foreach_free_point(b) {
129 int k = (coord_x(c, b) - 1) * 19 + (coord_y(c, b) - 1);
130 for (int i = 0; i < DCNN_BEST_N; i++)
131 if (r[k] > best_r[i]) {
132 for (int j = DCNN_BEST_N - 1; j > i; j--) { // shift
133 best_r[j] = best_r[j - 1];
134 best[j] = best[j - 1];
136 best_r[i] = r[k];
137 best[i] = c;
138 break;
140 } foreach_free_point_end;
143 void
144 print_dcnn_best_moves(struct tree_node *node, struct board *b,
145 coord_t *best, float *best_r)
147 fprintf(stderr, "%.*sprior_dcnn(%s) = [ ",
148 node->depth * 4, " ",
149 coord2sstr(node_coord(node), b));
150 for (int i = 0; i < DCNN_BEST_N; i++)
151 fprintf(stderr, "%s ", coord2sstr(best[i], b));
152 fprintf(stderr, "] ");
154 fprintf(stderr, "[ ");
155 for (int i = 0; i < DCNN_BEST_N; i++)
156 fprintf(stderr, "%.2f ", best_r[i]);
157 fprintf(stderr, "]\n");
160 static coord_t *
161 dcnn_genmove(struct engine *e, struct board *b, struct time_info *ti, enum stone color, bool pass_all_alive)
163 float r[19 * 19];
164 float best_r[DCNN_BEST_N] = { 0.0, };
165 coord_t best_moves[DCNN_BEST_N];
166 dcnn_get_moves(b, color, r);
167 find_dcnn_best_moves(b, r, best_moves, best_r);
169 return coord_copy(best_moves[0]);
172 struct engine *
173 engine_dcnn_init(char *arg, struct board *b)
175 dcnn_init();
176 if (!net) {
177 fprintf(stderr, "Couldn't initialize dcnn, aborting.\n");
178 abort();
180 //struct patternplay *pp = patternplay_state_init(arg);
181 struct engine *e = (engine*)calloc2(1, sizeof(struct engine));
182 e->name = (char*)"DCNN Engine";
183 e->comment = (char*)"I just select dcnn's best move.";
184 e->genmove = dcnn_genmove;
185 //e->evaluate = dcnn_evaluate;
186 //e->data = pp;
188 return e;
192 } /* extern "C" */