32 #ifndef SHARK_ALGORITHMS_QP_BOXBASEDSHRINKINGSTRATEGY_H 33 #define SHARK_ALGORITHMS_QP_BOXBASEDSHRINKINGSTRATEGY_H 46 template<
class Problem>
53 template<
class ProblemT>
56 , m_isUnshrinked(false)
58 , m_gradientEdge(problem.linear)
62 using Problem::gradient;
63 using Problem::linear;
64 using Problem::active;
65 using Problem::dimensions;
66 using Problem::quadratic;
67 using Problem::isLowerBound;
68 using Problem::isUpperBound;
69 using Problem::boxMin;
70 using Problem::boxMax;
71 using Problem::setInitialSolution;
73 virtual void updateSMO(std::size_t i, std::size_t j){
74 double aiOld = alpha(i);
75 double ajOld = alpha(j);
77 Problem::updateSMO(i,j);
82 updateGradientEdge(i,aiOld,ai);
83 updateGradientEdge(j,ajOld,aj);
87 if(!m_shrink)
return false;
91 getMaxKKTViolations(largestUp,smallestDown,active());
94 if (!m_isUnshrinked && (largestUp - smallestDown < 10.0 * epsilon))
98 getMaxKKTViolations(largestUp, smallestDown, dimensions());
101 auto& active = this->m_active;
102 for (std::size_t a = active; a > 0; --a){
104 if(Problem::testShrinkVariable(i, largestUp, smallestDown)){
105 Problem::flipCoordinates(i,active-1);
106 std::swap( m_gradientEdge[i], m_gradientEdge[active-1]);
115 if (active() == dimensions())
return;
116 m_isUnshrinked =
true;
125 for (std::size_t a = active(); a < dimensions(); a++)
126 this->m_gradient(a) = m_gradientEdge(a);
128 for (std::size_t i = 0; i < active(); i++){
130 if (isUpperBound(i) || isLowerBound(i))
continue;
132 QpFloatType* q = quadratic().row(i, 0, dimensions());
133 for (std::size_t a = active(); a < dimensions(); a++)
134 this->m_gradient(a) -= alpha(i) * q[a];
137 this->m_active = dimensions();
141 m_shrink = shrinking;
151 void setInitialSolution(RealVector
const& alpha, RealVector
const& gradient, RealVector
const& gradientEdge){
152 Problem::setInitialSolution(alpha,gradient);
153 std::size_t n = dimensions();
155 for (std::size_t i=0; i<n; i++){
156 std::size_t j = this->permutation(i);
157 m_gradientEdge(i) = gradientEdge(j);
168 std::size_t n = dimensions();
170 RealVector gradient = this->m_problem.linear;
171 RealVector gradientEdge = this->m_problem.linear;
172 blas::vector<QpFloatType> q(n);
173 std::vector<std::size_t> inverse(n);
174 for (std::size_t i=0; i<n; i++)
175 inverse[this->permutation(i)] = i;
176 for (std::size_t i=0; i<n; i++)
179 if (a == 0.0)
continue;
180 this->m_problem.quadratic.row(i, 0, n, q.raw_storage().values);
181 noalias(gradient) -= a * q;
182 std::size_t j = inverse[i];
183 if (a == boxMin(j) || a == boxMax(j)) gradientEdge -= a * q;
191 RealVector alpha_old(dimensions);
192 for(std::size_t i = 0; i != dimensions; ++i){
193 updateGradientEdge(i,alpha_old(i), alpha(i));
199 Problem::scaleBoxConstraints(factor,variableScalingFactor);
200 if(factor != variableScalingFactor){
201 for(std::size_t i = 0; i != dimensions(); ++i){
202 m_gradientEdge(i) = linear(i);
206 for(std::size_t i = 0; i != dimensions(); ++i){
207 m_gradientEdge(i) -= linear(i);
208 m_gradientEdge(i) *= factor;
209 m_gradientEdge(i) += linear(i);
216 m_gradientEdge(i) -= linear(i);
217 m_gradientEdge(i) += newValue;
218 Problem::setLinear(i,newValue);
223 Problem::flipCoordinates(i,j);
224 std::swap( m_gradientEdge[i], m_gradientEdge[j]);
232 void updateGradientEdge(std::size_t i,
double oldAlpha,
double newAlpha){
234 if(!m_shrink || oldAlpha==newAlpha)
return;
235 bool isInsideOld = oldAlpha > boxMin(i) && oldAlpha < boxMax(i);
236 bool isInsideNew = newAlpha > boxMin(i) && newAlpha < boxMax(i);
239 if((oldAlpha == 0 || isInsideOld) && isInsideNew)
250 QpFloatType* q = quadratic().row(i, 0, dimensions());
251 for(std::size_t a = 0; a != dimensions(); ++a){
252 m_gradientEdge(a) -= diff*q[a];
256 void getMaxKKTViolations(
double& largestUp,
double& smallestDown, std::size_t maxIndex){
258 smallestDown = 1e100;
259 for (std::size_t a = 0; a < maxIndex; a++){
260 if (!isLowerBound(a))
261 smallestDown = std::min(smallestDown,gradient(a));
262 if (!isUpperBound(a))
263 largestUp = std::max(largestUp,gradient(a));
273 RealVector m_gradientEdge;