Commit 3ff4a63d authored by Vivien Kraus's avatar Vivien Kraus
Browse files

Hook up the CNN evaluation to the predictor API.

parent 00b28569
......@@ -2384,6 +2384,24 @@ set the dimension /n/. /data/ is allocated with the =calloc=
function, so that it may be handled more efficiently by the kernel,
and you need to =free= it.
#+end_deftypefun
Since the CNN predicts the score based on a current client-side game,
we can use the =TarotPredictor= API in order to optionally use the
CNN.
#+attr_texinfo: :options {size_t} tarot_cnn_predictor_construct (size_t @var{maxmem}, char *@var{mem}, size_t *@var{alignment})
#+begin_deftypefun
Construct a CNN predictor in-place, at /mem/, which is an array of
/maxmem/ bytes. It is supposed to be correctly aligned if /maxmem/
not null. You can query the alignment and the required size by
calling this function with an empty /mem/ / /maxmem/ and looking at
/alignment/ and the return value.
#+end_deftypefun
#+attr_texinfo: :options {TarotPredictor *} tarot_cnn_predictor_alloc (void)
#+begin_deftypefun
Allocate a fresh predictor that will always use the CNN.
#+end_deftypefun
* GNU Free Documentation License
:PROPERTIES:
:APPENDIX: t
......
......@@ -42,6 +42,26 @@ tarot_cnn_predict_alloc (const TarotGame * game, double **score,
assert (n == *n_score);
}
size_t
tarot_cnn_predictor_construct (size_t max_mem, char *mem, size_t *alignment)
{
return cnn_predictor_construct (max_mem, mem, alignment);
}
TarotPredictor *
tarot_cnn_predictor_alloc (void)
{
size_t alignment;
size_t required = cnn_predictor_construct (0, NULL, &alignment);
size_t unused;
void *mem = xmalloc (required);
assert (alignment >= 1 && alignment <= alignof (max_align_t));
unused = cnn_predictor_construct (required, mem, &alignment);
assert (unused == required);
(void) unused;
return mem;
}
#include <tarot/cnn_private_impl.h>
#include <tarot/game_private_impl.h>
#include <tarot/features_private_impl.h>
......@@ -29,6 +29,7 @@ extern "C"
#endif
struct TarotGame;
struct TarotPredictor;
/**
* tarot_cnn_predict:
......@@ -43,6 +44,18 @@ extern "C"
*/
void tarot_cnn_predict_alloc (const TarotGame *game, double **score, size_t *n_score);
/**
* tarot_cnn_predictor_construct:
* @mem: (array length=max_mem):
* @alignment: (out):
*/
size_t tarot_cnn_predictor_construct (size_t max_mem, char *mem, size_t *alignment);
/**
* tarot_cnn_predictor_alloc:
*/
struct TarotPredictor *tarot_cnn_predictor_alloc (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......
......@@ -32,6 +32,9 @@ extern "C"
static size_t cnn_predict (const TarotGame * game, size_t max_score,
double *score);
static size_t cnn_predictor_construct (size_t max_mem, char *mem,
size_t *alignment);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......
......@@ -225,6 +225,18 @@ cnn_predict (const TarotGame * game, size_t max_score, double *score)
return n_players;
}
static inline size_t
cnn_predictor_construct (size_t max_mem, char *mem, size_t *alignment)
{
size_t ret = predictor_construct (max_mem, mem, alignment);
if (max_mem >= ret)
{
TarotPredictor *predictor = (TarotPredictor *) mem;
predictor->cnn = 1;
}
return ret;
}
#include <tarot/features_private_impl.h>
#endif /* H_TAROT_CNN_PRIVATE_IMPL_INCLUDED */
......@@ -33,6 +33,7 @@
#include <tarot/simulation.h>
#include <tarot/mcts.h>
#include <tarot/features.h>
#include <tarot/cnn.h>
#ifdef __cplusplus
extern "C"
......
......@@ -380,8 +380,9 @@ extern "C"
int can_play;
double best_score;
TarotGameEvent best_event;
/* For the handful */
/* For the discard */
unsigned int event_data[6];
int cnn;
};
#ifdef __cplusplus
......
......@@ -25,6 +25,7 @@
#include <tarot/game_event_private.h>
#include <tarot/cards_private.h>
#include <tarot/counter_private.h>
#include <tarot/cnn_private.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
......@@ -1342,12 +1343,13 @@ predictor_construct (size_t max_mem, char *mem, size_t *alignment)
predictor->can_play = 0;
predictor->best_event.n = 6;
predictor->best_event.data = predictor->event_data;
predictor->cnn = 0;
return max_mem;
}
return required;
}
static void
static inline void
predictor_copy (TarotPredictor * dest, const TarotPredictor * source)
{
game_copy (&(dest->game), &(source->game));
......@@ -1359,7 +1361,8 @@ predictor_copy (TarotPredictor * dest, const TarotPredictor * source)
}
static double
predictor_eval_one (const TarotGame * game, const TarotGameEvent * event)
stacking_predictor_eval_one (const TarotGame * game,
const TarotGameEvent * event)
{
size_t n_players;
int with_call;
......@@ -1578,8 +1581,44 @@ predictor_eval_one (const TarotGame * game, const TarotGameEvent * event)
return score;
}
static double
cnn_predictor_eval_one (const TarotGame * game, const TarotGameEvent * event)
{
TarotGame copy;
TarotPlayer next;
int has_next = (game_get_next (game, &next) == TAROT_GAME_OK);
double predictions[5];
size_t n_predictions;
assert (has_next);
game_copy (&copy, game);
if (game_add_event (&copy, event) != TAROT_GAME_OK)
{
assert (0);
}
n_predictions =
cnn_predict (&copy, sizeof (predictions) / sizeof (predictions[0]),
predictions);
assert (n_predictions <= sizeof (predictions) / sizeof (predictions[0]));
assert (next < n_predictions);
return predictions[next];
}
static double
predictor_eval_one (int cnn, const TarotGame * game,
const TarotGameEvent * event)
{
if (cnn)
{
return cnn_predictor_eval_one (game, event);
}
else
{
return stacking_predictor_eval_one (game, event);
}
}
static int
predictor_select_bid (const TarotGame * game, TarotBid * bid,
predictor_select_bid (int cnn, const TarotGame * game, TarotBid * bid,
double *best_score)
{
TarotBid minimum, candidate;
......@@ -1592,12 +1631,12 @@ predictor_select_bid (const TarotGame * game, TarotBid * bid,
}
event_set_bid (&e, TAROT_PASS);
*bid = TAROT_PASS;
*best_score = predictor_eval_one (game, &e);
*best_score = predictor_eval_one (cnn, game, &e);
for (candidate = minimum; candidate <= TAROT_DOUBLE_KEEP; candidate++)
{
double candidate_score;
event_set_bid (&e, candidate);
candidate_score = predictor_eval_one (game, &e);
candidate_score = predictor_eval_one (cnn, game, &e);
if (candidate_score > *best_score)
{
*bid = candidate;
......@@ -1608,7 +1647,8 @@ predictor_select_bid (const TarotGame * game, TarotBid * bid,
}
static int
predictor_select_decl (const TarotGame * game, int *decl, double *best_score)
predictor_select_decl (int cnn, const TarotGame * game, int *decl,
double *best_score)
{
int allowed;
TarotPlayer player;
......@@ -1618,11 +1658,12 @@ predictor_select_decl (const TarotGame * game, int *decl, double *best_score)
}
*decl = 0;
*best_score = 0;
(void) cnn;
return 0;
}
static int
predictor_select_call (const TarotGame * game, TarotCard * call,
predictor_select_call (int cnn, const TarotGame * game, TarotCard * call,
double *best_score)
{
static const TarotSuit suits[4] = {
......@@ -1654,7 +1695,7 @@ predictor_select_call (const TarotGame * game, TarotCard * call,
assert (0);
}
event_set_call (&e, c);
candidate_score = predictor_eval_one (game, &e);
candidate_score = predictor_eval_one (cnn, game, &e);
if (candidate_score > *best_score)
{
*call = c;
......@@ -1667,7 +1708,7 @@ predictor_select_call (const TarotGame * game, TarotCard * call,
}
static int
predictor_discard_try_changing_card (const TarotGame * game,
predictor_discard_try_changing_card (int cnn, const TarotGame * game,
size_t n_candidates,
const TarotCard * candidates,
size_t n_discard,
......@@ -1695,7 +1736,7 @@ predictor_discard_try_changing_card (const TarotGame * game,
event_set_discard (&e, n_discard, changed);
if (game_check_event (game, &e))
{
double this_score = predictor_eval_one (game, &e);
double this_score = predictor_eval_one (cnn, game, &e);
if (this_score > *best_score)
{
size_t j;
......@@ -1713,7 +1754,8 @@ predictor_discard_try_changing_card (const TarotGame * game,
/* FIXME: there is a huge bias there, the discard will favor hearts */
static int
predictor_set_discard_greedy (const TarotGame * game, size_t n_candidates,
predictor_set_discard_greedy (int cnn, const TarotGame * game,
size_t n_candidates,
const TarotCard * candidates, size_t n_discard,
TarotCard * discard, double *best_score)
{
......@@ -1739,12 +1781,13 @@ predictor_set_discard_greedy (const TarotGame * game, size_t n_candidates,
{
discard[i] = discard_candidate[i];
}
*best_score = predictor_eval_one (game, &e);
*best_score = predictor_eval_one (cnn, game, &e);
do
{
discard_changed =
predictor_discard_try_changing_card (game, n_candidates, candidates,
n_discard, discard_candidate,
predictor_discard_try_changing_card (cnn, game, n_candidates,
candidates, n_discard,
discard_candidate,
(i_card_to_change++) % n_discard,
discard, best_score);
}
......@@ -1753,7 +1796,7 @@ predictor_set_discard_greedy (const TarotGame * game, size_t n_candidates,
}
static int
predictor_select_discard (const TarotGame * game, size_t *n_cards,
predictor_select_discard (int cnn, const TarotGame * game, size_t *n_cards,
TarotCard * discard, double *best_score)
{
size_t n_discardable = 0;
......@@ -1786,7 +1829,7 @@ predictor_select_discard (const TarotGame * game, size_t *n_cards,
*best_score = -DBL_MAX;
assert (discard_size <= 6);
ret =
predictor_set_discard_greedy (game, n_discardable, discardable,
predictor_set_discard_greedy (cnn, game, n_discardable, discardable,
discard_size, actual_discard, best_score);
if (ret == 0)
{
......@@ -1799,7 +1842,7 @@ predictor_select_discard (const TarotGame * game, size_t *n_cards,
}
static int
predictor_select_card (const TarotGame * game, TarotCard * card,
predictor_select_card (int cnn, const TarotGame * game, TarotCard * card,
double *best_score)
{
size_t n_candidates;
......@@ -1816,13 +1859,13 @@ predictor_select_card (const TarotGame * game, TarotCard * card,
assert (n_candidates <= 78);
assert (n_candidates >= 1);
event_set_card (&e, playable[0]);
*best_score = predictor_eval_one (game, &e);
*best_score = predictor_eval_one (cnn, game, &e);
*card = playable[0];
for (i = 1; i < n_candidates; i++)
{
double candidate_score;
event_set_card (&e, playable[i]);
candidate_score = predictor_eval_one (game, &e);
candidate_score = predictor_eval_one (cnn, game, &e);
if (candidate_score > *best_score)
{
*card = playable[i];
......@@ -1841,32 +1884,35 @@ predictor_analyze (TarotPredictor * predictor)
TarotCard discard[6];
TarotCard card;
size_t n_discard;
if (predictor_select_bid (&(predictor->game),
if (predictor_select_bid (predictor->cnn, &(predictor->game),
&bid, &(predictor->best_score)) == 0)
{
event_set_bid (&(predictor->best_event), bid);
predictor->can_play = 1;
}
else if (predictor_select_decl (&(predictor->game),
else if (predictor_select_decl (predictor->cnn, &(predictor->game),
&decl, &(predictor->best_score)) == 0)
{
event_set_decl (&(predictor->best_event), decl);
predictor->can_play = 1;
}
else if (predictor_select_call (&(predictor->game),
else if (predictor_select_call (predictor->cnn, &(predictor->game),
&call, &(predictor->best_score)) == 0)
{
event_set_call (&(predictor->best_event), call);
predictor->can_play = 1;
}
else if (predictor_select_discard (&(predictor->game), &n_discard, discard,
&(predictor->best_score)) == 0)
else if ((predictor_select_discard (predictor->cnn,
&(predictor->game),
&n_discard,
discard,
&(predictor->best_score))) == 0)
{
assert (n_discard <= 6);
event_set_discard (&(predictor->best_event), n_discard, discard);
predictor->can_play = 1;
}
else if (predictor_select_card (&(predictor->game),
else if (predictor_select_card (predictor->cnn, &(predictor->game),
&card, &(predictor->best_score)) == 0)
{
event_set_card (&(predictor->best_event), card);
......@@ -1874,14 +1920,13 @@ predictor_analyze (TarotPredictor * predictor)
}
}
static void
static inline void
predictor_set_game (TarotPredictor * predictor, const TarotGame * game)
{
TarotGameIterator i;
const TarotGameEvent *next_event;
TarotPlayer next_player;
size_t n_cards;
predictor->can_play = 0;
game_initialize (&(predictor->game), 4, 0);
game_iterator_setup (&i, game);
......@@ -1971,7 +2016,7 @@ predictor_set_game (TarotPredictor * predictor, const TarotGame * game)
predictor_analyze (predictor);
}
static const TarotGameEvent *
static inline const TarotGameEvent *
predictor_best (const TarotPredictor * predictor, double *score)
{
if (predictor->can_play)
......@@ -1985,7 +2030,7 @@ predictor_best (const TarotPredictor * predictor, double *score)
}
}
static size_t
static inline size_t
predictor_eval (const TarotPredictor * predictor, size_t n_candidates,
const TarotGameEvent ** candidates, size_t start, size_t max,
double *score)
......@@ -1999,7 +2044,9 @@ predictor_eval (const TarotPredictor * predictor, size_t n_candidates,
}
if (i >= start && i - start < max)
{
score[i] = predictor_eval_one (&(predictor->game), candidates[i]);
score[i] =
predictor_eval_one (predictor->cnn, &(predictor->game),
candidates[i]);
}
}
return n_candidates;
......@@ -2272,5 +2319,6 @@ features_cnn_add (const TarotGame * game, size_t max, double *data)
#include <tarot/game_event_private_impl.h>
#include <tarot/cards_private_impl.h>
#include <tarot/counter_private_impl.h>
#include <tarot/cnn_private_impl.h>
#endif /* H_TAROT_FEATURES_PRIVATE_IMPL_INCLUDED */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment