Exemplo n.º 1
0
 /** @see "Convex Optimization, p. 610" */
 private DoubleMatrix1D rCent(DoubleMatrix1D fiX, DoubleMatrix1D L, double t) {
   DoubleMatrix1D ret = F1.make(L.size());
   for (int i = 0; i < ret.size(); i++) {
     ret.setQuick(i, -L.getQuick(i) * fiX.getQuick(i) - 1. / t);
   }
   return ret;
 }
Exemplo n.º 2
0
 /**
  * Inequality functions values at X. This is (-x+lb) for all bounded lb and (x-ub) for all bounded
  * ub.
  */
 @Override
 protected DoubleMatrix1D getFi(DoubleMatrix1D X) {
   double[] ret = new double[getMieq()];
   for (int i = 0; i < getDim(); i++) {
     ret[i] = -X.getQuick(i) + getLb().getQuick(i);
     ret[getDim() + i] = X.getQuick(i) - getUb().getQuick(i);
   }
   return F1.make(ret);
 }
Exemplo n.º 3
0
  /** Computes the term Grad[fi].stepX */
  protected DoubleMatrix1D gradFiStepX(DoubleMatrix1D stepX) {

    DoubleMatrix1D ret = F1.make(getMieq());
    for (int i = 0; i < getDim(); i++) {
      ret.setQuick(i, -stepX.getQuick(i));
      ret.setQuick(getDim() + i, stepX.getQuick(i));
    }

    return ret;
  }
Exemplo n.º 4
0
 /**
  * Calculates the second term of the first row of (11.55) "Convex Optimization".
  *
  * @see "Convex Optimization, 11.55"
  */
 protected DoubleMatrix1D gradSum(double t, DoubleMatrix1D fiX) {
   DoubleMatrix1D gradSum = F1.make(getDim());
   for (int i = 0; i < dim; i++) {
     double d = 0;
     d += 1. / (t * fiX.getQuick(i));
     d += -1. / (t * fiX.getQuick(getDim() + i));
     gradSum.setQuick(i, d);
   }
   return gradSum;
 }
Exemplo n.º 5
0
 /** @see "Convex Optimization, p. 610" */
 protected DoubleMatrix1D rDual(DoubleMatrix1D gradF0X, DoubleMatrix1D L, DoubleMatrix1D V) {
   // m1 = GradFiX[T].L + gradF0X
   DoubleMatrix1D m1 = F1.make(getDim());
   for (int i = 0; i < getDim(); i++) {
     double m = 0;
     m += -L.getQuick(i);
     m += L.getQuick(getDim() + i);
     m1.setQuick(i, m + gradF0X.get(i));
   }
   if (getMeq() == 0) {
     return m1;
   }
   return ColtUtils.zMultTranspose(getA(), V, m1, 1.);
 }
Exemplo n.º 6
0
  /**
   * Return the H matrix (that is diagonal). This is the third addendum of (11.56) of "Convex
   * Optimization".
   *
   * @see "Convex Optimization, 11.56"
   */
  protected DoubleMatrix2D GradLSum(DoubleMatrix1D L, DoubleMatrix1D fiX) {
    // DoubleMatrix2D GradLSum = F2.make(1, getDim());
    SparseDoubleMatrix2D GradLSum =
        new SparseDoubleMatrix2D(getDim(), getDim(), getDim(), 0.001, 0.01);
    for (int i = 0; i < getDim(); i++) {
      double d = 0;
      d -= L.getQuick(i) / fiX.getQuick(i);
      d -= L.getQuick(getDim() + i) / fiX.getQuick(getDim() + i);
      // GradLSum.setQuick(0, i, d);
      GradLSum.setQuick(i, i, d);
    }

    return GradLSum;
  }
