src/solve_all_subgames.cpp
// Currently assume that this is a street-initial node.
// Might need to do up to four solves.  Imagine we have an asymmetric base
// betting tree, and an asymmetric solving method.
Currently assume that this is a street-initial node.
Might need to do up to four solves.  Imagine we have an asymmetric base
betting tree, and an asymmetric solving method.
Currently assume that this is a street - initial node . Might need to do up to four solves . Imagine we have an asymmetric base betting tree and an asymmetric solving method .
void SubgameSolver::ResolveUnsafe(Node *node, int gbd, const string &action_sequence,
				  const ReachProbs &reach_probs) {
  int st = node->Street();
  fprintf(stderr, "ResolveUnsafe %s st %i nt %i gbd %i\n", action_sequence.c_str(), st,
	  node->NonterminalID(), gbd);
  int num_players = Game::NumPlayers();
  HandTree hand_tree(st, gbd, Game::MaxStreet());
  unique_ptr<EGCFR> eg_cfr;
  if (method_ == ResolvingMethod::UNSAFE) {
    eg_cfr.reset(new UnsafeEGCFR(subgame_card_abstraction_, base_card_abstraction_,
				 base_betting_abstraction_, subgame_cfr_config_, base_cfr_config_,
				 subgame_buckets_, num_inner_threads_));
    if (st < Game::MaxStreet()) {
      eg_cfr->SetSplitStreet(st + 1);
    }
  } else {
    fprintf(stderr, "Method not supported yet\n");
    exit(-1);
  }
  int num_asym_players = base_betting_abstraction_.Asymmetric() ? num_players : 1;
  for (int asym_p = 0; asym_p < num_asym_players; ++asym_p) {
    BettingTrees *base_subtrees = nullptr;
    BettingTrees *subgame_subtrees = CreateSubtrees(node, asym_p, false);
    if (! base_mem_) {
      fprintf(stderr, "base_mem_ false not supported currently\n");
      exit(-1);
#if 0
      base_subtrees = CreateSubtrees(node, asym_p, true);
      unique_ptr<CFRValues> base_subgame_strategy =
	    ReadBaseSubgameStrategy(base_card_abstraction_, base_betting_abstraction_,
				    base_cfr_config_, base_betting_trees_.get(), base_buckets_,
				    subgame_buckets_, base_it_, node,  gbd, "x", reach_probs,
				    base_subtrees, current_, asym_p);
      dynamic_cbr_.reset(new DynamicCBR2(base_card_abstraction_, base_betting_abstraction_,
					 base_cfr_config_, base_buckets_, 1));
      if (current_) dynamic_cbr_->MoveRegrets(base_subgame_strategy);
      else          dynamic_cbr_->MoveSumprobs(base_subgame_strategy);
#endif
    }
    if (method_ == ResolvingMethod::UNSAFE) {
      struct timespec start, finish;
      clock_gettime(CLOCK_MONOTONIC, &start);
      eg_cfr->SolveSubgame(subgame_subtrees, gbd, reach_probs, action_sequence, &hand_tree, nullptr,
			   -1, true, num_subgame_its_);
      clock_gettime(CLOCK_MONOTONIC, &finish);
      resolving_secs_ += (finish.tv_sec - start.tv_sec);
      resolving_secs_ += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
      num_resolves_ += 1;
      for (int solve_p = 0; solve_p < num_players; ++solve_p) {
	WriteSubgame(subgame_subtrees->Root(), action_sequence, action_sequence, gbd,
		     base_card_abstraction_, subgame_card_abstraction_, base_betting_abstraction_,
		     subgame_betting_abstraction_, base_cfr_config_, subgame_cfr_config_, method_,
		     eg_cfr->Sumprobs().get(), st, gbd, asym_p, solve_p, st);
      }
    } else {
      for (int solve_p = 0; solve_p < num_players; ++solve_p) {
	if (! card_level_) {
	  fprintf(stderr, "DynamicCBR cannot compute bucket-level CVs\n");
	  exit(-1);
	}
	shared_ptr<double []> t_vals;
	if (method_ != ResolvingMethod::UNSAFE) {
	  if (base_mem_) {
	    t_vals = dynamic_cbr_->Compute(node, reach_probs, gbd, trunk_hand_tree_.get(),
					   solve_p^1, cfrs_, zero_sum_, current_,
					   pure_streets_[st]);
	  } else {
	    t_vals = dynamic_cbr_->Compute(base_subtrees->Root(), reach_probs, gbd, &hand_tree,
					   solve_p^1, cfrs_, zero_sum_, current_,
					   pure_streets_[st]);
	  }
	}
	eg_cfr->SolveSubgame(subgame_subtrees, gbd, reach_probs, action_sequence, &hand_tree,
			     t_vals.get(), solve_p, false, num_subgame_its_);
	WriteSubgame(subgame_subtrees->Root(), action_sequence, action_sequence, gbd,
		     base_card_abstraction_, subgame_card_abstraction_, base_betting_abstraction_,
		     subgame_betting_abstraction_, base_cfr_config_, subgame_cfr_config_, method_,
		     eg_cfr->Sumprobs().get(), st, gbd, asym_p, solve_p, st);
      }
    }
    delete base_subtrees;
    delete subgame_subtrees;
  }
}
void SubgameSolver :: ResolveUnsafe ( Node * node , int gbd , const string & action_sequence , const ReachProbs & reach_probs ) { int st = node -> Street ( ) ; fprintf ( stderr , " \n " , action_sequence . c_str ( ) , st , node -> NonterminalID ( ) , gbd ) ; int num_players = Game :: NumPlayers ( ) ; HandTree hand_tree ( st , gbd , Game :: MaxStreet ( ) ) ; unique_ptr < EGCFR > eg_cfr ; if ( method_ == ResolvingMethod :: UNSAFE ) { eg_cfr . reset ( new UnsafeEGCFR ( subgame_card_abstraction_ , base_card_abstraction_ , base_betting_abstraction_ , subgame_cfr_config_ , base_cfr_config_ , subgame_buckets_ , num_inner_threads_ ) ) ; if ( st < Game :: MaxStreet ( ) ) { eg_cfr -> SetSplitStreet ( st + 1 ) ; } } else { fprintf ( stderr , " \n " ) ; exit ( -1 ) ; } int num_asym_players = base_betting_abstraction_ . Asymmetric ( ) ? num_players : 1 ; for ( int asym_p = 0 ; asym_p < num_asym_players ; ++ asym_p ) { BettingTrees * base_subtrees = nullptr ; BettingTrees * subgame_subtrees = CreateSubtrees ( node , asym_p , false ) ; if ( ! base_mem_ ) { fprintf ( stderr , " \n " ) ; exit ( -1 ) ; #if 0 base_subtrees = CreateSubtrees ( node , asym_p , true ) ; unique_ptr < CFRValues > base_subgame_strategy = ReadBaseSubgameStrategy ( base_card_abstraction_ , base_betting_abstraction_ , base_cfr_config_ , base_betting_trees_ . get ( ) , base_buckets_ , subgame_buckets_ , base_it_ , node , gbd , " " , reach_probs , base_subtrees , current_ , asym_p ) ; dynamic_cbr_ . reset ( new DynamicCBR2 ( base_card_abstraction_ , base_betting_abstraction_ , base_cfr_config_ , base_buckets_ , 1 ) ) ; if ( current_ ) dynamic_cbr_ -> MoveRegrets ( base_subgame_strategy ) ; else dynamic_cbr_ -> MoveSumprobs ( base_subgame_strategy ) ; #endif } if ( method_ == ResolvingMethod :: UNSAFE ) { struct timespec start , finish ; clock_gettime ( CLOCK_MONOTONIC , & start ) ; eg_cfr -> SolveSubgame ( subgame_subtrees , gbd , reach_probs , action_sequence , & hand_tree , nullptr , -1 , true , num_subgame_its_ ) ; clock_gettime ( CLOCK_MONOTONIC , & finish ) ; resolving_secs_ += ( finish . tv_sec - start . tv_sec ) ; resolving_secs_ += ( finish . tv_nsec - start . tv_nsec ) / 1000000000.0 ; num_resolves_ += 1 ; for ( int solve_p = 0 ; solve_p < num_players ; ++ solve_p ) { WriteSubgame ( subgame_subtrees -> Root ( ) , action_sequence , action_sequence , gbd , base_card_abstraction_ , subgame_card_abstraction_ , base_betting_abstraction_ , subgame_betting_abstraction_ , base_cfr_config_ , subgame_cfr_config_ , method_ , eg_cfr -> Sumprobs ( ) . get ( ) , st , gbd , asym_p , solve_p , st ) ; } } else { for ( int solve_p = 0 ; solve_p < num_players ; ++ solve_p ) { if ( ! card_level_ ) { fprintf ( stderr , " \n " ) ; exit ( -1 ) ; } shared_ptr < double [ ] > t_vals ; if ( method_ != ResolvingMethod :: UNSAFE ) { if ( base_mem_ ) { t_vals = dynamic_cbr_ -> Compute ( node , reach_probs , gbd , trunk_hand_tree_ . get ( ) , solve_p ^ 1 , cfrs_ , zero_sum_ , current_ , pure_streets_ [ st ] ) ; } else { t_vals = dynamic_cbr_ -> Compute ( base_subtrees -> Root ( ) , reach_probs , gbd , & hand_tree , solve_p ^ 1 , cfrs_ , zero_sum_ , current_ , pure_streets_ [ st ] ) ; } } eg_cfr -> SolveSubgame ( subgame_subtrees , gbd , reach_probs , action_sequence , & hand_tree , t_vals . get ( ) , solve_p , false , num_subgame_its_ ) ; WriteSubgame ( subgame_subtrees -> Root ( ) , action_sequence , action_sequence , gbd , base_card_abstraction_ , subgame_card_abstraction_ , base_betting_abstraction_ , subgame_betting_abstraction_ , base_cfr_config_ , subgame_cfr_config_ , method_ , eg_cfr -> Sumprobs ( ) . get ( ) , st , gbd , asym_p , solve_p , st ) ; } } delete base_subtrees ; delete subgame_subtrees ; } }
Currently assume that this is a street-initial node.
Currently assume that this is a street - initial node .
// The action sequence passed in should specify the root of the system // we are reading (the base system). // We never finished implementing this function. // We are calculating CBRs from the *base* strategy, not the resolved // endgame strategy.  So pass in base_card_abstraction_, etc. // One solve for unsafe endgame solving, no t_vals // Write out the P0 and P1 strategies // What should I be supplying for the betting abstraction, CFR // config and betting tree?  Does it matter? // When base_mem_ is true, we use a global betting tree, a global // hand tree and have a global base strategy. // We assume that pure_streets_[st] tells us whether to purify // for the entire endgame. // Pass in false for both_players.  I am doing separate solves for // each player.