public void setChildrenCriteriaWeights(Criterion parent, int precision) {
    if (parent.hasChildren()) {
      CriterionWeightsMatrix critM =
          new CriterionWeightsMatrix(
              parent.getChildren().size(),
              new HashSet<CriterionImportance>(parent.getImportanceChildren()));

      setChildrenCriteriaWeights(parent, critM.getMatrix(), precision);
    }
  }
  public void setChildrenCriteriaWeights(Criterion parent, Matrix m, int precision) {
    Vector<Double> criteriaWeights = calculateEigenvector(m, precision);

    if (criteriaWeights.size() > 0 && criteriaWeights.size() >= parent.getChildren().size()) {
      Iterator<Criterion> itiLeaf = parent.getChildren().iterator();
      int i = 0;
      while (itiLeaf.hasNext()) {
        Criterion leafCriterion = itiLeaf.next();
        leafCriterion.setWeight(criteriaWeights.get(i));
        log.info(
            leafCriterion.getName()
                + ": local weight = "
                + leafCriterion.getWeight()
                + ", global weight = "
                + leafCriterion.getGlobalWeight());
        i++;
      }
    }
  }
  // TODO: neuen Exceptiontyp einf¸hren!
  public EvaluationResult evaluate(List<Evaluation> evals, int precision) throws Exception {

    log.info("---------- new evaluation ----------");

    if (!sanityCheck(evals)) throw new Exception("Given decision model not complete.");

    Map<Alternative, Double> alternativeMultiplicativeMap = new HashMap<Alternative, Double>();
    Map<Alternative, Double> alternativeAdditiveMap = new HashMap<Alternative, Double>();
    Map<Alternative, Double> alternativePositiveMap = new HashMap<Alternative, Double>();
    Map<Alternative, Double> alternativeNegativeMap = new HashMap<Alternative, Double>();

    // Filter Alternatives

    // GoalWeights
    GoalWeightsMatrix critM =
        new GoalWeightsMatrix(
            decision.getGoals().size(), new HashSet<GoalImportance>(decision.getImportanceGoals()));
    Vector<Double> goalsWeights = calculateEigenvector(critM.getMatrix(), precision);
    if (goalsWeights.size() < decision.getGoals().size())
      for (int i = goalsWeights.size() - 1; i < decision.getGoals().size(); i++)
        goalsWeights.add(0D);
    for (int i = 0; i < decision.getGoals().size(); i++)
      decision.getGoals().get(i).setWeight(goalsWeights.get(i));
    log.info("goals weights: " + goalsWeights);

    int g = 0;
    for (Goal goal : decision.getGoals()) {

      log.info("processing goal " + goal.getName());

      // ChildrenWeights
      setChildrenCriteriaWeights(goal);
      for (Criterion c : goal.getAllDescendants()) setChildrenCriteriaWeights(c);

      List<Criterion> leafCriteria = goal.getLeafCriteria();

      setAlternativeEvaluations(new HashSet<AlternativeEvaluation>());

      Evaluation evaluation = evals != null && evals.size() > g ? evals.get(g) : null;

      if (evaluation == null) {
        evaluation = new Evaluation();
        for (Criterion leaf : leafCriteria) {
          if (CriterionType.QUALITATIVE.equals(leaf.getType())) {
            AlternativeWeightsMatrix m =
                new AlternativeWeightsMatrix(
                    decision.getAlternatives().size(), leaf.getImportanceAlternatives(), leaf);
            evaluation.getEvaluations().add(m.getMatrix());
            log.info("created matrix for " + leaf.getName());
            log.info(m.getMatrix().toString());
          } else {
            AlternativeValuesMatrix m =
                new AlternativeValuesMatrix(
                    decision.getAlternatives().size(), leaf.getValuesAlternatives(), leaf);
            evaluation.getEvaluations().add(m.getMatrix());
            log.info("created matrix for " + leaf.getName());
            log.info(m.getMatrix().toString());
          }
        }
      } else {
        // TODO: check if evaluation is correct/complete - sanity
        log.info("no health check for manual evaluations, yet");
      }

      int i = 0;
      for (Matrix m : evaluation.getEvaluations()) {
        // System.out.print("Matrix to Eigen for "
        // + getDecision().getAlternatives().size()
        // + " alternatives, criterion " + leafCriteria.get(i) + ":");
        // m.print(2, 2);
        if (m != null) {
          Vector<Double> normalized = calculateEigenvector(m, precision);
          log.info(
              "normalization for criterion " + leafCriteria.get(i) + ": " + normalized.toString());

          for (int j = 0; j < normalized.size(); j++)
            getAlternativeEvaluations()
                .add(
                    new AlternativeEvaluation(
                        leafCriteria.get(i),
                        getDecision().getAlternatives().get(j),
                        normalized.get(j)));
        }
        i++;
      }

      log.info("evaluations for goal " + g + ": " + getAlternativeEvaluations());

      Map<Alternative, Double> alternativeGoalMap = new HashMap<Alternative, Double>();

      for (AlternativeEvaluation ce : getAlternativeEvaluations()) {
        alternativeGoalMap.put(
            ce.getAlternative(),
            new Double(
                (alternativeGoalMap.get(ce.getAlternative()) != null
                        ? alternativeGoalMap.get(ce.getAlternative()).doubleValue()
                        : 0D)
                    + (ce.getValue() * ce.getCriterion().getGlobalWeight())));
      }
      log.info("goalMap: " + alternativeGoalMap);
      for (Alternative a : alternativeGoalMap.keySet()) {
        log.info("Aggregating for Alternative " + a);
        if (goal.getGoalType().equals(GoalType.POSITIVE))
          alternativePositiveMap.put(
              a,
              (alternativePositiveMap.get(a) != null
                      ? alternativePositiveMap.get(a).doubleValue()
                      : 0D)
                  + alternativeGoalMap.get(a));
        else
          alternativeNegativeMap.put(
              a,
              (alternativeNegativeMap.get(a) != null
                      ? alternativeNegativeMap.get(a).doubleValue()
                      : 0D)
                  + alternativeGoalMap.get(a));
      }
      g++;
    }

    log.info("Positive Map " + alternativePositiveMap);
    log.info("Negative Map " + alternativeNegativeMap);

    for (Alternative a : decision.getAlternatives()) {
      log.info("Generating Indices for Alternative " + a);
      alternativeMultiplicativeMap.put(
          a,
          (alternativePositiveMap.containsKey(a) ? alternativePositiveMap.get(a) : 1D)
              / (alternativeNegativeMap.containsKey(a) ? alternativeNegativeMap.get(a) : 1D));

      alternativeAdditiveMap.put(
          a,
          (alternativePositiveMap.containsKey(a) ? alternativePositiveMap.get(a) : 0D)
              - (alternativeNegativeMap.containsKey(a) ? alternativeNegativeMap.get(a) : 0D));
    }

    log.info("---------- end evaluation ----------");

    return new EvaluationResult(
        decision,
        alternativeMultiplicativeMap,
        alternativeAdditiveMap,
        alternativePositiveMap,
        alternativeNegativeMap);
  }