void M2MFstAligner::_conditional_max( bool y_given_x ){ /* Compute the conditional distribution, P(Y|X) using the WFST paradigm. This is bassed on the approach from Shu and Hetherington 2002. It is assumed that all WFSTs and operations use the Log semiring. Given: FST1 = P(X,Y) Compute: FST2 = P(X) := Map_inv(Det(RmEps(Proj_i(FST1)))) FST3 = P(Y|X) := Compose(FST2,FST1) Proj_i: project on input labels RmEps: epsilon removal Det: determinize Map_inv: invert weights Notes: An analogous process may be used to compute P(X|Y). In this case one would project on OUTPUT labels - Proj_o, and reverse the composition order to Compose(FST1,FST2). Future work: What we are doing here in terms of *generating* the JOINT fst each time is really just a dumb hack. We *should* encode the model in an FST and encode the individual lattices, rather than doing the hacky manual label encoding that we currently rely on. */ //Joint distribution that we start with VectorFst<LogArc>* joint = new VectorFst<LogArc>(); SymbolTable* misyms = new SymbolTable("misyms"); SymbolTable* mosyms = new SymbolTable("mosyms"); joint->AddState(); joint->AddState(); joint->SetStart(0); joint->SetFinal(1,LogArc::Weight::One()); map<LogArc::Label,LogWeight>::iterator it; for( it=prev_alignment_model.begin(); it != prev_alignment_model.end(); it++ ){ string isym = isyms->Find((*it).first); vector<string> io = tokenize_utf8_string( &isym, &s1s2_sep ); LogArc arc( misyms->AddSymbol(io[0]), mosyms->AddSymbol(io[1]), (*it).second, 1 ); joint->AddArc( 0, arc ); } //VectorFst<LogArc>* joint = new VectorFst<LogArc>(); //Push<LogArc,REWEIGHT_TO_FINAL>(*_joint, joint, kPushWeights); //joint->SetFinal(1,LogWeight::One()); joint->Write("m2mjoint.fst"); //BEGIN COMPUTE MARGINAL P(X) VectorFst<LogArc>* dmarg; if( y_given_x ) dmarg = new VectorFst<LogArc>(ProjectFst<LogArc>(*joint, PROJECT_INPUT)); else dmarg = new VectorFst<LogArc>(ProjectFst<LogArc>(*joint, PROJECT_OUTPUT)); RmEpsilon(dmarg); VectorFst<LogArc>* marg = new VectorFst<LogArc>(); Determinize(*dmarg, marg); ArcMap(marg, InvertWeightMapper<LogArc>()); if( y_given_x ) ArcSort(marg, OLabelCompare<LogArc>()); else ArcSort(marg, ILabelCompare<LogArc>()); //END COMPUTE MARGINAL P(X) marg->Write("marg.fst"); //CONDITIONAL P(Y|X) VectorFst<LogArc>* cond = new VectorFst<LogArc>(); if( y_given_x ) Compose(*marg, *joint, cond); else Compose(*joint, *marg, cond); //cond now contains the conditional distribution P(Y|X) cond->Write("cond.fst"); //Now update the model with the new values for( MutableArcIterator<VectorFst<LogArc> > aiter(cond, 0); !aiter.Done(); aiter.Next() ){ LogArc arc = aiter.Value(); string lab = misyms->Find(arc.ilabel)+"}"+mosyms->Find(arc.olabel); int labi = isyms->Find(lab); alignment_model[labi] = arc.weight; prev_alignment_model[labi] = LogWeight::Zero(); } delete joint, marg, cond, dmarg; delete misyms, mosyms; return; }
Move ChooseMove(const GameState& game, unsigned iterations) { std::mt19937 r(GlobalRandomDevice()); MCTSNode root; MCTSNode* store = (MCTSNode*)malloc(sizeof(MCTSNode) * iterations); MCTSNode* store_head = store; for (unsigned iter = 0; iter < iterations; ++iter) { GameState sim_state = Determinize(game, r); // Selection MCTSNode* node = &root; while (!node->HasUntriedMoves(sim_state) && node->HasChildren()) { MCTSNode* next_node = node->UCTSelectChild(sim_state); // Update availability for (MCTSNode* avail_node = node->m_child; avail_node; avail_node = avail_node->m_siblings) { if (sim_state.m_possible_moves.Contains(avail_node->m_move)) { avail_node->m_availability++; } } sim_state.ProcessMove(next_node->m_move); node = next_node; } // Expansion if (node->HasUntriedMoves(sim_state)) { Move m = node->ChooseRandomUntriedMove(sim_state, r); for (MCTSNode* avail_node = node->m_child; avail_node; avail_node = avail_node->m_siblings) { if (sim_state.m_possible_moves.Contains(avail_node->m_move)) { avail_node->m_availability++; } } sim_state.ProcessMove(m); node = node->AddChild(m, store_head); store_head += 1; node->m_availability++; } // Simulation sim_state.PlayOutRandomly(r); // Backpropagation bool won = sim_state.m_winner == (Winner)game.m_active_player_index; while (node) { node->m_visits++; if (won) node->m_wins++; node = node->m_parent; } } MCTSNode* best_node = nullptr; uint32_t best_visits = 0; for (MCTSNode* node = root.m_child; node; node = node->m_siblings) { if (node->m_visits > best_visits) { best_visits = node->m_visits; best_node = node; } } Move m = best_node->m_move; free(store); return m; }