//todo: remove it later, not efective private float FindMinObjParallel2(float GMax, int i, float[] Q_i, SortedNVal minIdx) { // object lockObj = new object(); float GMax2Tmp = -INF; // Parallel.For(0, active_size, () => new Pair <float, Pair <int, float> >(-INF, new Pair <int, float>(-1, INF)), (j, loopState, maxMinPair) => { if (y[j] == +1) { if (!is_lower_bound(j)) { float grad_diff = GMax + G[j]; if (G[j] >= maxMinPair.First) { maxMinPair.First = G[j]; } if (grad_diff > 0) { float obj_diff; float quad_coef = (float)(Q_i[i] + QD[j] - 2.0 * y[i] * Q_i[j]); if (quad_coef > 0) { obj_diff = -(grad_diff * grad_diff) / quad_coef; } else { obj_diff = (float)(-(grad_diff * grad_diff) / 1e-12); } if (obj_diff < maxMinPair.Second.Second) { maxMinPair.Second.First = j; maxMinPair.Second.Second = obj_diff; } } } } else { if (!is_upper_bound(j)) { float grad_diff = GMax - G[j]; if (-G[j] >= maxMinPair.First) { maxMinPair.First = -G[j]; } if (grad_diff > 0) { float obj_diff; float quad_coef = (float)(Q_i[i] + QD[j] + 2.0 * y[i] * Q_i[j]); if (quad_coef > 0) { obj_diff = -(grad_diff * grad_diff) / quad_coef; } else { obj_diff = (float)(-(grad_diff * grad_diff) / 1e-12); } if (obj_diff < maxMinPair.Second.Second) { maxMinPair.Second.First = j; maxMinPair.Second.Second = obj_diff; } } } } //if (maxMinPair.Second.First == -1) // return null; return(maxMinPair); }, (maxMinPair) => { if (maxMinPair != null && maxMinPair.Second.First != -1) { lock (lockObj) { if (GMax2Tmp < maxMinPair.First) { GMax2Tmp = maxMinPair.First; } minIdx.Add(maxMinPair.Second.First, maxMinPair.Second.Second); } } } ); return(GMax2Tmp); }
private float FindMinObjSeq(float GMax, float GMax2, int i, float[] Q_i, SortedNVal minIdx) { for (int j = 0; j < active_size; j++) { if (y[j] == +1) { if (!is_lower_bound(j)) { float grad_diff = GMax + G[j]; if (G[j] >= GMax2) { GMax2 = G[j]; } if (grad_diff > 0) { float obj_diff; float quad_coef = (float)(Q_i[i] + QD[j] - 2.0 * y[i] * Q_i[j]); if (quad_coef > 0) { obj_diff = -(grad_diff * grad_diff) / quad_coef; } else { obj_diff = (float)(-(grad_diff * grad_diff) / 1e-12); } minIdx.Add(j, obj_diff); //if (obj_diff < obj_diff_Min) //previous "<=" //{ // GMin_idx = j; // obj_diff_Min = obj_diff; // // minSecIdx.Add(new KeyValuePair<int, float>(j, obj_diff_Min)); //} //else if (obj_diff_Min < obj_diff_NMin) //{ // // minSecIdx.Add(new KeyValuePair<int, float>(j, obj_diff)); //} //else continue; } //else continue; } //else continue; } else { if (!is_upper_bound(j)) { float grad_diff = GMax - G[j]; if (-G[j] >= GMax2) { GMax2 = -G[j]; } if (grad_diff > 0) { float obj_diff; float quad_coef = (float)(Q_i[i] + QD[j] + 2.0 * y[i] * Q_i[j]); if (quad_coef > 0) { obj_diff = -(grad_diff * grad_diff) / quad_coef; } else { obj_diff = (float)(-(grad_diff * grad_diff) / 1e-12); } minIdx.Add(j, obj_diff); //if (obj_diff < obj_diff_Min) //{ // GMin_idx = j; // obj_diff_Min = obj_diff; // //minSecIdx.Add(new KeyValuePair<int, float>(j, obj_diff_Min)); //} //else if (obj_diff < obj_diff_NMin) //{ // minSecIdx.Add(new KeyValuePair<int, float>(j, obj_diff)); //} //else continue; } //else continue; } //else continue; } //if (minSecIdx.Count > pairsCount) //{ // var minPair = minSecIdx.Min; // minSecIdx.Remove(minPair); // obj_diff_NMin = minPair.Value; //} } return(GMax2); }
private float FindMinObjParallel(float GMax, OrderablePartitioner <Tuple <int, int> > rangePart, int i, float[] Q_i, SortedNVal minIdx) { float GMax2Tmp = -INF; //todo: to many allocation, use range partitioner Parallel.ForEach(rangePart, () => new Pair <float, Pair <int, float> >(-INF, new Pair <int, float>(-1, INF)), (range, loopState, maxMinPair) => { int endRange = range.Item2; for (int j = range.Item1; j < endRange; j++) { if (y[j] == +1) { if (!is_lower_bound(j)) { float grad_diff = GMax + G[j]; if (G[j] >= maxMinPair.First) { maxMinPair.First = G[j]; } if (grad_diff > 0) { float obj_diff; float quad_coef = (float)(Q_i[i] + QD[j] - 2.0 * y[i] * Q_i[j]); if (quad_coef > 0) { obj_diff = -(grad_diff * grad_diff) / quad_coef; } else { obj_diff = (float)(-(grad_diff * grad_diff) / 1e-12); } if (obj_diff < maxMinPair.Second.Second) { maxMinPair.Second.First = j; maxMinPair.Second.Second = obj_diff; } } } } else { if (!is_upper_bound(j)) { float grad_diff = GMax - G[j]; if (-G[j] >= maxMinPair.First) { maxMinPair.First = -G[j]; } if (grad_diff > 0) { float obj_diff; float quad_coef = (float)(Q_i[i] + QD[j] + 2.0 * y[i] * Q_i[j]); if (quad_coef > 0) { obj_diff = -(grad_diff * grad_diff) / quad_coef; } else { obj_diff = (float)(-(grad_diff * grad_diff) / 1e-12); } if (obj_diff < maxMinPair.Second.Second) { maxMinPair.Second.First = j; maxMinPair.Second.Second = obj_diff; } } } } } return(maxMinPair); }, (maxMinPair) => { lock (lockObj) { if (GMax2Tmp < maxMinPair.First) { GMax2Tmp = maxMinPair.First; } //todo: in this solver we use only one value and index, minIdx.Add(maxMinPair.Second.First, maxMinPair.Second.Second); } } ); return(GMax2Tmp); }
// return 1 if already optimal, return 0 otherwise int select_working_set(int[] working_set, int pairsCount) { // return i,j such that // i: Maximizes -y_i * grad(f)_i, i in I_up(\alpha) // j: mimimizes the decrease of obj value // (if quadratic coefficeint <= 0, replace it with tau) // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha) float GMax = -INF; // float GNMax = -INF; float GMax2 = -INF; int GMax_idx = -1; int GMin_idx = -1; //float obj_diff_Min = INF; //float obj_diff_NMin = INF; #region find max i Pair <int, float> maxPair = new Pair <int, float>(-1, -INF); //todo: move it up to class field, in this solver active_size is constant var partition = Partitioner.Create(0, active_size); #region Find Max pair in parallel Parallel.ForEach(partition, () => new Pair <int, float>(-1, -INF), (range, loopState, localMax) => { int endRange = range.Item2; for (int t = range.Item1; t < endRange; t++) { if (y[t] == +1) { if (!is_upper_bound(t)) { if (-G[t] > localMax.Second) //wcześniej było większe lub równe { localMax.First = t; localMax.Second = -G[t]; } } } else { if (!is_lower_bound(t)) { if (G[t] > localMax.Second) //wcześniej było >= { localMax.First = t; localMax.Second = G[t]; } } } } return(localMax); }, (localMax) => { lock (lockObj) { if (localMax.Second > maxPair.Second) { maxPair = localMax; } } } ); #endregion GMax = maxPair.Second; GMax_idx = maxPair.First; #region original sequential find max //for (int t = 0; t < active_size; t++) //{ // if (y[t] == +1) // { // if (!is_upper_bound(t)) // { // if (-G[t] > GMax) //wcześniej było większe lub równe // { // GMax = -G[t]; // GMax_idx = t; // } // } // } // else // { // if (!is_lower_bound(t)) // { // if (G[t] > GMax) //wcześniej było >= // { // GMax = G[t]; // GMax_idx = t; // } // } // } //} #endregion #endregion int i = GMax_idx; float[] Q_i = null; if (i != -1) // null Q_i not accessed: GMax=-INF if i=-1 { Q_i = Q.GetQ(i, active_size); } //todo: sorted N values, for this solver we need only one value, not "pairsCount" which is equal number of cores //find min SortedNVal minIdx = new SortedNVal(pairsCount, SortedNVal.SortMode.Asc); GMax2 = FindMinObjParallel(GMax, partition, i, Q_i, minIdx); //GMax2 = FindMinObjParallel2(GMax, i, Q_i, minIdx); //GMax2 = FindMinObjSeq(GMax, GMax2, i, Q_i, minIdx); if (GMax + GMax2 < EPS) { return(1); } if (minIdx.Count > 0) { GMin_idx = minIdx.ToArray()[0].Key; } else { GMin_idx = -1; } working_set[0] = GMax_idx; working_set[1] = GMin_idx; return(0); }