Exemplo n.º 7
0
  private static double[] solution(DoubleMatrix2D X, DoubleMatrix2D Y, int k) {
    // Solve X * Beta = Y for Beta
    // Only the first column of Y is used
    // k is number of beta coefficients

    QRDecomposition qr = new QRDecomposition(X);

    if (qr.hasFullRank()) {
      DoubleMatrix2D B = qr.solve(Y);
      return B.viewColumn(0).toArray();

    } else {
      DoubleMatrix1D Y0 = Y.viewColumn(0); // first column of Y
      SingularValueDecomposition svd = new SingularValueDecomposition(X);
      DoubleMatrix2D S = svd.getS();
      DoubleMatrix2D V = svd.getV();
      DoubleMatrix2D U = svd.getU();
      Algebra alg = new Algebra();
      DoubleMatrix2D Ut = alg.transpose(U);
      DoubleMatrix1D g = alg.mult(Ut, Y0); // Ut*Y0

      for (int j = 0; j < k; j++) {
        // solve S*p = g for p;  S is a diagonal matrix
        double x = S.getQuick(j, j);
        if (x > 0.) {
          x = g.getQuick(j) / x; // p[j] = g[j]/S[j]
          g.setQuick(j, x); // overwrite g by p
        } else g.setQuick(j, 0.);
      }
      DoubleMatrix1D beta = alg.mult(V, g); // V*p
      return beta.toArray();
    }
  }
Exemplo n.º 8
0
  static boolean computeLogMi(
      FeatureGenerator featureGen,
      double lambda[],
      DoubleMatrix2D Mi_YY,
      DoubleMatrix1D Ri_Y,
      boolean takeExp,
      boolean reuseM,
      boolean initMDone) {

    if (reuseM && initMDone) {
      Mi_YY = null;
    } else initMDone = false;
    if (Mi_YY != null) Mi_YY.assign(0);
    Ri_Y.assign(0);
    while (featureGen.hasNext()) {
      Feature feature = featureGen.next();
      int f = feature.index();
      int yp = feature.y();
      int yprev = feature.yprev();
      float val = feature.value();
      //	    System.out.println(feature.toString());

      if (yprev < 0) {
        // this is a single state feature.
        double oldVal = Ri_Y.getQuick(yp);
        Ri_Y.setQuick(yp, oldVal + lambda[f] * val);
      } else if (Mi_YY != null) {
        Mi_YY.setQuick(yprev, yp, Mi_YY.getQuick(yprev, yp) + lambda[f] * val);
        initMDone = true;
      }
    }
    if (takeExp) {
      for (int r = Ri_Y.size() - 1; r >= 0; r--) {
        Ri_Y.setQuick(r, expE(Ri_Y.getQuick(r)));
        if (Mi_YY != null)
          for (int c = Mi_YY.columns() - 1; c >= 0; c--) {
            Mi_YY.setQuick(r, c, expE(Mi_YY.getQuick(r, c)));
          }
      }
    }
    return initMDone;
  }
Exemplo n.º 9
0
    public double apply(int first, int second, double third) {

      if (first == second) {
        return third;
      }

      //            System.out.println("checking = " + min_val + " versus " +
      // (third/count_matrix.getQuick(first,second)));
      double d_q =
          2
              * (third / m_total_distances
                  - (a_matrix.getQuick(first) * a_matrix.getQuick(second))
                      / (m_total_distances * m_total_distances));
      if (d_q > max_q) {
        min_m = first;
        min_n = second;
        max_q = d_q;
      }

      return third;
    }
Exemplo n.º 10
0
  /**
   * Feature-specific contribution to the prediction of the value of an instance.
   *
   * @param x instance
   * @param i index of the feature of interest
   * @param xi value of the feature of interest
   * @return value of the contribution of the feature to the prediction
   */
  public double prediction(I x, int i, double xi) {
    double wi = w.getQuick(i);
    DoubleMatrix1D mi = m.viewRow(i);

    double pred = 0.0;

    pred += xi * wi;

    pred +=
        x.operate(
            (j, xj) -> {
              DoubleMatrix1D mj = m.viewRow(j);

              return xi * xj * mi.zDotProduct(mj);
            },
            (v1, v2) -> v1 + v2);

    return pred;
  }
Exemplo n.º 11
0
  /**
   * Predict the value of an instance.
   *
   * @param x instance
   * @return value of prediction
   */
  public double prediction(I x) {
    double pred = b;

    DoubleMatrix1D xm = new DenseDoubleMatrix1D(m.columns());
    pred +=
        x.operate(
            (i, xi) -> {
              double wi = w.getQuick(i);
              DoubleMatrix1D mi = m.viewRow(i);

              xm.assign(mi, (r, s) -> r + xi * s);

              return xi * wi - 0.5 * xi * xi * mi.zDotProduct(mi);
            },
            (v1, v2) -> v1 + v2);

    pred += 0.5 * xm.zDotProduct(xm);

    return pred;
  }
