private void updateLog(
      double[] gama,
      double[] mi,
      double teta,
      double lambda,
      int k,
      double ub,
      double lb,
      ModelLagrange model) {

    String vec_gama = "";
    String vec_mi = "";

    printer.println("k:" + k);

    for (int i = 0; i < data.nLinks; i++) {
      vec_gama = vec_gama + " " + String.format("%5.2f", gama[i]);
    }
    printer.println(String.format("%-15s", "Gama:") + vec_gama);

    for (int i = 0; i < data.nLinks; i++) {
      vec_mi = vec_mi + " " + String.format("%5.2f", mi[i]);
    }
    printer.println(String.format("%-15s", "Mi:") + vec_mi);

    printer.println(String.format("%-15s", "Teta:") + String.format("%15.2f", teta));
    printer.println(String.format("%-15s", "Lambda:") + String.format("%15.2f", lambda));
    printer.println(String.format("%-15s", "Lower Bound:") + String.format("%15.2f", lb));
    printer.println(String.format("%-15s", "Upper Bound:") + String.format("%15.2f", ub));
    printer.println(
        String.format("%-15s", "GAP: ")
            + String.format("%15.2f", Math.abs(ub - lb) / ((1E-10) + lb)));
    printer.println(
        String.format("%-15s", "Time:") + String.format("%15.2f", model.getSolverTime()));
    printer.println("");
  }
  public Solver() {
    super();
    try {
      data = new Data(filename);
      printer = new PrintStream("out.txt");

      // Dimensionando vetores
      mi = new double[data.nLinks];
      mi_new = new double[data.nLinks];
      mi_diff = new double[data.nLinks];
      gama = new double[data.nLinks];

      // Resolvo o modelo com todos os Y=1 para iniciar o loop
      ModelY1 modely1 = new ModelY1(data);
      UB = modely1.getUB();
      modely1.finalizeModel();

      // Resolvo o modelo linear, ou seja, y do tipo numvar
      ModelLinear modellinear = new ModelLinear(data);
      linearObjectiveValue = modellinear.getOV();
      modellinear.finalizeModel();

      printer.println(
          String.format("%-15s", "Linear Objective Value:")
              + String.format("%15.2f", linearObjectiveValue));

      // Lower Bound comeca igual a -infinito
      LB = -Double.MAX_VALUE;

      // Crio meu modelo Lagrange
      ModelLagrange model = new ModelLagrange(data);

      for (int k = 0; k < K; k++) {
        model.buildAndSolveObjectiveFunction(mi);

        // Atualizo o LB
        double lb = model.getLB();
        if (lb > LB) {
          LB = lb;
          // zero contabilizacao de ocorrencia de progresso
          beta = 0;
        }

        // Acho gama
        gama = model.getGama();

        // atualizacao do UB se o gama for viavel
        if (model.isFeasible(gama) && (model.getUB() < UB)) {
          UB = model.getUB();
        }

        // Calculo o Teta
        teta = (lambda * (UB - model.getLB())) / Math.pow(Util.calculaNorma(gama), 2);

        // Calculo o MI(k+1) e o MI(k+1 - k)
        for (int i = 0; i < data.nLinks; i++) {
          mi_new[i] = Math.max(0, mi[i] + (teta * gama[i]));
          mi_diff[i] = mi_new[i] - mi[i];
        }

        if (Util.calculaNorma(mi_diff) < EPSLON) {
          break;
        }

        if (beta == BETA) {
          lambda = (lambda / 2);
          beta = 0;
        } else {
          beta++;
        }

        updateLog(gama, mi, teta, lambda, k, UB, LB, model);

        for (int i = 0; i < data.nLinks; i++) {
          mi[i] = mi_new[i];
        }
      }
    } catch (IOException exc1) {
      System.err.println(exc1);
    } catch (IloException exc2) {
      System.err.println(exc2);
    } catch (OutOfMemoryError exc3) {
      System.err.println(exc3);
    }
  }