protected void expandNode(
      FormationSearchNode<SymmetricGame, Set<Action>> node,
      Queue<FormationSearchNode<SymmetricGame, Set<Action>>> queue,
      Map<Set<Action>, FormationSearchNode<SymmetricGame, Set<Action>>> nodes,
      SymmetricMultiAgentSystem bound) {

    Set<Action> currentPlayerActions = node.getGame().getActions();

    if (currentPlayerActions.size() != bound.getActions().size()) {

      for (Action action : actions) {

        if (bound.getActions().contains(action) && !currentPlayerActions.contains(action)) {

          Set<Action> key = new HashSet<Action>(currentPlayerActions);

          key.add(action);

          if (!nodes.containsKey(key)) {
            double tau = rationalizableFinder.rationalizableTau(action, node.getGame(), getBase());

            if (tau > 0) {
              FormationSearchNode<SymmetricGame, Set<Action>> child = createNode(key);

              if (child != null) {
                queue.offer(child);
                nodes.put(key, child);
              }
            }
          }
        }
      }
    }
  }
  protected void initialNodes(
      SymmetricGame base,
      Queue<FormationSearchNode<SymmetricGame, Set<Action>>> queue,
      Map<Set<Action>, FormationSearchNode<SymmetricGame, Set<Action>>> nodes,
      SymmetricMultiAgentSystem bound) {

    for (Action action : actions) {
      if (bound.getActions().contains(action)) {
        Set<Action> strategySpace = new HashSet<Action>();

        strategySpace.add(action);

        SymmetricGame game = new ActionReducedSymmetricGame(base, strategySpace);

        double epsilon = rationalizableFinder.rationalizableEpsilon(game, base);
        epsilon = Math.round(epsilon / tolerance) * tolerance;

        FormationSearchNode<SymmetricGame, Set<Action>> node =
            new FormationSearchNode<SymmetricGame, Set<Action>>(game, strategySpace, epsilon, 1);

        queue.offer(node);
        nodes.put(strategySpace, node);
      }
    }
  }