/**
   * This method is the access point to the planning procedure. Initially, it adds all variables
   * from axioms to the set of found vars, then does the linear planning. If lp does not solve the
   * problem and there are subtasks, goal-driven recursive planning with backtracking is invoked.
   * Planning is performed until no new variables are introduced into the algorithm.
   */
  public EvaluationAlgorithm invokePlaning(Problem problem, boolean _computeAll) {
    long startTime = System.currentTimeMillis();

    computeAll = _computeAll;
    EvaluationAlgorithm algorithm = new EvaluationAlgorithm();

    PlanningContext context = problem.getCurrentContext();

    // add all axioms at the beginning of an algorithm
    Collection<Var> flattened = new HashSet<Var>();
    for (Iterator<Rel> axiomIter = problem.getAxioms().iterator(); axiomIter.hasNext(); ) {
      Rel rel = axiomIter.next();

      unfoldVarsToSet(rel.getOutputs(), flattened);

      // do not overwrite values of variables that come via args of compute() or as inputs of
      // independent subtasks
      if (!problem.getAssumptions().containsAll(flattened)
      // do not overwrite values of already known variables.
      // typically this is the case when a value of a variable
      // is given in a scheme via a properties window
      //                    && !problem.getKnownVars().containsAll( flattened )
      ) {
        algorithm.addRel(rel);
      }
      axiomIter.remove();
      context.getKnownVars().addAll(flattened);
      flattened.clear();
    }

    context.getFoundVars().addAll(context.getKnownVars());

    // remove all known vars with no relations
    for (Iterator<Var> varIter = context.getKnownVars().iterator(); varIter.hasNext(); ) {
      if (varIter.next().getRels().isEmpty()) {
        varIter.remove();
      }
    }

    // start planning
    if (problem.getRelsWithSubtasks().isEmpty()
        && linearForwardSearch(context, algorithm, computeAll)) {
      if (isLinearLoggingOn()) logger.debug("Problem solved without subtasks");
    } else if (!problem.getRelsWithSubtasks().isEmpty() && subtaskPlanning(problem, algorithm)) {
      if (isLinearLoggingOn()) logger.debug("Problem solved with subtasks");
    } else if (!computeAll) {
      if (isLinearLoggingOn()) logger.debug("Problem not solved");
    }

    if (!nested) {
      logger.info("Planning time: " + (System.currentTimeMillis() - startTime) + "ms.");
    }
    return algorithm;
  }