Exemplo n.º 12
0
  public void newmanCluster(ItemRegistry registry) {

    DoubleMatrix2D distance_matrix =
        DoubleFactory2D.sparse.make(
            registry.getGraph().getNodeCount(), registry.getGraph().getNodeCount());
    DoubleMatrix1D a_matrix = DoubleFactory1D.dense.make(registry.getGraph().getNodeCount(), 0.);

    Map<String, Cluster> cluster_map = new HashMap<String, Cluster>();

    // construct the leaf node distance matrix

    Iterator edge_iter = registry.getGraph().getEdges();
    m_total_distances = 0.;
    while (edge_iter.hasNext()) {
      Edge edge = (Edge) edge_iter.next();
      Cluster clust1 = (Cluster) edge.getFirstNode();
      Cluster clust2 = (Cluster) edge.getSecondNode();
      if (cluster_map.get(clust1.getAttribute("id")) == null) {
        cluster_map.put(clust1.getAttribute("id"), clust1);
      }
      if (cluster_map.get(clust2.getAttribute("id")) == null) {
        cluster_map.put(clust2.getAttribute("id"), clust2);
      }
      int n = Integer.parseInt(clust1.getAttribute("id"));
      int m = Integer.parseInt(clust2.getAttribute("id"));
      // make reciprocal (big values = good in newman, but not in our case)
      double dist = 1 / clust1.getCenter().distance(clust2.getCenter());
      distance_matrix.set(Math.max(n, m), Math.min(n, m), dist);
      //            m_total_distances += dist;
      //            a_matrix.setQuick( n, a_matrix.getQuick( n ) + dist );
      //            a_matrix.setQuick( m, a_matrix.getQuick( m ) + dist );
      m_total_distances += 1;
      a_matrix.setQuick(n, a_matrix.getQuick(n) + 1);
      a_matrix.setQuick(m, a_matrix.getQuick(m) + 1);
    }

    //        System.out.println(distance_matrix);
    //        System.out.println(count_matrix);
    // agglomerate nodes until we reach a root node (or nodes)
    boolean done = false;
    int trash = 0;
    QFinder qfinder = new QFinder();
    qfinder.a_matrix = a_matrix;
    QMerger qmerger = new QMerger();
    while (!done) {
      // find the minimum cluster distance

      qfinder.reset();

      distance_matrix.forEachNonZero(qfinder);

      //            done = true;

      //            System.out.println(distance_matrix);
      //            System.out.println(count_matrix);
      if (qfinder.getVal() == -Double.MAX_VALUE) {
        break;
      }

      // add a parent cluster to the graph

      Cluster clust1 = cluster_map.get("" + qfinder.getM());
      Cluster clust2 = cluster_map.get("" + qfinder.getN());
      while (clust1.getParent() != null) {
        clust1 = clust1.getParent();
      }
      while (clust2.getParent() != null) {
        clust2 = clust2.getParent();
      }
      trash++;
      double dist = Math.max(clust1.getHeight(), clust2.getHeight());
      Cluster new_cluster =
          new DefaultCluster(
              (float) (clust1.getCenter().getX() + clust2.getCenter().getX()) / 2.f,
              (float) (clust1.getCenter().getY() + clust2.getCenter().getY()) / 2.f,
              (float)
                  Math.sqrt(
                      clust1.getRadius() * clust1.getRadius()
                          + clust2.getRadius() * clust2.getRadius()),
              clust1,
              clust2,
              dist);
      registry.getGraph().addNode(new_cluster);

      // merge the clusters distances / counts

      int M = Math.max(qfinder.getM(), qfinder.getN());
      int N = Math.min(qfinder.getM(), qfinder.getN());
      a_matrix.set(N, a_matrix.getQuick(M) + a_matrix.getQuick(N));
      a_matrix.set(M, 0);
      //            System.out.println("M = "+M+" N = "+N + " VAL=" + minfinder.getVal() );
      qmerger.setM(M);
      qmerger.setN(N);
      qmerger.setParent(distance_matrix);
      qmerger.setMode(true);
      //            System.out.println(distance_matrix.viewPart( 0, M, distance_matrix.rows(), 1));
      distance_matrix.viewPart(0, M, distance_matrix.rows(), 1).forEachNonZero(qmerger);
      qmerger.setMode(false);
      //            System.out.println(distance_matrix.viewPart( M, 0, 1, M ));
      distance_matrix.viewPart(M, 0, 1, M).forEachNonZero(qmerger);

      //            System.out.println(distance_matrix);
      //            System.out.println(count_matrix);
      // free any superfluous memory randomly ~ (1/20) times

      if (Math.random() > 0.95) {
        distance_matrix.trimToSize();
      }
    }
  }
