2 #ifndef OPENGM_DUALDDECOMPOSITION_BUNDLE_HXX
3 #define OPENGM_DUALDDECOMPOSITION_BUNDLE_HXX
15 #ifdef WITH_CONICBUNDLE
16 #include <CBSolver.hxx>
27 template<
class GM,
class INF,
class DUALBLOCK >
28 class DualDecompositionBundle
29 :
public Inference<GM,typename INF::AccumulationType>,
30 public DualDecompositionBase<GM, DUALBLOCK>,
31 public ConicBundle::FunctionOracle
35 typedef GM GraphicalModelType;
36 typedef typename INF::AccumulationType AccumulationType;
38 typedef visitors::VerboseVisitor<DualDecompositionBundle<GM, INF,DUALBLOCK> > VerboseVisitorType;
39 typedef visitors::TimingVisitor<DualDecompositionBundle<GM, INF,DUALBLOCK> > TimingVisitorType;
40 typedef visitors::EmptyVisitor<DualDecompositionBundle<GM, INF,DUALBLOCK> > EmptyVisitorType;
42 typedef DUALBLOCK DualBlockType;
43 typedef typename DualBlockType::DualVariableType DualVariableType;
44 typedef DualDecompositionBase<GmType, DualBlockType> DDBaseType;
46 typedef typename DDBaseType::SubGmType SubGmType;
47 typedef typename DualBlockType::SubFactorType SubFactorType;
48 typedef typename DualBlockType::SubFactorListType SubFactorListType;
49 typedef typename DDBaseType::SubVariableType SubVariableType;
50 typedef typename DDBaseType::SubVariableListType SubVariableListType;
52 class Parameter :
public DualDecompositionBaseParameter{
55 double minimalRelAccuracy_;
57 typename InfType::Parameter subPara_;
59 double relativeDualBoundPrecision_;
61 size_t maxBundlesize_;
63 bool activeBoundFixing_;
65 double minDualWeight_;
67 double maxDualWeight_;
71 bool useHeuristicStepsize_;
74 : relativeDualBoundPrecision_(0.0),
76 activeBoundFixing_(
false),
80 useHeuristicStepsize_(
true)
84 using DualDecompositionBase<GmType, DualBlockType >::gm_;
85 using DualDecompositionBase<GmType, DualBlockType >::subGm_;
86 using DualDecompositionBase<GmType, DualBlockType >::dualBlocks_;
87 using DualDecompositionBase<GmType, DualBlockType >::numDualsOvercomplete_;
88 using DualDecompositionBase<GmType, DualBlockType >::numDualsMinimal_;
90 ~DualDecompositionBundle();
91 DualDecompositionBundle(
const GmType&);
92 DualDecompositionBundle(
const GmType&,
const Parameter&);
93 virtual std::string name()
const {
return "DualDecompositionSubGradient";};
94 virtual const GmType& graphicalModel()
const {
return gm_;};
96 template<
class VisitorType>
98 virtual ValueType bound()
const;
99 virtual ValueType value()
const;
101 virtual int evaluate(
const ConicBundle::DVector&,
double,
double&, ConicBundle::DVector&, std::vector<ConicBundle::DVector>&,
102 std::vector<ConicBundle::PrimalData*>&, ConicBundle::PrimalExtender*&);
105 virtual void allocate();
106 virtual DualDecompositionBaseParameter& parameter();
107 int dualStep(
const size_t iteration);
108 template <
class T_IndexType,
class T_LabelType>
109 void getPartialSubGradient(
const size_t,
const std::vector<T_IndexType>&, std::vector<T_LabelType>&)
const;
110 double euclideanSubGradientNorm();
113 std::vector<std::vector<LabelType> > subStates_;
114 ConicBundle::CBSolver* solver;
115 size_t nullStepCounter_;
117 Accumulation<ValueType,LabelType,AccumulationType> acUpperBound_;
118 Accumulation<ValueType,LabelType,AccumulationType> acNegLowerBound_;
119 ValueType upperBound_;
120 ValueType lowerBound_;
123 std::vector<ValueType> mem_;
124 std::vector<ValueType> mem2_;
134 template<
class GM,
class INF,
class DUALBLOCK>
135 DualDecompositionBundle<GM,INF,DUALBLOCK>::~DualDecompositionBundle()
140 template<
class GM,
class INF,
class DUALBLOCK>
141 DualDecompositionBundle<GM,INF,DUALBLOCK>::DualDecompositionBundle(
const GmType& gm)
142 : DualDecompositionBase<GmType, DualBlockType >(gm)
145 subStates_.resize(subGm_.size());
146 for(
size_t i=0; i<subGm_.size(); ++i)
147 subStates_[i].resize(subGm_[i].numberOfVariables());
149 solver =
new ConicBundle::CBSolver(para_.noBundle_);
151 solver->init_problem(numDualsMinimal_);
152 solver->add_function(*
this);
153 solver->set_out(&std::cout,0);
155 solver->set_max_bundlesize(*
this,para_.maxBundlesize_);
158 solver->set_active_bounds_fixing(para_.activeBoundFixing_);
159 solver->set_term_relprec(para_.relativeDualBoundPrecision_);
160 solver->set_min_weight(para_.minDualWeight_);
161 solver->set_max_weight(para_.maxDualWeight_);
165 template<
class GM,
class INF,
class DUALBLOCK>
166 DualDecompositionBundle<GM,INF,DUALBLOCK>::DualDecompositionBundle(
const GmType& gm,
const Parameter& para)
167 : DualDecompositionBase<GmType, DualBlockType >(gm)
172 subStates_.resize(subGm_.size());
173 for(
size_t i=0; i<subGm_.size(); ++i)
174 subStates_[i].resize(subGm_[i].numberOfVariables());
176 solver =
new ConicBundle::CBSolver(para_.noBundle_);
178 solver->init_problem(numDualsMinimal_);
179 solver->add_function(*
this);
180 solver->set_out(&std::cout,0);
181 solver->set_max_bundlesize(*
this,para_.maxBundlesize_);
184 solver->set_active_bounds_fixing(para.activeBoundFixing_);
185 solver->set_term_relprec(para_.relativeDualBoundPrecision_);
186 solver->set_min_weight(para_.minDualWeight_);
187 solver->set_max_weight(para_.maxDualWeight_);
194 template <
class GM,
class INF,
class DUALBLOCK>
195 void DualDecompositionBundle<GM,INF,DUALBLOCK>::allocate()
197 mem_.resize(numDualsOvercomplete_,0);
198 mem2_.resize(numDualsOvercomplete_,0);
199 ValueType *data1Front = &mem_[0];
200 ValueType *data1Back = &mem_[numDualsOvercomplete_];
201 ValueType *data2Front = &mem2_[0];
202 ValueType *data2Back = &mem2_[numDualsOvercomplete_];
203 for(
typename std::vector<DualBlockType>::iterator it=dualBlocks_.begin(); it!=dualBlocks_.end(); ++it){
204 for(
size_t i=0; i<(*it).duals_.size(); ++i){
205 DualVariableType& dv1 = (*it).duals_[i];
206 DualVariableType& dv2 = (*it).duals2_[i];
207 if(i+1==(*it).duals_.size()){
208 data1Back -= dv1.size();
209 data2Back -= dv2.size();
210 dv1.assign( dv1.shapeBegin(),dv1.shapeEnd(),data1Back);
211 dv2.assign( dv2.shapeBegin(),dv2.shapeEnd(),data2Back);
214 dv1.assign( dv1.shapeBegin(),dv1.shapeEnd(),data1Front);
215 dv2.assign( dv2.shapeBegin(),dv2.shapeEnd(),data2Front);
216 data1Front += dv1.size();
217 data2Front += dv2.size();
227 template <
class GM,
class INF,
class DUALBLOCK>
228 DualDecompositionBaseParameter& DualDecompositionBundle<GM,INF,DUALBLOCK>::parameter()
235 template<
class GM,
class INF,
class DUALBLOCK>
239 EmptyVisitorType visitor;
240 return infer(visitor);
243 template<
class GM,
class INF,
class DUALBLOCK>
244 template<
class VisitorType>
246 infer(VisitorType& visitor)
248 std::cout.precision(15);
249 visitor.begin(*
this);
250 for(
size_t iteration=0; iteration<para_.maximalNumberOfIterations_; ++iteration){
254 if(dualBlocks_.size() == 0){
256 for(
size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
257 InfType inf(subGm_[subModelId],para_.subPara_);
259 inf.arg(subStates_[subModelId]);
263 std::vector<LabelType> temp;
264 std::vector<LabelType> temp2;
265 const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
266 (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
267 acNegLowerBound_(-lowerBound_,temp2);
268 acUpperBound_(upperBound_, temp);
272 ret = dualStep(iteration);
276 std::cout.precision(15);
277 if(visitor(*
this)!=0){
288 AccumulationType::iop(0.0001,-0.0001,o);
289 OPENGM_ASSERT(AccumulationType::bop(lowerBound_, upperBound_+o));
290 OPENGM_ASSERT(AccumulationType::bop(-acNegLowerBound_.value(), acUpperBound_.value()+o));
292 if( fabs(acUpperBound_.value() + acNegLowerBound_.value()) <= para_.minimalAbsAccuracy_
293 || fabs((acUpperBound_.value()+ acNegLowerBound_.value())/acUpperBound_.value()) <= para_.minimalRelAccuracy_
306 template<
class GM,
class INF,
class DUALBLOCK>
308 arg(std::vector<LabelType>& conf,
const size_t n)
const
314 acUpperBound_.state(conf);
319 template<
class GM,
class INF,
class DUALBLOCK>
320 typename GM::ValueType DualDecompositionBundle<GM,INF,DUALBLOCK>::value()
const
322 return acUpperBound_.value();
325 template<
class GM,
class INF,
class DUALBLOCK>
326 typename GM::ValueType DualDecompositionBundle<GM,INF,DUALBLOCK>::bound()
const
328 return -acNegLowerBound_.value();
334 template <
class GM,
class INF,
class DUALBLOCK>
335 int DualDecompositionBundle<GM,INF,DUALBLOCK>::dualStep(
const size_t iteration)
338 if(para_.useHeuristicStepsize_){
339 solver->set_min_weight(para_.minDualWeight_);
340 solver->set_max_weight(para_.maxDualWeight_);
342 else if(iteration == 0){
343 solver->set_min_weight(100);
344 solver->set_max_weight(100);
347 if(solver->get_objval() == solver->get_candidate_value() || iteration==1){
349 double primalDualGap = fabs(acUpperBound_.value() + acNegLowerBound_.value());
351 double subgradientNorm = (*this).euclideanSubGradientNorm();
352 double stepsize = (primalDualGap)/subgradientNorm * para_.stepsizeStride_;
354 if(para_.minDualWeight_>=0)
355 stepsize = std::min(1/para_.minDualWeight_, stepsize);
356 if(para_.maxDualWeight_>=0)
357 stepsize = std::max(1/para_.maxDualWeight_, stepsize);
359 double t = 1/stepsize;
360 solver->set_next_weight(t);
361 solver->set_min_weight(t);
362 solver->set_max_weight(t);
371 retval=solver->do_descent_step(1);
374 std::cout<<
"descent_step returned "<<retval<<std::endl;
377 return solver->termination_code();
380 template <
class GM,
class INF,
class DUALBLOCK>
381 int DualDecompositionBundle<GM,INF,DUALBLOCK>::evaluate
383 const ConicBundle::DVector& dual,
385 double& objective_value,
386 ConicBundle::DVector& cut_vals,
387 std::vector<ConicBundle::DVector>& subgradients,
388 std::vector<ConicBundle::PrimalData*>& primal_solutions,
389 ConicBundle::PrimalExtender*& primal_extender
392 typename std::vector<DualBlockType>::iterator it;
393 typename SubFactorListType::const_iterator lit;
395 for(
size_t i=0; i<numDualsMinimal_; ++i){
398 for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
399 const size_t numDuals = (*it).duals_.size();
400 (*it).duals_[numDuals-1] = -(*it).duals_[0];
401 for(
size_t i=1; i<numDuals-1;++i){
402 (*it).duals_[numDuals-1] -= (*it).duals_[i];
413 for(
size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
414 InfType inf(subGm_[subModelId],para_.subPara_);
416 inf.arg(subStates_[subModelId]);
419 primalTime_ += primalTimer_.elapsedTime();
422 std::vector<LabelType> temp;
423 std::vector<LabelType> temp2;
424 const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
425 (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
426 acNegLowerBound_(-lowerBound_,temp2);
427 acUpperBound_(upperBound_, temp);
428 objective_value = -lowerBound_;
431 std::vector<size_t> s;
432 mem2_.assign(mem2_.size(),0);
433 for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
434 const size_t numDuals = (*it).duals_.size();
435 lit = (*((*it).subFactorList_)).begin();
436 s.resize((*lit).subIndices_.size());
437 for(
size_t i=0; i<numDuals; ++i){
438 getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s);
440 (*it).duals2_[i](s.begin()) += -1.0;
442 for(
size_t i=0; i<numDuals-1; ++i){
443 (*it).duals2_[i] -= (*it).duals2_[numDuals-1] ;
448 ConicBundle::PrimalDVector h(numDualsMinimal_,0);
449 cut_vals.push_back(objective_value);
450 for(
size_t i=0; i<numDualsMinimal_; ++i){
453 subgradients.push_back(h);
460 template <
class GM,
class INF,
class DUALBLOCK>
461 template <
class T_IndexType,
class T_LabelType>
462 inline void DualDecompositionBundle<GM,INF,DUALBLOCK>::getPartialSubGradient
464 const size_t subModelId,
465 const std::vector<T_IndexType>& subIndices,
466 std::vector<T_LabelType> & s
470 for(
size_t n=0; n<s.size(); ++n){
471 s[n] = subStates_[subModelId][subIndices[n]];
475 template <
class GM,
class INF,
class DUALBLOCK>
476 double DualDecompositionBundle<GM,INF,DUALBLOCK>::euclideanSubGradientNorm()
479 std::vector<size_t> s,s2;
480 typename std::vector<DUALBLOCK>::const_iterator it;
481 typename SubFactorListType::const_iterator lit;
482 for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
483 const size_t numDuals = (*it).duals_.size();
484 const SubFactorType& sf = (*((*it).subFactorList_)).back();
485 lit = (*((*it).subFactorList_)).begin();
486 s.resize((*lit).subIndices_.size());
487 s2.resize((*lit).subIndices_.size());
488 getPartialSubGradient(sf.subModelId_, sf.subIndices_, s2);
489 for(
size_t i=0; i<numDuals-1; ++i){
490 getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s);
502 #endif // WITH_CONICBUNDLE
Platform-independent runtime measurements.
#define OPENGM_ASSERT(expression)
#define OPENGM_GM_TYPE_TYPEDEFS