Пример #1
0
void ClpPdco::matPrecon(double delta, CoinDenseVector<double> &x, CoinDenseVector<double> &y)
{
     double *x_elts = x.getElements();
     double *y_elts = y.getElements();
     matPrecon(delta, x_elts, y_elts);
     return;
}
Пример #2
0
inline double pdxxxmerit(int nlow, int nupp, int *low, int *upp, CoinDenseVector <double> &r1,
                         CoinDenseVector <double> &r2, CoinDenseVector <double> &rL,
                         CoinDenseVector <double> &rU, CoinDenseVector <double> &cL,
                         CoinDenseVector <double> &cU )
{

// Evaluate the merit function for Newton's method.
// It is the 2-norm of the three sets of residuals.
     double sum1, sum2;
     CoinDenseVector <double> f(6);
     f[0] = r1.twoNorm();
     f[1] = r2.twoNorm();
     sum1 = sum2 = 0.0;
     for (int k = 0; k < nlow; k++) {
          sum1 += rL[low[k]] * rL[low[k]];
          sum2 += cL[low[k]] * cL[low[k]];
     }
     f[2] = sqrt(sum1);
     f[4] = sqrt(sum2);
     sum1 = sum2 = 0.0;
     for (int k = 0; k < nupp; k++) {
          sum1 += rL[upp[k]] * rL[upp[k]];
          sum2 += cL[upp[k]] * cL[upp[k]];
     }
     f[3] = sqrt(sum1);
     f[5] = sqrt(sum2);

     return f.twoNorm();
}
Пример #3
0
void ClpPdco::matVecMult( int mode, CoinDenseVector<double> &x, CoinDenseVector<double> &y)
{
     double *x_elts = x.getElements();
     double *y_elts = y.getElements();
     matVecMult( mode, x_elts, y_elts);
     return;
}
Пример #4
0
void ClpLsqr::matVecMult(int mode, CoinDenseVector< double > *x, CoinDenseVector< double > *y)
{
  int n = model_->numberColumns();
  int m = model_->numberRows();
  CoinDenseVector< double > *temp = new CoinDenseVector< double >(n, 0.0);
  double *t_elts = temp->getElements();
  double *x_elts = x->getElements();
  double *y_elts = y->getElements();
  ClpPdco *pdcoModel = (ClpPdco *)model_;
  if (mode == 1) {
    pdcoModel->matVecMult(2, temp, y);
    for (int k = 0; k < n; k++)
      x_elts[k] += (diag1_[k] * t_elts[k]);
    for (int k = 0; k < m; k++)
      x_elts[n + k] += (diag2_ * y_elts[k]);
  } else {
    for (int k = 0; k < n; k++)
      t_elts[k] = diag1_[k] * y_elts[k];
    pdcoModel->matVecMult(1, x, temp);
    for (int k = 0; k < m; k++)
      x_elts[k] += diag2_ * y_elts[n + k];
  }
  delete temp;
  return;
}
Пример #5
0
template <typename T> void
CoinDenseVector<T>::append(const CoinDenseVector<T> & caboose)
{
   const int s = nElements_;
   const int cs = caboose.getNumElements();
   int newsize = s + cs;
   resize(newsize);
   const T * celem = caboose.getElements();
   CoinDisjointCopyN(celem, cs, elements_ + s);
}
Пример #6
0
inline double  pdxxxstep(int nset, int *set, CoinDenseVector <double> &x, CoinDenseVector <double> &dx )
{

// Assumes x > 0.
// Finds the maximum step such that x + step*dx >= 0.

     double step     = 1e+20;

     int n = x.size();
     double *x_elts = x.getElements();
     double *dx_elts = dx.getElements();
     for (int k = 0; k < n; k++)
          if (dx_elts[k] < 0)
               if ((x_elts[k] / (-dx_elts[k])) < step)
                    step = x_elts[k] / (-dx_elts[k]);
     return step;
}
Пример #7
0
inline void pdxxxresid1(ClpPdco *model, const int nlow, const int nupp, const int nfix,
                        int *low, int *upp, int *fix,
                        CoinDenseVector <double> &b, double *bl, double *bu, double d1, double d2,
                        CoinDenseVector <double> &grad, CoinDenseVector <double> &rL,
                        CoinDenseVector <double> &rU, CoinDenseVector <double> &x,
                        CoinDenseVector <double> &x1, CoinDenseVector <double> &x2,
                        CoinDenseVector <double> &y,  CoinDenseVector <double> &z1,
                        CoinDenseVector <double> &z2, CoinDenseVector <double> &r1,
                        CoinDenseVector <double> &r2, double *Pinf, double *Dinf)
{

// Form residuals for the primal and dual equations.
// rL, rU are output, but we input them as full vectors
// initialized (permanently) with any relevant zeros.

// Get some element pointers for efficiency
     double *x_elts  = x.getElements();
     double *r2_elts = r2.getElements();

     for (int k = 0; k < nfix; k++)
          x_elts[fix[k]]  = 0;

     r1.clear();
     r2.clear();
     model->matVecMult( 1, r1, x );
     model->matVecMult( 2, r2, y );
     for (int k = 0; k < nfix; k++)
          r2_elts[fix[k]]  = 0;


     r1      = b    - r1 - d2 * d2 * y;
     r2      = grad - r2 - z1;              // grad includes d1*d1*x
     if (nupp > 0)
          r2    = r2 + z2;

     for (int k = 0; k < nlow; k++)
          rL[low[k]] = bl[low[k]] - x[low[k]] + x1[low[k]];
     for (int k = 0; k < nupp; k++)
          rU[upp[k]] = - bu[upp[k]] + x[upp[k]] + x2[upp[k]];

     double normL = 0.0;
     double normU = 0.0;
     for (int k = 0; k < nlow; k++)
          if (rL[low[k]] > normL) normL = rL[low[k]];
     for (int k = 0; k < nupp; k++)
          if (rU[upp[k]] > normU) normU = rU[upp[k]];

     *Pinf    = CoinMax(normL, normU);
     *Pinf    = CoinMax( r1.infNorm() , *Pinf );
     *Dinf    = r2.infNorm();
     *Pinf    = CoinMax( *Pinf, 1e-99 );
     *Dinf    = CoinMax( *Dinf, 1e-99 );
}
Пример #8
0
inline void pdxxxresid2(double mu, int nlow, int nupp, int *low, int *upp,
                        CoinDenseVector <double> &cL, CoinDenseVector <double> &cU,
                        CoinDenseVector <double> &x1, CoinDenseVector <double> &x2,
                        CoinDenseVector <double> &z1, CoinDenseVector <double> &z2,
                        double *center, double *Cinf, double *Cinf0)
{

// Form residuals for the complementarity equations.
// cL, cU are output, but we input them as full vectors
// initialized (permanently) with any relevant zeros.
// Cinf  is the complementarity residual for X1 z1 = mu e, etc.
// Cinf0 is the same for mu=0 (i.e., for the original problem).

     double maxXz = -1e20;
     double minXz = 1e20;

     double *x1_elts = x1.getElements();
     double *z1_elts = z1.getElements();
     double *cL_elts = cL.getElements();
     for (int k = 0; k < nlow; k++) {
          double x1z1    = x1_elts[low[k]] * z1_elts[low[k]];
          cL_elts[low[k]] = mu - x1z1;
          if (x1z1 > maxXz) maxXz = x1z1;
          if (x1z1 < minXz) minXz = x1z1;
     }

     double *x2_elts = x2.getElements();
     double *z2_elts = z2.getElements();
     double *cU_elts = cU.getElements();
     for (int k = 0; k < nupp; k++) {
          double x2z2    = x2_elts[upp[k]] * z2_elts[upp[k]];
          cU_elts[upp[k]] = mu - x2z2;
          if (x2z2 > maxXz) maxXz = x2z2;
          if (x2z2 < minXz) minXz = x2z2;
     }

     maxXz   = CoinMax( maxXz, 1e-99 );
     minXz   = CoinMax( minXz, 1e-99 );
     *center  = maxXz / minXz;

     double normL = 0.0;
     double normU = 0.0;
     for (int k = 0; k < nlow; k++)
          if (cL_elts[low[k]] > normL) normL = cL_elts[low[k]];
     for (int k = 0; k < nupp; k++)
          if (cU_elts[upp[k]] > normU) normU = cU_elts[upp[k]];
     *Cinf    = CoinMax( normL, normU);
     *Cinf0   = maxXz;
}
Пример #9
0
CoinDenseVector<T>::CoinDenseVector(const CoinDenseVector<T> & rhs):
   nElements_(0),
   elements_(NULL)
{
     setVector(rhs.getNumElements(), rhs.getElements());
}
Пример #10
0
void ClpLsqr::do_lsqr(CoinDenseVector< double > &b,
  double damp, double atol, double btol, double conlim, int itnlim,
  bool show, Info info, CoinDenseVector< double > &x, int *istop,
  int *itn, Outfo *outfo, bool precon, CoinDenseVector< double > &Pr)
{

  /**
     Special version of LSQR for use with pdco.m.
     It continues with a reduced atol if a pdco-specific test isn't
     satisfied with the input atol.
     */

  //     Initialize.
  static char term_msg[8][80] = {
    "The exact solution is x = 0",
    "The residual Ax - b is small enough, given ATOL and BTOL",
    "The least squares error is small enough, given ATOL",
    "The estimated condition number has exceeded CONLIM",
    "The residual Ax - b is small enough, given machine precision",
    "The least squares error is small enough, given machine precision",
    "The estimated condition number has exceeded machine precision",
    "The iteration limit has been reached"
  };

  //  printf("***************** Entering LSQR *************\n");
  assert(model_);

  char str1[100], str2[100], str3[100], str4[100], head1[100], head2[100];

  int n = ncols_; // set  m,n from lsqr object

  *itn = 0;
  *istop = 0;
  double ctol = 0;
  if (conlim > 0)
    ctol = 1 / conlim;

  double anorm = 0;
  double acond = 0;
  double ddnorm = 0;
  double xnorm = 0;
  double xxnorm = 0;
  double z = 0;
  double cs2 = -1;
  double sn2 = 0;

  // Set up the first vectors u and v for the bidiagonalization.
  // These satisfy  beta*u = b,  alfa*v = A'u.

  CoinDenseVector< double > u(b);
  CoinDenseVector< double > v(n, 0.0);
  x.clear();
  double alfa = 0;
  double beta = u.twoNorm();
  if (beta > 0) {
    u = (1 / beta) * u;
    matVecMult(2, v, u);
    if (precon)
      v = v * Pr;
    alfa = v.twoNorm();
  }
  if (alfa > 0) {
    v.scale(1 / alfa);
  }
  CoinDenseVector< double > w(v);

  double arnorm = alfa * beta;
  if (arnorm == 0) {
    printf("  %s\n\n", term_msg[0]);
    return;
  }

  double rhobar = alfa;
  double phibar = beta;
  double bnorm = beta;
  double rnorm = beta;
  sprintf(head1, "   Itn      x(1)      Function");
  sprintf(head2, " Compatible   LS      Norm A   Cond A");

  if (show) {
    printf(" %s%s\n", head1, head2);
    double test1 = 1;
    double test2 = alfa / beta;
    sprintf(str1, "%6d %12.5e %10.3e", *itn, x[0], rnorm);
    sprintf(str2, "  %8.1e  %8.1e", test1, test2);
    printf("%s%s\n", str1, str2);
  }

  //----------------------------------------------------------------
  // Main iteration loop.
  //----------------------------------------------------------------
  while (*itn < itnlim) {
    *itn += 1;
    // Perform the next step of the bidiagonalization to obtain the
    // next beta, u, alfa, v.  These satisfy the relations
    // beta*u  =  a*v   -  alfa*u,
    // alfa*v  =  A'*u  -  beta*v.

    u.scale((-alfa));
    if (precon) {
      CoinDenseVector< double > pv(v * Pr);
      matVecMult(1, u, pv);
    } else {
      matVecMult(1, u, v);
    }
    beta = u.twoNorm();
    if (beta > 0) {
      u.scale((1 / beta));
      anorm = sqrt(anorm * anorm + alfa * alfa + beta * beta + damp * damp);
      v.scale((-beta));
      CoinDenseVector< double > vv(n);
      vv.clear();
      matVecMult(2, vv, u);
      if (precon)
        vv = vv * Pr;
      v = v + vv;
      alfa = v.twoNorm();
      if (alfa > 0)
        v.scale((1 / alfa));
    }

    // Use a plane rotation to eliminate the damping parameter.
    // This alters the diagonal (rhobar) of the lower-bidiagonal matrix.

    double rhobar1 = sqrt(rhobar * rhobar + damp * damp);
    double cs1 = rhobar / rhobar1;
    double sn1 = damp / rhobar1;
    double psi = sn1 * phibar;
    phibar *= cs1;

    // Use a plane rotation to eliminate the subdiagonal element (beta)
    // of the lower-bidiagonal matrix, giving an upper-bidiagonal matrix.

    double rho = sqrt(rhobar1 * rhobar1 + beta * beta);
    double cs = rhobar1 / rho;
    double sn = beta / rho;
    double theta = sn * alfa;
    rhobar = -cs * alfa;
    double phi = cs * phibar;
    phibar = sn * phibar;
    double tau = sn * phi;

    // Update x and w.

    double t1 = phi / rho;
    double t2 = -theta / rho;
    //    dk           =   ((1/rho)*w);

    double w_norm = w.twoNorm();
    x = x + t1 * w;
    w = v + t2 * w;
    ddnorm = ddnorm + (w_norm / rho) * (w_norm / rho);
    // if wantvar, var = var  +  dk.*dk; end

    // Use a plane rotation on the right to eliminate the
    // super-diagonal element (theta) of the upper-bidiagonal matrix.
    // Then use the result to estimate  norm(x).

    double delta = sn2 * rho;
    double gambar = -cs2 * rho;
    double rhs = phi - delta * z;
    double zbar = rhs / gambar;
    xnorm = sqrt(xxnorm + zbar * zbar);
    double gamma = sqrt(gambar * gambar + theta * theta);
    cs2 = gambar / gamma;
    sn2 = theta / gamma;
    z = rhs / gamma;
    xxnorm = xxnorm + z * z;

    // Test for convergence.
    // First, estimate the condition of the matrix  Abar,
    // and the norms of  rbar  and  Abar'rbar.

    acond = anorm * sqrt(ddnorm);
    double res1 = phibar * phibar;
    double res2 = res1 + psi * psi;
    rnorm = sqrt(res1 + res2);
    arnorm = alfa * fabs(tau);

    // Now use these norms to estimate certain other quantities,
    // some of which will be small near a solution.

    double test1 = rnorm / bnorm;
    double test2 = arnorm / (anorm * rnorm);
    double test3 = 1 / acond;
    t1 = test1 / (1 + anorm * xnorm / bnorm);
    double rtol = btol + atol * anorm * xnorm / bnorm;

    // The following tests guard against extremely small values of
    // atol, btol  or  ctol.  (The user may have set any or all of
    // the parameters  atol, btol, conlim  to 0.)
    // The effect is equivalent to the normal tests using
    // atol = eps,  btol = eps,  conlim = 1/eps.

    if (*itn >= itnlim)
      *istop = 7;
    if (1 + test3 <= 1)
      *istop = 6;
    if (1 + test2 <= 1)
      *istop = 5;
    if (1 + t1 <= 1)
      *istop = 4;

    // Allow for tolerances set by the user.

    if (test3 <= ctol)
      *istop = 3;
    if (test2 <= atol)
      *istop = 2;
    if (test1 <= rtol)
      *istop = 1;

    //-------------------------------------------------------------------
    // SPECIAL TEST THAT DEPENDS ON pdco.m.
    // Aname in pdco   is  iw in lsqr.
    // dy              is  x
    // Other stuff     is in info.

    // We allow for diagonal preconditioning in pdDDD3.
    //-------------------------------------------------------------------
    if (*istop > 0) {
      double r3new = arnorm;
      double r3ratio = r3new / info.r3norm;
      double atolold = atol;
      double atolnew = atol;

      if (atol > info.atolmin) {
        if (r3ratio <= 0.1) { // dy seems good
          // Relax
        } else if (r3ratio <= 0.5) { // Accept dy but make next one more accurate.
          atolnew = atolnew * 0.1;
        } else { // Recompute dy more accurately
          if (show) {
            printf("\n                                ");
            printf("                                \n");
            printf(" %5.1f%7d%7.3f", log10(atolold), *itn, r3ratio);
          }
          atol = atol * 0.1;
          atolnew = atol;
          *istop = 0;
        }

        outfo->atolold = atolold;
        outfo->atolnew = atolnew;
        outfo->r3ratio = r3ratio;
      }

      //-------------------------------------------------------------------
      // See if it is time to print something.
      //-------------------------------------------------------------------
      int prnt = 0;
      if (n <= 40)
        prnt = 1;
      if (*itn <= 10)
        prnt = 1;
      if (*itn >= itnlim - 10)
        prnt = 1;
      if (*itn % 10 == 0)
        prnt = 1;
      if (test3 <= 2 * ctol)
        prnt = 1;
      if (test2 <= 10 * atol)
        prnt = 1;
      if (test1 <= 10 * rtol)
        prnt = 1;
      if (*istop != 0)
        prnt = 1;

      if (prnt == 1) {
        if (show) {
          sprintf(str1, "   %6d %12.5e %10.3e", *itn, x[0], rnorm);
          sprintf(str2, "  %8.1e %8.1e", test1, test2);
          sprintf(str3, " %8.1e %8.1e", anorm, acond);
          printf("%s%s%s\n", str1, str2, str3);
        }
      }
      if (*istop > 0)
        break;
    }
  }
  // End of iteration loop.
  // Print the stopping condition.

  if (show) {
    printf("\n LSQR finished\n");
    //    disp(msg(istop+1,:))
    //    disp(' ')
    printf("%s\n", term_msg[*istop]);
    sprintf(str1, "istop  =%8d     itn    =%8d", *istop, *itn);
    sprintf(str2, "anorm  =%8.1e   acond  =%8.1e", anorm, acond);
    sprintf(str3, "rnorm  =%8.1e   arnorm =%8.1e", rnorm, arnorm);
    sprintf(str4, "bnorm  =%8.1e   xnorm  =%8.1e", bnorm, xnorm);
    printf("%s %s\n", str1, str2);
    printf("%s %s\n", str3, str4);
  }
}