internal virtual void Solve(int l1, SvmMatrix q1, double[] p1, short[] y1, double[] alpha1, double cp1, double cn1, double eps1, SolutionInfo si, bool shrinking) { l = l1; q = q1; qd = q1.GetQd(); p = (double[])p1.Clone(); y = (short[])y1.Clone(); alpha = (double[])alpha1.Clone(); cp = cp1; cn = cn1; eps = eps1; unshrink = false; // initialize alpha_status { alphaStatus = new byte[l1]; for (int i = 0; i < l1; i++) { UpdateAlphaStatus(i); } } // initialize active set (for shrinking) { activeSet = new int[l1]; for (int i = 0; i < l1; i++) { activeSet[i] = i; } activeSize = l1; } // initialize gradient { g = new double[l1]; gBar = new double[l1]; int i; for (i = 0; i < l1; i++) { g[i] = p[i]; gBar[i] = 0; } for (i = 0; i < l1; i++) { if (!IsLowerBound(i)) { float[] qI = q1.GetQ(i, l1); double alphaI = alpha[i]; int j; for (j = 0; j < l1; j++) { g[j] += alphaI * qI[j]; } if (IsUpperBound(i)) { for (j = 0; j < l1; j++) { gBar[j] += GetC(i) * qI[j]; } } } } } // optimization step int iter = 0; int maxIter = Math.Max(10000000, l1 > int.MaxValue / 100 ? int.MaxValue : 100 * l1); int counter = Math.Min(l1, 1000) + 1; int[] workingSet = new int[2]; while (iter < maxIter) { // show progress and do shrinking if (--counter == 0) { counter = Math.Min(l1, 1000); if (shrinking) { DoShrinking(); } SvmMain.Info("."); } if (SelectWorkingSet(workingSet) != 0) { // reconstruct the whole gradient ReconstructGradient(); // reset active set size and check activeSize = l1; SvmMain.Info("*"); if (SelectWorkingSet(workingSet) != 0) { break; } counter = 1; // do shrinking next iteration } int i = workingSet[0]; int j = workingSet[1]; ++iter; // update alpha[i] and alpha[j], handle bounds carefully float[] qI = q1.GetQ(i, activeSize); float[] qJ = q1.GetQ(j, activeSize); double cI = GetC(i); double cJ = GetC(j); double oldAlphaI = alpha[i]; double oldAlphaJ = alpha[j]; if (y[i] != y[j]) { double quadCoef = qd[i] + qd[j] + 2 * qI[j]; if (quadCoef <= 0) { quadCoef = 1e-12; } double delta = (-g[i] - g[j]) / quadCoef; double diff = alpha[i] - alpha[j]; alpha[i] += delta; alpha[j] += delta; if (diff > 0) { if (alpha[j] < 0) { alpha[j] = 0; alpha[i] = diff; } } else { if (alpha[i] < 0) { alpha[i] = 0; alpha[j] = -diff; } } if (diff > cI - cJ) { if (alpha[i] > cI) { alpha[i] = cI; alpha[j] = cI - diff; } } else { if (alpha[j] > cJ) { alpha[j] = cJ; alpha[i] = cJ + diff; } } } else { double quadCoef = qd[i] + qd[j] - 2 * qI[j]; if (quadCoef <= 0) { quadCoef = 1e-12; } double delta = (g[i] - g[j]) / quadCoef; double sum = alpha[i] + alpha[j]; alpha[i] -= delta; alpha[j] += delta; if (sum > cI) { if (alpha[i] > cI) { alpha[i] = cI; alpha[j] = sum - cI; } } else { if (alpha[j] < 0) { alpha[j] = 0; alpha[i] = sum; } } if (sum > cJ) { if (alpha[j] > cJ) { alpha[j] = cJ; alpha[i] = sum - cJ; } } else { if (alpha[i] < 0) { alpha[i] = 0; alpha[j] = sum; } } } // update G double deltaAlphaI = alpha[i] - oldAlphaI; double deltaAlphaJ = alpha[j] - oldAlphaJ; for (int k = 0; k < activeSize; k++) { g[k] += qI[k] * deltaAlphaI + qJ[k] * deltaAlphaJ; } // update alpha_status and G_bar { bool ui = IsUpperBound(i); bool uj = IsUpperBound(j); UpdateAlphaStatus(i); UpdateAlphaStatus(j); int k; if (ui != IsUpperBound(i)) { qI = q1.GetQ(i, l1); if (ui) { for (k = 0; k < l1; k++) { gBar[k] -= cI * qI[k]; } } else { for (k = 0; k < l1; k++) { gBar[k] += cI * qI[k]; } } } if (uj != IsUpperBound(j)) { qJ = q1.GetQ(j, l1); if (uj) { for (k = 0; k < l1; k++) { gBar[k] -= cJ * qJ[k]; } } else { for (k = 0; k < l1; k++) { gBar[k] += cJ * qJ[k]; } } } } } if (iter >= maxIter) { if (activeSize < l1) { // reconstruct the whole gradient to calculate objective value ReconstructGradient(); activeSize = l1; SvmMain.Info("*"); } SvmMain.Info("\nWARNING: reaching max number of iterations"); } // calculate rho si.rho = CalculateRho(); // calculate objective value { double v = 0; int i; for (i = 0; i < l1; i++) { v += alpha[i] * (g[i] + p[i]); } si.obj = v / 2; } // put back the solution { for (int i = 0; i < l1; i++) { alpha1[activeSet[i]] = alpha[i]; } } si.upperBoundP = cp1; si.upperBoundN = cn1; SvmMain.Info("\noptimization finished, #iter = " + iter + "\n"); }
internal override void Solve(int l1, SvmMatrix q1, double[] p1, short[] y1, double[] alpha1, double cp1, double cn1, double eps1, SolutionInfo si1, bool shrinking) { si = si1; base.Solve(l1, q1, p1, y1, alpha1, cp1, cn1, eps1, si1, shrinking); }
internal virtual void Solve(int l1, SvmMatrix q1, double[] p1, short[] y1, double[] alpha1, double cp1, double cn1, double eps1, SolutionInfo si, bool shrinking) { l = l1; q = q1; qd = q1.GetQd(); p = (double[]) p1.Clone(); y = (short[]) y1.Clone(); alpha = (double[]) alpha1.Clone(); cp = cp1; cn = cn1; eps = eps1; unshrink = false; // initialize alpha_status { alphaStatus = new byte[l1]; for (int i = 0; i < l1; i++){ UpdateAlphaStatus(i); } } // initialize active set (for shrinking) { activeSet = new int[l1]; for (int i = 0; i < l1; i++){ activeSet[i] = i; } activeSize = l1; } // initialize gradient { g = new double[l1]; gBar = new double[l1]; int i; for (i = 0; i < l1; i++){ g[i] = p[i]; gBar[i] = 0; } for (i = 0; i < l1; i++){ if (!IsLowerBound(i)){ float[] qI = q1.GetQ(i, l1); double alphaI = alpha[i]; int j; for (j = 0; j < l1; j++){ g[j] += alphaI*qI[j]; } if (IsUpperBound(i)){ for (j = 0; j < l1; j++){ gBar[j] += GetC(i)*qI[j]; } } } } } // optimization step int iter = 0; int maxIter = Math.Max(10000000, l1 > int.MaxValue/100 ? int.MaxValue : 100*l1); int counter = Math.Min(l1, 1000) + 1; int[] workingSet = new int[2]; while (iter < maxIter){ // show progress and do shrinking if (--counter == 0){ counter = Math.Min(l1, 1000); if (shrinking){ DoShrinking(); } SvmMain.Info("."); } if (SelectWorkingSet(workingSet) != 0){ // reconstruct the whole gradient ReconstructGradient(); // reset active set size and check activeSize = l1; SvmMain.Info("*"); if (SelectWorkingSet(workingSet) != 0){ break; } counter = 1; // do shrinking next iteration } int i = workingSet[0]; int j = workingSet[1]; ++iter; // update alpha[i] and alpha[j], handle bounds carefully float[] qI = q1.GetQ(i, activeSize); float[] qJ = q1.GetQ(j, activeSize); double cI = GetC(i); double cJ = GetC(j); double oldAlphaI = alpha[i]; double oldAlphaJ = alpha[j]; if (y[i] != y[j]){ double quadCoef = qd[i] + qd[j] + 2*qI[j]; if (quadCoef <= 0){ quadCoef = 1e-12; } double delta = (-g[i] - g[j])/quadCoef; double diff = alpha[i] - alpha[j]; alpha[i] += delta; alpha[j] += delta; if (diff > 0){ if (alpha[j] < 0){ alpha[j] = 0; alpha[i] = diff; } } else{ if (alpha[i] < 0){ alpha[i] = 0; alpha[j] = -diff; } } if (diff > cI - cJ){ if (alpha[i] > cI){ alpha[i] = cI; alpha[j] = cI - diff; } } else{ if (alpha[j] > cJ){ alpha[j] = cJ; alpha[i] = cJ + diff; } } } else{ double quadCoef = qd[i] + qd[j] - 2*qI[j]; if (quadCoef <= 0){ quadCoef = 1e-12; } double delta = (g[i] - g[j])/quadCoef; double sum = alpha[i] + alpha[j]; alpha[i] -= delta; alpha[j] += delta; if (sum > cI){ if (alpha[i] > cI){ alpha[i] = cI; alpha[j] = sum - cI; } } else{ if (alpha[j] < 0){ alpha[j] = 0; alpha[i] = sum; } } if (sum > cJ){ if (alpha[j] > cJ){ alpha[j] = cJ; alpha[i] = sum - cJ; } } else{ if (alpha[i] < 0){ alpha[i] = 0; alpha[j] = sum; } } } // update G double deltaAlphaI = alpha[i] - oldAlphaI; double deltaAlphaJ = alpha[j] - oldAlphaJ; for (int k = 0; k < activeSize; k++){ g[k] += qI[k]*deltaAlphaI + qJ[k]*deltaAlphaJ; } // update alpha_status and G_bar { bool ui = IsUpperBound(i); bool uj = IsUpperBound(j); UpdateAlphaStatus(i); UpdateAlphaStatus(j); int k; if (ui != IsUpperBound(i)){ qI = q1.GetQ(i, l1); if (ui){ for (k = 0; k < l1; k++){ gBar[k] -= cI*qI[k]; } } else{ for (k = 0; k < l1; k++){ gBar[k] += cI*qI[k]; } } } if (uj != IsUpperBound(j)){ qJ = q1.GetQ(j, l1); if (uj){ for (k = 0; k < l1; k++){ gBar[k] -= cJ*qJ[k]; } } else{ for (k = 0; k < l1; k++){ gBar[k] += cJ*qJ[k]; } } } } } if (iter >= maxIter){ if (activeSize < l1){ // reconstruct the whole gradient to calculate objective value ReconstructGradient(); activeSize = l1; SvmMain.Info("*"); } SvmMain.Info("\nWARNING: reaching max number of iterations"); } // calculate rho si.rho = CalculateRho(); // calculate objective value { double v = 0; int i; for (i = 0; i < l1; i++){ v += alpha[i]*(g[i] + p[i]); } si.obj = v/2; } // put back the solution { for (int i = 0; i < l1; i++){ alpha1[activeSet[i]] = alpha[i]; } } si.upperBoundP = cp1; si.upperBoundN = cn1; SvmMain.Info("\noptimization finished, #iter = " + iter + "\n"); }