parameters: (self, pid, state, my_reaches)
docstring: Recursively traverse game tree to compute aggregate policy.
docstring_summary: Recursively traverse game tree to compute aggregate policy.
docstring_tokens: Recursively traverse game tree to compute aggregate policy .
function: def _rec_aggregate(self, pid, state, my_reaches):
      """Recursively traverse game tree to compute aggregate policy."""
      if state.is_terminal():
        return
  
      if state.is_simultaneous_node():
        assert (self._game_type.dynamics == pyspiel.GameType.Dynamics.SIMULTANEOUS
               ), "Game must be simultaneous-move"
        assert (self._game_type.chance_mode == pyspiel.GameType.ChanceMode
                .DETERMINISTIC), "Chance nodes not supported"
        assert (self._game_type.information == pyspiel.GameType.Information
                .ONE_SHOT), "Only one-shot NFGs supported"
        policies = _aggregate_at_state(self._joint_policies, state, pid)
        state_key = self._state_key(state, pid)
  
        self._policy[state_key] = {}
  
        for player_policies, weight in zip(policies, my_reaches):
          player_policy = player_policies[pid]
          for action in player_policy.keys():
            if action in self._policy[state_key]:
              self._policy[state_key][action] += weight * player_policy[action]
            else:
              self._policy[state_key][action] = weight * player_policy[action]
        # No recursion because we only support one shot simultaneous games.
        return
  
      if state.is_chance_node():
        for action in state.legal_actions():
          new_state = state.child(action)
          self._rec_aggregate(pid, new_state, my_reaches)
        return
  
      current_player = state.current_player()
  
      state_key = self._state_key(state, current_player)
      action_probabilities_list = _aggregate_at_state(self._joint_policies, state,
                                                      current_player)
      if pid == current_player:
        # update the current node
        # will need the observation to query the policies
        if state not in self._policy:
          self._policy[state_key] = {}
  
      for action in state.legal_actions():
        new_reaches = np.copy(my_reaches)
        if pid == current_player:
          for idx, state_action_probs in enumerate(action_probabilities_list):
            # compute the new reach for each policy for this action
            new_reaches[idx] *= state_action_probs.get(action, 0)
            # add reach * prob(a) for this policy to the computed policy
            if action in self._policy[state_key].keys():
              self._policy[state_key][action] += new_reaches[idx]
            else:
              self._policy[state_key][action] = new_reaches[idx]
  
        # recurse
        self._rec_aggregate(pid, state.child(action), new_reaches)
function_tokens: def _rec_aggregate ( self , pid , state , my_reaches ) : if state . is_terminal ( ) : return if state . is_simultaneous_node ( ) : assert ( self . _game_type . dynamics == pyspiel . GameType . Dynamics . SIMULTANEOUS ) , "Game must be simultaneous-move" assert ( self . _game_type . chance_mode == pyspiel . GameType . ChanceMode . DETERMINISTIC ) , "Chance nodes not supported" assert ( self . _game_type . information == pyspiel . GameType . Information . ONE_SHOT ) , "Only one-shot NFGs supported" policies = _aggregate_at_state ( self . _joint_policies , state , pid ) state_key = self . _state_key ( state , pid ) self . _policy [ state_key ] = { } for player_policies , weight in zip ( policies , my_reaches ) : player_policy = player_policies [ pid ] for action in player_policy . keys ( ) : if action in self . _policy [ state_key ] : self . _policy [ state_key ] [ action ] += weight * player_policy [ action ] else : self . _policy [ state_key ] [ action ] = weight * player_policy [ action ] # No recursion because we only support one shot simultaneous games. return if state . is_chance_node ( ) : for action in state . legal_actions ( ) : new_state = state . child ( action ) self . _rec_aggregate ( pid , new_state , my_reaches ) return current_player = state . current_player ( ) state_key = self . _state_key ( state , current_player ) action_probabilities_list = _aggregate_at_state ( self . _joint_policies , state , current_player ) if pid == current_player : # update the current node # will need the observation to query the policies if state not in self . _policy : self . _policy [ state_key ] = { } for action in state . legal_actions ( ) : new_reaches = np . copy ( my_reaches ) if pid == current_player : for idx , state_action_probs in enumerate ( action_probabilities_list ) : # compute the new reach for each policy for this action new_reaches [ idx ] *= state_action_probs . get ( action , 0 ) # add reach * prob(a) for this policy to the computed policy if action in self . _policy [ state_key ] . keys ( ) : self . _policy [ state_key ] [ action ] += new_reaches [ idx ] else : self . _policy [ state_key ] [ action ] = new_reaches [ idx ] # recurse self . _rec_aggregate ( pid , state . child ( action ) , new_reaches )