Пример #1
0
/* ----------------------------------------------------------------------- */
int projectD(double xPtr[], double bPtr[], double dPtr[], double dOrg[], double tau, int n)
/* ----------------------------------------------------------------------- */
{  int
       i, j;
   double
       csdb,        /* Cumulative sum of d.*b          */
       csd2,        /* Cumulative sum of d.^2          */
       b,           /* Current element of vector b     */
       d,           /* Current element of vector d     */
       bd,          /* Current element of vector b / d */
       alpha  = 0,
       soft   = 0;

   /* Check if tau is essentially zero.  Exit with x = 0. */
   if (tau < DBL_EPSILON)
   {   for (i = 0; i < n; i++) xPtr[i] = 0;
       return 0;
   }

   /* Preliminary check on trivial solution x = b (meanwhile, scale x) */
   for (csdb = 0, i = 0; i < n; i++)
   {  d = dPtr[i];
      b = xPtr[i];
      csdb += (d * b);
      xPtr[i] = b / d;
   }

   if (csdb <= tau)
   {  
       /* Reset the entries of x to b */
      memcpy((void *)xPtr, (void *)bPtr, n * sizeof(double));
      return 0;
   }

   /* Set up the heap (we have to sort on b./d) */
   heap_build_2(n, xPtr, dPtr);

   /* Initialise csbd with -tau so we don't have to subtract this at every iteration */
   csdb = -tau;
   csd2 =  0;

   /* Determine the threshold level `soft' */
   for (i = n, j = 0; j < n; soft = alpha)
   {
      bd    = xPtr[0];        /* Get current maximum b / d                */
      j    ++;                /* Give compiler some room for optimization */
      d     = dPtr[0];        /* Get current value of d                   */
      d    *= d;              /* Compute d squared                        */
      csd2 += d;              /* Update the cumulative sum of d.*d        */
      csdb += bd * d;         /* Update the cumulative sum of d.*b        */

      /* Move heap to next maximum value */
      i = heap_del_max_2(i, xPtr, dPtr);

      /* Compute the required step to satisfy the lambda constraint */
      alpha  = csdb / csd2;

      /* We are done as soon as the constraint can be satisfied */
      /* without exceeding the current minimum value of b / d   */
      if (alpha >= bd) break;
   }

   /* Set the solution */
   for (i = 0; i < n; i++)
   {  b     = bPtr[i];
      alpha = dOrg[i] * soft; /* Use the original values of d here */
      if (b <= alpha)
           xPtr[i] = 0;
      else xPtr[i] = b - alpha;
   }

   return j;
}
Пример #2
0
/* ----------------------------------------------------------------------- */
int projectD(double xPtr[], double bPtr[], double dPtr[], double lambda, int n)
/* ----------------------------------------------------------------------- */
{  int
       i, j;
   double
       csdb,        /* Cumulative sum of d.*b          */
       csd2,        /* Cumulative sum of d.^2          */
       b,           /* Current element of vector b     */
       d,           /* Current element of vector d     */
       bd,          /* Current element of vector b / d */
       alpha  = 0,
       tau    = 0;

   /* Check if lambda is essentially zero.  Exit with x = 0. */
   if (lambda < DBL_EPSILON)
   {   for (i = 0; i < n; i++) xPtr[i] = 0;
       return 0;
   }

   /* Preliminary check on trivial solution x = Db (and scale b) */
   for (csdb = 0, i = 0; i < n; i++)
   {  d = dPtr[i];
      b = xPtr[i];
      csdb += (d * fabs(b));
      xPtr[i] = b / d;
   }
   if (csdb <= lambda)
   {  
       /* Reset the entries of x to b */
      memcpy((void *)xPtr, (void *)bPtr, n * sizeof(double));
      return 0;
   }

   /* Set up the heap (we have to sort on Db) */
   heap_build_2(n, xPtr, dPtr);

   /* Initialise csbd with -lambda so we don't have to subtract this at every iteration */
   csdb = -lambda;
   csd2 =  0;

   /* Determine the threshold level tau */
   for (i = n, j = 0; j < n; tau = alpha)
   {
      bd    = fabs(xPtr[0]);  /* Get current minimum b / d                */
      j    ++;                /* Give compiler some room for optimization */
      d     = dPtr[0];        /* Get current value of d                   */
      d    *= d;              /* Compute d squared                        */
      csd2 += d;              /* Update the cumulative sum of d.*d        */
      csdb += bd * d;         /* Update the cumulative sum of d.*b        */

      /* Move heap to next minimum value */
      i = heap_del_min_2(i, bPtr, dPtr);

      /* Compute the required step to satisfy the lambda constraint */
      alpha  = csdb / csd2;

      /* We are done as soon as the constraint can be satisfied */
      /* without exceeding the current minimum value of b / d   */
      if (alpha >= bd) break;
   }

   /* Set the solution */
   for (i = 0; i < n; i++)
   {  b     = bPtr[i];
      alpha = dPtr[i] * tau;
      if (fabs(b) <= alpha)
           xPtr[i] = 0;
      else xPtr[i] = b - alpha * (b < 0 ? -1 : 1);
      
   }

   return j;
}