Exemplo n.º 13
0
  /**
   * Solves a presolved standard form LP problem in the form of min(c) s.t. A.x = b lb <= x <= ub
   */
  protected int optimizePresolvedStandardLP() throws Exception {
    log.info("optimizePresolvedStandardLP");

    long tStart = System.currentTimeMillis();

    LPOptimizationRequest lpRequest = getLPOptimizationRequest();
    if (log.isDebugEnabled() && lpRequest.isDumpProblem()) {
      log.debug("LP problem: " + lpRequest.toString());
    }

    if (this.dim <= -1) {
      if (getLb().size() != getUb().size()) {
        log.error("Lower and upper bounds must have the same dimension");
        throw new IllegalArgumentException("Lower and upper bounds must have the same dimension");
      }
      this.dim = getLb().size();
      double minDeltaBoundsValue = Double.MAX_VALUE;
      int minDeltaBoundsIndex = -1;
      for (int i = 0; i < getDim(); i++) {
        double deltai = getUb().getQuick(i) - getLb().getQuick(i);
        if (deltai < minDeltaBoundsValue) {
          minDeltaBoundsValue = deltai;
          minDeltaBoundsIndex = i;
        }
      }
      log.info("min delta bounds index: " + minDeltaBoundsIndex);
      log.info("min delta bounds value: " + minDeltaBoundsValue);
    }
    // this.boundedLb = new boolean[getDim()];
    // this.boundedUb = new boolean[getDim()];
    //		for(int i=0; i<getDim(); i++){
    //			if(!isLbUnbounded(getLb().getQuick(i))){
    //				boundedLb[i] = true;
    //				nOfBoundedLb++;
    //			}
    //			if(!isUbUnbounded(getUb().getQuick(i))){
    //				boundedUb[i] = true;
    //				nOfBoundedUb++;
    //			}
    //		}
    this.meq = (this.meq > -1) ? this.meq : ((getA() != null) ? getA().rows() : 0);
    // this.mieq = (this.mieq>-1)? this.mieq : (nOfBoundedLb+nOfBoundedUb);
    this.mieq = (this.mieq > -1) ? this.mieq : (2 * getDim());

    if (log.isDebugEnabled()) {
      log.debug("dim : " + getDim());
      log.debug("meq : " + getMeq());
      log.debug("mieq: " + getMieq());
    }

    LPOptimizationResponse lpResponse = new LPOptimizationResponse();

    DoubleMatrix1D X0 = getInitialPoint();
    if (X0 == null) {
      DoubleMatrix1D X0NF = getNotFeasibleInitialPoint();
      if (X0NF != null) {
        double rPriX0NFNorm = Math.sqrt(ALG.norm2(rPri(X0NF)));
        DoubleMatrix1D fiX0NF = getFi(X0NF);
        int maxIndex = Utils.getMaxIndex(fiX0NF);
        double maxValue = fiX0NF.get(maxIndex);
        if (log.isDebugEnabled()) {
          log.debug("rPriX0NFNorm :  " + rPriX0NFNorm);
          log.debug("X0NF         :  " + ArrayUtils.toString(X0NF.toArray()));
          log.debug("fiX0NF       :  " + ArrayUtils.toString(fiX0NF.toArray()));
        }
        if (maxValue < 0 && rPriX0NFNorm <= getToleranceFeas()) {
          // the provided not-feasible starting point is already feasible
          log.debug("the provided initial point is already feasible");
          X0 = X0NF;
        }
      }
      if (X0 == null) {
        BasicPhaseILPPDM bf1 = new BasicPhaseILPPDM(this);
        X0 = bf1.findFeasibleInitialPoint();
      }
    }

    // check X0 feasibility
    DoubleMatrix1D fiX0 = getFi(X0);
    int maxIndex = Utils.getMaxIndex(fiX0);
    double maxValue = fiX0.get(maxIndex);
    double rPriX0Norm = Math.sqrt(ALG.norm2(rPri(X0)));
    if (maxValue >= 0. || rPriX0Norm > getToleranceFeas()) { // must be fi STRICTLY < 0
      log.warn("rPriX0Norm  : " + rPriX0Norm);
      log.warn("ineqX0      : " + ArrayUtils.toString(fiX0.toArray()));
      log.warn("max ineq index: " + maxIndex);
      log.warn("max ineq value: " + maxValue);
      // the point must be INTERNAL, fi are used as denominators
      throw new Exception("initial point must be strictly feasible");
    }

    DoubleMatrix1D V0 = F1.make(getMeq());
    if (getYlb() != null && getYub() != null) {
      // NB: the Lagrangian multipliers for eq. constraints used in this interior point method (v)
      // are the opposite of the Lagrangian  multipliers for eq. constraints used in the presolver
      // (y)
      // and so Ylb<=y<=Yub becomes -Yub<=v<=-Ylb
      for (int i = 0; i < getMeq(); i++) {
        double v0i = 0;
        if (!isLbUnbounded(getYlb().getQuick(i))) {
          if (!isUbUnbounded(getYub().getQuick(i))) {
            v0i = -(getYub().getQuick(i) + getYlb().getQuick(i)) / 2;
          } else {
            v0i = -getYlb().getQuick(i);
          }
        } else {
          if (!isUbUnbounded(getYub().getQuick(i))) {
            v0i = -getYub().getQuick(i);
          } else {
            v0i = 0;
          }
        }
        V0.setQuick(i, v0i);
      }
    }

    DoubleMatrix1D L0 = getInitialLagrangian();
    if (L0 != null) {
      for (int j = 0; j < L0.size(); j++) {
        // must be >0
        if (L0.get(j) <= 0) {
          throw new IllegalArgumentException("initial lagrangian must be strictly > 0");
        }
      }
    } else {
      L0 = F1.make(getMieq(), 1.); // must be >0 strictly
      if (getZlb() != null && getZub() != null) {
        // Zlb<= L <=Zub, meaning that:
        // zlb[i] and zub[i] are the bounds on the Lagrangian of the constraint associated with
        // lb[i]<x[i]<ub[i]
        // note that zlb.size = zub.size = lb.size = ub.size (and = n of variables of the problem (=
        // getDim())
        // and that L.size = nOfBoundedLb + nOfBoundedUb (and in general < 2*getDim())
        int cntLB = 0;
        int cntUB = 0;
        for (int i = 0; i < getDim(); i++) {
          double zlbi =
              (isLbUnbounded(getZlb().getQuick(i))) ? 0 : getZlb().getQuick(i); // L must be > 0
          double zubi = (isUbUnbounded(getZub().getQuick(i))) ? 1 : getZub().getQuick(i);
          L0.setQuick(cntLB, (zubi - zlbi) / 2);
          cntLB++;
          L0.setQuick(getDim() + cntUB, (zubi - zlbi) / 2);
          cntUB++;
        }
      } else {
        // inequalities comes from the pairs lower bounds-upper bounds
        // in the calculation of the H matrix fro the KKT system, each pairs gives terms of the
        // form:
        // t = tl + tu
        // tl = -L[i] / fi[i] for the lower bound
        // tu =  L[dim+i] / fi[dim+i] for the upper bound
        // we want t = 1, and hence
        // L[i] > -cc * fi[i]
        // L[dim+i] = (1 + L[i] / fi[i]) * fi[dim+i]
        //				double cc = 10;
        //				int nOfLB = getMieq()/2;
        //				for (int i = 0; i < nOfLB; i++) {
        //					L0.setQuick(i, -cc * fiX0.getQuick(i));
        //					L0.setQuick(nOfLB + i, (1 - 10)	* fiX0.getQuick(nOfLB + i));
        //					double sum = -L0.getQuick(i)/fiX0.getQuick(i)+L0.getQuick(nOfLB +
        // i)/fiX0.getQuick(nOfLB + i);
        //					log.debug("sum["+i+"]:  " + sum);
        //				}
      }
    }
    if (log.isDebugEnabled()) {
      log.debug("X0:  " + ArrayUtils.toString(X0.toArray()));
      log.debug("V0:  " + ArrayUtils.toString(V0.toArray()));
      log.debug("L0:  " + ArrayUtils.toString(L0.toArray()));
    }
    if (log.isInfoEnabled()) {
      log.info("toleranceFeas:  " + getToleranceFeas());
      log.info("tolerance    :  " + getTolerance());
    }

    DoubleMatrix1D X = X0;
    DoubleMatrix1D V = V0;
    DoubleMatrix1D L = L0;
    double previousF0X = Double.NaN;
    double previousRPriXNorm = Double.NaN;
    double previousRDualXLVNorm = Double.NaN;
    double previousSurrDG = Double.NaN;
    double t;
    int iteration = 0;
    // List<DoubleMatrix1D> XList = new ArrayList<DoubleMatrix1D>();
    // List<double[]> SList = new ArrayList<double[]>();
    while (true) {

      iteration++;
      // iteration limit condition
      if (iteration == getMaxIteration() + 1) {
        lpResponse.setReturnCode(OptimizationResponse.FAILED);
        log.error("Max iterations limit reached");
        throw new Exception("Max iterations limit reached");
      }

      // XList.add(XList.size(), X);
      double F0X = getF0(X);
      if (log.isInfoEnabled()) {
        log.info("iteration: " + iteration);
        log.info("f0(X)=" + F0X);
      }
      if (log.isDebugEnabled()) {
        log.debug("X=" + ArrayUtils.toString(X.toArray()));
        log.debug("L=" + ArrayUtils.toString(L.toArray()));
        log.debug("V=" + ArrayUtils.toString(V.toArray()));
      }

      // determine functions evaluations
      DoubleMatrix1D gradF0X = getGradF0(X);
      DoubleMatrix1D fiX = getFi(X);
      log.debug("fiX=" + ArrayUtils.toString(fiX.toArray()));
      // DoubleMatrix2D GradFiX = getGradFi(X);
      // DoubleMatrix2D GradFiXOLD = getGradFiOLD(X);

      // determine t
      double surrDG = getSurrogateDualityGap(fiX, L);
      t = getMu() * getMieq() / surrDG;
      log.debug("t:  " + t);

      // determine residuals
      DoubleMatrix1D rPriX = rPri(X);
      DoubleMatrix1D rCentXLt = rCent(fiX, L, t);
      DoubleMatrix1D rDualXLV = rDual(gradF0X, L, V);
      // DoubleMatrix1D rDualXLVOLD = rDualOLD(GradFiXOLD, gradF0X, L, V);
      // log.debug("delta: " + ALG.normInfinity(rDualXLVOLD.assign(rDualXLV, Functions.minus)));
      double rPriXNorm = Math.sqrt(ALG.norm2(rPriX));
      double rCentXLtNorm = Math.sqrt(ALG.norm2(rCentXLt));
      double rDualXLVNorm = Math.sqrt(ALG.norm2(rDualXLV));
      double normRXLVt =
          Math.sqrt(Math.pow(rPriXNorm, 2) + Math.pow(rCentXLtNorm, 2) + Math.pow(rDualXLVNorm, 2));
      // @TODO: set log.debug not log.info
      log.info("rPri  norm: " + rPriXNorm);
      log.info("rCent norm: " + rCentXLtNorm);
      log.info("rDual norm: " + rDualXLVNorm);
      log.info("surrDG    : " + surrDG);

      // custom exit condition
      if (checkCustomExitConditions(X)) {
        lpResponse.setReturnCode(OptimizationResponse.SUCCESS);
        break;
      }

      // exit condition
      if (rPriXNorm <= getToleranceFeas()
          && rDualXLVNorm <= getToleranceFeas()
          && surrDG <= getTolerance()) {
        lpResponse.setReturnCode(OptimizationResponse.SUCCESS);
        break;
      }

      // progress conditions
      if (isCheckProgressConditions()) {
        if (!Double.isNaN(previousRPriXNorm)
            && !Double.isNaN(previousRDualXLVNorm)
            && !Double.isNaN(previousSurrDG)) {
          if ((previousRPriXNorm <= rPriXNorm && rPriXNorm >= getToleranceFeas())
              || (previousRDualXLVNorm <= rDualXLVNorm && rDualXLVNorm >= getToleranceFeas())) {
            log.error("No progress achieved, exit iterations loop without desired accuracy");
            lpResponse.setReturnCode(OptimizationResponse.FAILED);
            throw new Exception(
                "No progress achieved, exit iterations loop without desired accuracy");
          }
        }
        previousRPriXNorm = rPriXNorm;
        previousRDualXLVNorm = rDualXLVNorm;
        previousSurrDG = surrDG;
      }

      // compute primal-dual search direction
      // a) prepare 11.55 system
      DoubleMatrix2D Hpd = GradLSum(L, fiX);
      // DoubleMatrix2D HpdOLD = GradLSumOLD(GradFiXOLD, L, fiX);
      // log.debug("delta: " + ALG.normInfinity(HpdOLD.assign(Hpd, Functions.minus)));
      DoubleMatrix1D gradSum = gradSum(t, fiX);
      DoubleMatrix1D g = null;
      // if(getAT()==null){
      if (getA() == null) {
        g = ColtUtils.add(gradF0X, gradSum);
      } else {
        // g = ColtUtils.add(ColtUtils.add(gradF0X, gradSum), ALG.mult(getAT(), V));
        g =
            ColtUtils.add(
                ColtUtils.add(gradF0X, gradSum),
                ColtUtils.zMultTranspose(getA(), V, F1.make(getDim()), 0));
      }

      // b) solving 11.55 system
      if (this.kktSolver == null) {
        this.kktSolver = new UpperDiagonalHKKTSolver(getDim(), lpRequest.isRescalingDisabled());
        // this.kktSolver = new DiagonalHKKTSolver(getDim(), lpRequest.isRescalingDisabled());
      }
      if (isCheckKKTSolutionAccuracy()) {
        kktSolver.setCheckKKTSolutionAccuracy(true);
        kktSolver.setToleranceKKT(getToleranceKKT());
      }
      kktSolver.setHMatrix(Hpd);
      kktSolver.setGVector(g);
      if (getA() != null) {
        kktSolver.setAMatrix(getA());
        // kktSolver.setATMatrix(getAT());
        kktSolver.setHVector(rPriX);
        //				if(rPriXNorm > getToleranceFeas()){
        //					kktSolver.setHVector(rPriX);
        //				}
      }
      DoubleMatrix1D[] sol = kktSolver.solve();
      DoubleMatrix1D stepX = sol[0];
      // double[] signa = new double[stepX.size()];
      //			for(int p=0; p<stepX.size(); p++){
      //				signa[p] =	Math.signum(stepX.getQuick(p));
      //			}
      // SList.add(SList.size(), signa);
      DoubleMatrix1D stepV = (sol[1] != null) ? sol[1] : F1.make(0);
      if (log.isDebugEnabled()) {
        log.debug("stepX: " + ArrayUtils.toString(stepX.toArray()));
        log.debug("stepV: " + ArrayUtils.toString(stepV.toArray()));
      }

      // c) solving for L
      DoubleMatrix1D stepL = F1.make(getMieq());
      DoubleMatrix1D gradFiStepX = gradFiStepX(stepX);
      for (int i = 0; i < getMieq(); i++) {
        stepL.setQuick(
            i, (-L.getQuick(i) * gradFiStepX.getQuick(i) + rCentXLt.getQuick(i)) / fiX.getQuick(i));
      }
      if (log.isDebugEnabled()) {
        log.debug("stepL: " + ArrayUtils.toString(stepL.toArray()));
      }

      // line search and update
      // a) sMax computation
      double sMax = Double.MAX_VALUE;
      for (int j = 0; j < getMieq(); j++) {
        if (stepL.get(j) < 0) {
          sMax = Math.min(-L.get(j) / stepL.get(j), sMax);
        }
      }
      sMax = Math.min(1, sMax);
      double s = 0.99 * sMax;
      // b) backtracking with f
      DoubleMatrix1D X1 = F1.make(X.size());
      DoubleMatrix1D L1 = F1.make(L.size());
      DoubleMatrix1D V1 = F1.make(V.size());
      DoubleMatrix1D fiX1 = null;
      DoubleMatrix1D gradF0X1 = null;
      // DoubleMatrix2D GradFiX1 = null;
      // DoubleMatrix2D GradFiX1 = null;
      DoubleMatrix1D rPriX1 = null;
      DoubleMatrix1D rCentX1L1t = null;
      DoubleMatrix1D rDualX1L1V1 = null;
      int cnt = 0;
      boolean areAllNegative = true;
      while (cnt < 500) {
        cnt++;
        // X1 = X + s*stepX
        X1 = stepX.copy().assign(Mult.mult(s)).assign(X, Functions.plus);
        DoubleMatrix1D ineqValueX1 = getFi(X1);
        areAllNegative = true;
        for (int j = 0; areAllNegative && j < getMieq(); j++) {
          areAllNegative = (Double.compare(ineqValueX1.get(j), 0.) < 0);
        }
        if (areAllNegative) {
          break;
        }
        s = getBeta() * s;
      }

      if (!areAllNegative) {
        // exited from the feasible region
        throw new Exception("Optimization failed: impossible to remain within the faesible region");
      }

      log.debug("s: " + s);
      // c) backtracking with norm
      double previousNormRX1L1V1t = Double.NaN;
      cnt = 0;
      while (cnt < 500) {
        cnt++;
        X1 = ColtUtils.add(X, stepX, s);
        L1 = ColtUtils.add(L, stepL, s);
        V1 = ColtUtils.add(V, stepV, s);

        if (isInDomainF0(X1)) {
          fiX1 = getFi(X1);
          gradF0X1 = getGradF0(X1);
          // GradFiX1 = getGradFi(X1);

          rPriX1 = rPri(X1);
          rCentX1L1t = rCent(fiX1, L1, t);
          rDualX1L1V1 = rDual(gradF0X1, L1, V1);
          double normRX1L1V1t =
              Math.sqrt(ALG.norm2(rPriX1) + ALG.norm2(rCentX1L1t) + ALG.norm2(rDualX1L1V1));
          // log.debug("normRX1L1V1t: "+normRX1L1V1t);
          if (normRX1L1V1t <= (1 - getAlpha() * s) * normRXLVt) {
            break;
          }

          if (!Double.isNaN(previousNormRX1L1V1t)) {
            if (previousNormRX1L1V1t <= normRX1L1V1t) {
              log.warn("No progress achieved in backtracking with norm");
              break;
            }
          }
          previousNormRX1L1V1t = normRX1L1V1t;
        }

        s = getBeta() * s;
        // log.debug("s: " + s);
      }

      // update
      X = X1;
      V = V1;
      L = L1;
    }

    //		if(lpRequest.isCheckOptimalDualityConditions()){
    //			//check duality conditions:
    //			if(!checkDualityConditions(X, L, V)){
    //				log.error("duality conditions not satisfied");
    //				lpResponse.setReturnCode(OptimizationResponse.FAILED);
    //				throw new Exception("duality conditions not satisfied");
    //			}
    //		}

    if (lpRequest.isCheckOptimalLagrangianBounds()) {
      // check equality constraints Lagrangian bounds
      //			if(!checkEqConstraintsLagrangianBounds(V)){
      //				log.error("equality constraints Lagrangian multipliers bounds not satisfied");
      //				lpResponse.setReturnCode(OptimizationResponse.FAILED);
      //				throw new Exception("equality constraints Lagrangian multipliers bounds not satisfied");
      //			}

      // check inequality constraints Lagrangian bounds
      //			if(!checkIneqConstraintsLagrangianBounds(X, L)){
      //				log.error("inequality constraints Lagrangian multipliers bounds not satisfied");
      //				lpResponse.setReturnCode(OptimizationResponse.FAILED);
      //				throw new Exception("inequality constraints Lagrangian multipliers bounds not
      // satisfied");
      //			}
    }

    long tStop = System.currentTimeMillis();
    log.debug("time: " + (tStop - tStart));
    log.debug("sol : " + ArrayUtils.toString(X.toArray()));
    log.debug("ret code: " + lpResponse.getReturnCode());
    //		log.debug("XList : " + ArrayUtils.toString(XList));
    //		for(int s=0; s<SList.size(); s++){
    //			log.debug("SList : " + ArrayUtils.toString(SList.get(s)));
    //		}
    lpResponse.setSolution(X.toArray());
    setLPOptimizationResponse(lpResponse);
    return lpResponse.getReturnCode();
  }