8 #ifndef SMOOTH_NESTEROV_HXX_
9 #define SMOOTH_NESTEROV_HXX_
33 if (name.compare(
"WC_STEP")==0)
return WC_STEP;
34 else if (name.compare(
"JOJIC_STEP")==0)
return JOJIC_STEP;
43 case WC_STEP :
return std::string(
"WC_STEP");
44 case JOJIC_STEP :
return std::string(
"JOJIC_STEP");
45 default:
return std::string(
"UNKNOWN");
51 bool absolutePrecision=
true,
52 size_t numOfInternalIterations=3,
56 ValueType primalBoundPrecision=std::numeric_limits<ValueType>::epsilon(),
58 size_t presolveMaxIterNumber=100,
68 bool plainGradient=
false
70 :parent(numOfExternalIterations,
73 numOfInternalIterations,
79 presolveMaxIterNumber,
97 #ifdef TRWS_DEBUG_OUTPUT
98 void print(std::ostream& fout)
const
101 fout <<
"gradientStep_="<<
getString(gradientStep_)<<std::endl;
102 fout <<
"gamma0_=" << gamma0_ <<std::endl;
103 fout <<
"plainGradient_=" << plainGradient_ <<std::endl;
110 template<
class GM,
class ACC>
139 #ifdef TRWS_DEBUG_OUTPUT
140 ,std::ostream& fout=std::cout
145 #ifdef TRWS_DEBUG_OUTPUT
146 ,(param.verbose_ ? fout : *OUT::nullstream::Instance())
150 _currentDualVector(_getDualVectorSize(),0.0)
152 #ifdef TRWS_DEBUG_OUTPUT
153 parent::_fout <<
"Parameters of the "<<
name() <<
" algorithm:"<<std::endl;
154 param.print(parent::_fout);
157 if (param.numOfExternalIterations_==0)
throw std::runtime_error(
"NEST: a strictly positive number of iterations must be provided!");
160 template<
class VISITOR>
163 std::string
name()
const{
return "NEST"; }
177 ValueType _evaluateGradient(
const DDVectorType& point,DDVectorType* pgradient);
178 ValueType _evaluateSmoothObjective(
const DDVectorType& point);
180 void _SetDualVariables(
const DDVectorType& lambda);
181 ValueType _estimateOmega0()
const{
return 1;};
182 void _InitSmoothing();
183 void _GradientStep(
const DDVectorType& gradient,
const DDVectorType& startPoint, DDVectorType& endPoint, ValueType stepsize);
185 ValueType getLipschitzConstant()
const;
187 Parameter _parameters;
188 DDVectorType _currentDualVector;
191 template<
class GM,
class ACC>
192 typename NesterovAcceleratedGradient<GM,ACC>::ValueType
193 NesterovAcceleratedGradient<GM,ACC>::getLipschitzConstant()
const
196 for (IndexType modelId=0;modelId<parent::_storage.numberOfModels();++modelId)
197 result+=(ValueType)parent::_storage.size(modelId);
199 return result/parent::_sumprodsolver.GetSmoothing();
202 template<
class GM,
class ACC>
203 typename NesterovAcceleratedGradient<GM,ACC>::ValueType
204 NesterovAcceleratedGradient<GM,ACC>::_evaluateGradient(
const DDVectorType& point,DDVectorType* pgradient)
206 ValueType bound=_evaluateSmoothObjective(point);
207 parent::_sumprodsolver.GetMarginalsMove();
208 std::vector<ValueType> buffer1st;
209 std::vector<ValueType> buffer;
211 pgradient->resize(_currentDualVector.size());
212 typename DDVectorType::iterator gradientIt=pgradient->begin();
213 for (IndexType varId=0;varId<parent::_storage.masterModel().numberOfVariables();++varId)
215 const typename Storage::SubVariableListType& varList=parent::_storage.getSubVariableList(varId);
217 if (varList.size()==1)
continue;
218 typename Storage::SubVariableListType::const_iterator modelIt=varList.begin();
219 IndexType firstModelId=modelIt->subModelId_;
220 IndexType firstModelVariableId=modelIt->subVariableId_;
221 buffer1st.resize(parent::_storage.masterModel().numberOfLabels(varId));
222 buffer.resize(parent::_storage.masterModel().numberOfLabels(varId));
223 parent::_sumprodsolver.GetMarginalsForSubModel(firstModelId,firstModelVariableId,buffer1st.begin());
225 for(;modelIt!=varList.end();++modelIt)
227 parent::_sumprodsolver.GetMarginalsForSubModel(modelIt->subModelId_,modelIt->subVariableId_,buffer.begin());
228 gradientIt=std::transform(buffer.begin(),buffer.end(),buffer1st.begin(),gradientIt,std::minus<ValueType>());
236 template<
class GM,
class ACC>
237 typename NesterovAcceleratedGradient<GM,ACC>::ValueType
238 NesterovAcceleratedGradient<GM,ACC>::_evaluateSmoothObjective(
const DDVectorType& point)
240 _SetDualVariables(point);
241 parent::_sumprodsolver.ForwardMove();
242 return parent::_sumprodsolver.bound();
245 template<
class GM,
class ACC>
246 void NesterovAcceleratedGradient<GM,ACC>::_SetDualVariables(
const DDVectorType& lambda)
248 DDVectorType delta(_currentDualVector.size());
249 std::transform(lambda.begin(),lambda.end(),_currentDualVector.begin(),delta.begin(),std::minus<ValueType>());
250 _currentDualVector=lambda;
251 parent::_storage.addDDvector(delta);
254 template<
class GM,
class ACC>
255 void NesterovAcceleratedGradient<GM,ACC>::_InitSmoothing()
257 if (_parameters.smoothing_ > 0.0)
258 parent::_sumprodsolver.SetSmoothing(_parameters.smoothing_);
260 throw std::runtime_error(
"NesterovAcceleratedGradient::_InitSmoothing(): Error! Automatic smoothing selection is not implemented yet.");
263 template<
class GM,
class ACC>
264 void NesterovAcceleratedGradient<GM,ACC>::_GradientStep(
const DDVectorType& gradient,
const DDVectorType& startPoint, DDVectorType& endPoint, ValueType stepsize)
267 std::transform(gradient.begin(),gradient.end(),endPoint.begin(),std::bind1st(std::multiplies<ValueType>(),stepsize));
268 std::transform(startPoint.begin(),startPoint.end(),endPoint.begin(),endPoint.begin(),std::plus<ValueType>());
271 template<
class GM,
class ACC>
272 template<
class VISITOR>
278 visitor.
addLog(
"primalLPbound");
279 visitor.
addLog(
"oracleCalls");
282 if (parent::_sumprodsolver.GetSmoothing()<=0.0)
285 parent::_maxsumsolver.ForwardMove();
286 parent::_maxsumsolver.EstimateIntegerLabelingAndBound();
287 parent::_SelectOptimalBoundsAndLabeling();
290 if (parent::_sumprodsolver.CheckDualityGap(parent::value(),parent::bound()))
292 #ifdef TRWS_DEBUG_OUTPUT
293 parent::_fout <<
"NesterovAcceleratedGradient::_CheckStoppingCondition(): Precision attained! Problem solved!"<<std::endl;
299 counter+=parent::_EstimateStartingSmoothing(visitor);
303 parent::_sumprodsolver.SetSmoothing(_parameters.startSmoothingValue());
306 DDVectorType gradient(_currentDualVector.size()),
307 lambda(_currentDualVector.size()),
308 y(_currentDualVector),
309 v(_currentDualVector);
310 DDVectorType w(_currentDualVector.size());
313 gamma= _parameters.gamma0_,
314 omega=_estimateOmega0();
318 for (
size_t i=0;i<_parameters.maxNumberOfIterations();++i)
320 #ifdef TRWS_DEBUG_OUTPUT
321 parent::_fout <<
"i="<<i<<std::endl;
324 ValueType doubledLipschitzConstant=2*getLipschitzConstant();
326 for (
size_t j=0;j<_parameters.numberOfInternalIterations();++j)
330 counter+=2; ValueType oldObjVal=_evaluateGradient(y,&gradient);
331 #ifdef TRWS_DEBUG_OUTPUT
332 parent::_fout <<
"Dual smooth objective ="<<oldObjVal<<std::endl;
335 switch (_parameters.gradientStep_)
337 case Parameter::ADAPTIVE_STEP:
339 ValueType norm2=std::inner_product(gradient.begin(),gradient.end(),gradient.begin(),(ValueType)0);
347 ACC::iop(-1.0,1.0,mul);
348 _GradientStep(gradient,y,lambda,mul/omega);
351 ++counter; newObjVal=_evaluateSmoothObjective(lambda);
353 while ( ACC::bop(newObjVal,(ValueType)(oldObjVal+mul*norm2/2.0/omega)) && (omega < doubledLipschitzConstant));
354 ++counter; parent::_sumprodsolver.GetMarginalsAndDerivativeMove();
356 if (omega >= doubledLipschitzConstant)
358 #ifdef TRWS_DEBUG_OUTPUT
359 parent::_fout <<
"Step size is smaller then the inverse Lipschitz constant. Passing to smoothing update." <<std::endl;
365 case Parameter::WC_STEP:
366 omega=doubledLipschitzConstant/2.0;
367 _GradientStep(gradient,y,lambda,mul/omega);
370 case Parameter::JOJIC_STEP:
371 omega=1.0/parent::_sumprodsolver.GetSmoothing();
372 _GradientStep(gradient,y,lambda,mul/omega);
375 std::runtime_error(
"NesterovAcceleratedGradient::infer():Error! Unknown value of the step size selector _parameters.gradientStep_.");
380 if (!_parameters.plainGradient_)
383 alpha=(sqrt(gamma*gamma+4*omega*gamma)-gamma)/omega/2.0;
387 std::transform(v.begin(),v.end(),gradient.begin(),v.begin(),std::plus<ValueType>());
391 std::transform(v.begin(),v.end(),w.begin(),std::bind1st(std::multiplies<ValueType>(),alpha));
392 std::transform(w.begin(),w.end(),lambda.begin(),y.begin(),std::plus<ValueType>());
395 std::copy(lambda.begin(),lambda.end(),y.begin());
400 parent::_maxsumsolver.ForwardMove();
401 parent::_maxsumsolver.EstimateIntegerLabelingAndBound();
403 #ifdef TRWS_DEBUG_OUTPUT
404 parent::_fout <<
"_maxsumsolver.bound()=" <<parent::_maxsumsolver.bound()<<
", _maxsumsolver.value()=" <<parent::_maxsumsolver.value() <<std::endl;
407 ValueType derivative=parent::_EstimateRhoDerivative();
408 #ifdef TRWS_DEBUG_OUTPUT
409 parent::_fout <<
"derivative="<<derivative<<std::endl;
413 if ( parent::_CheckStoppingCondition(&returncode))
417 visitor.
log(
"oracleCalls",(
double)counter);
418 visitor.
log(
"primalLPbound",(
double)parent::_bestPrimalLPbound);
423 size_t flag=visitor();
425 visitor.
log(
"oracleCalls",(
double)counter);
426 visitor.
log(
"primalLPbound",(
double)parent::_bestPrimalLPbound);
431 parent::_UpdateSmoothing(parent::_bestPrimalBound,parent::_maxsumsolver.bound(),parent::_sumprodsolver.bound(),derivative,i+1);
436 parent::_SelectOptimalBoundsAndLabeling();
438 visitor.
log(
"oracleCalls",(
double)counter);
439 visitor.
log(
"primalLPbound",(
double)parent::_bestPrimalLPbound);
parent::MaxSumSolverParametersType MaxSumSolverParametersType
GradientStepType gradientStep_
Nesterov_Parameter< GM > Parameter
const ValueType & precision() const
NesterovAcceleratedGradient(const GraphicalModelType &gm, const Parameter ¶m)
static std::string getString(GradientStepType steptype)
ValueType & smoothingDecayMultiplier()
parent::MaxSumSolver MaxSumSolver
visitors::VerboseVisitor< NesterovAcceleratedGradient< GM, ACC > > VerboseVisitorType
Storage::StructureType & decompositionType()
static GradientStepType getGradientStepType(const std::string &name)
SmoothingStrategyType & smoothingStrategy()
void log(const std::string &logName, double value)
bool & lazyLPPrimalBoundComputation()
parent::SumProdSolver SumProdSolver
visitors::EmptyVisitor< NesterovAcceleratedGradient< GM, ACC > > EmptyVisitorType
size_t & maxPrimalBoundIterationNumber()
parent::SumProdSolverParametersType SumProdSolverParametersType
trws_base::DecompositionStorage< GM > Storage
parent::PrimalBoundEstimator PrimalBoundEstimator
const bool & canonicalNormalization() const
parent::PrimalLPEstimatorParametersType PrimalLPEstimatorParametersType
ValueType & smoothingGapRatio()
InputIterator transform_inplace(InputIterator first, InputIterator last, UnaryOperator op)
size_t getDDVectorSize() const
parent::SmoothingStrategyType SmoothingStrategyType
const bool & fastComputations() const
InferenceTermination infer()
ValueType & presolveMinRelativeDualImprovement()
parent::SmoothingParametersType SmoothingParametersType
const ValueType & startSmoothingValue() const
Nesterov_Parameter(size_t numOfExternalIterations=0, ValueType precision=1.0, bool absolutePrecision=true, size_t numOfInternalIterations=3, typename Storage::StructureType decompositionType=Storage::GENERALSTRUCTURE, ValueType smoothingGapRatio=4, ValueType startSmoothingValue=0.0, ValueType primalBoundPrecision=std::numeric_limits< ValueType >::epsilon(), size_t maxPrimalBoundIterationNumber=100, size_t presolveMaxIterNumber=100, bool canonicalNormalization=true, ValueType presolveMinRelativeDualImprovement=0.01, bool lazyLPPrimalBoundComputation=true, ValueType smoothingDecayMultiplier=-1.0, SmoothingStrategyType smoothingStrategy=SmoothingParametersType::ADAPTIVE_DIMINISHING, bool fastComputations=true, bool verbose=false, GradientStepType gradientStep=ADAPTIVE_STEP, ValueType gamma0=1e6, bool plainGradient=false)
std::vector< typename GM::ValueType > DDVectorType
PrimalLPBound< GM, ACC > PrimalBoundEstimator
parent::PrimalLPEstimatorParametersType PrimalLPEstimatorParametersType
parent::SumProdSolverParametersType SumProdSolverParametersType
visitors::TimingVisitor< NesterovAcceleratedGradient< GM, ACC > > TimingVisitorType
trws_base::SmoothingBasedInference_Parameter< GM > parent
void addLog(const std::string &logName)
Storage::DDVectorType DDVectorType
trws_base::SmoothingBasedInference< GM, ACC > parent
static const size_t ContinueInf
parent::MaxSumSolverParametersType MaxSumSolverParametersType