parameters: (dist, payoff_matrices, num_players, proj_grad=True)
return_statement: return (grad_dist,), np.mean(unreg_exp), np.mean(unreg_exp)
docstring: Computes exploitablity gradient.
  
    Args:
      dist: list of 1-d np.arrays, current estimate of nash distribution
      payoff_matrices: dictionary with keys as tuples of agents (i, j) and
          values of (2 x A x A) np.arrays, payoffs for each joint action. keys
          are sorted and arrays should be indexed in the same order
      num_players: int, number of players, in case payoff_matrices is abbreviated
      proj_grad: bool, if True, projects dist gradient onto simplex
    Returns:
      gradient of payoff w.r.t. (dist) as tuple
      unregularized exploitability (stochastic estimate)
      unregularized exploitability (stochastic estimate) *duplicate
docstring_summary: Computes exploitablity gradient.
docstring_tokens: Computes exploitablity gradient .
function: def gradients(dist, payoff_matrices, num_players, proj_grad=True):
    """Computes exploitablity gradient.
  
    Args:
      dist: list of 1-d np.arrays, current estimate of nash distribution
      payoff_matrices: dictionary with keys as tuples of agents (i, j) and
          values of (2 x A x A) np.arrays, payoffs for each joint action. keys
          are sorted and arrays should be indexed in the same order
      num_players: int, number of players, in case payoff_matrices is abbreviated
      proj_grad: bool, if True, projects dist gradient onto simplex
    Returns:
      gradient of payoff w.r.t. (dist) as tuple
      unregularized exploitability (stochastic estimate)
      unregularized exploitability (stochastic estimate) *duplicate
    """
    # first compute best responses and payoff gradients
    grad_dist = []
    unreg_exp = []
    for i in range(num_players):
  
      nabla_i = np.zeros_like(dist[i])
      # TODO(imgemp): decide if averaging over nablas provides best comparison
      for j in range(num_players):
        if j == i:
          continue
        if i < j:
          hess_i_ij = payoff_matrices[(i, j)][0]
        else:
          hess_i_ij = payoff_matrices[(j, i)][1].T
  
        nabla_ij = hess_i_ij.dot(dist[j])
        nabla_i += nabla_ij / float(num_players - 1)
  
      grad_dist_i = -nabla_i
      if proj_grad:
        grad_dist_i = simplex.project_grad(grad_dist_i)
      grad_dist.append(nabla_i)
  
      unreg_exp.append(np.max(nabla_i) - nabla_i.dot(dist[i]))
  
    return (grad_dist,), np.mean(unreg_exp), np.mean(unreg_exp)
function_tokens: def gradients ( dist , payoff_matrices , num_players , proj_grad = True ) : # first compute best responses and payoff gradients grad_dist = [ ] unreg_exp = [ ] for i in range ( num_players ) : nabla_i = np . zeros_like ( dist [ i ] ) # TODO(imgemp): decide if averaging over nablas provides best comparison for j in range ( num_players ) : if j == i : continue if i < j : hess_i_ij = payoff_matrices [ ( i , j ) ] [ 0 ] else : hess_i_ij = payoff_matrices [ ( j , i ) ] [ 1 ] . T nabla_ij = hess_i_ij . dot ( dist [ j ] ) nabla_i += nabla_ij / float ( num_players - 1 ) grad_dist_i = - nabla_i if proj_grad : grad_dist_i = simplex . project_grad ( grad_dist_i ) grad_dist . append ( nabla_i ) unreg_exp . append ( np . max ( nabla_i ) - nabla_i . dot ( dist [ i ] ) ) return ( grad_dist , ) , np . mean ( unreg_exp ) , np . mean ( unreg_exp )