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;
55 typedef typename INF:: template RebindGm<_GM>::type RebindedInf;
56 typedef DualDecompositionBundle<_GM, RebindedInf, DUALBLOCK> type;
59 template<
class _GM,
class _ACC>
60 struct RebindGmAndAcc{
61 typedef typename INF:: template RebindGm<_GM,_ACC>::type RebindedInf;
62 typedef DualDecompositionBundle<_GM, RebindedInf, DUALBLOCK> type;
66 class Parameter :
public DualDecompositionBaseParameter{
69 double minimalRelAccuracy_;
71 typename InfType::Parameter subPara_;
73 double relativeDualBoundPrecision_;
75 size_t maxBundlesize_;
77 bool activeBoundFixing_;
79 double minDualWeight_;
81 double maxDualWeight_;
85 bool useHeuristicStepsize_;
88 : relativeDualBoundPrecision_(0.0),
90 activeBoundFixing_(
false),
94 useHeuristicStepsize_(
true)
98 Parameter(
const P & p)
100 minimalRelAccuracy_(p.minimalRelAccuracy_),
102 relativeDualBoundPrecision_(p.relativeDualBoundPrecision_),
103 maxBundlesize_(p.maxBundlesize_),
104 activeBoundFixing_(p.activeBoundFixing_),
105 minDualWeight_(p.minDualWeight_),
106 maxDualWeight_(p.maxDualWeight_),
107 noBundle_(p.noBundle_),
108 useHeuristicStepsize_(p.useHeuristicStepsize_){
118 ~DualDecompositionBundle();
119 DualDecompositionBundle(
const GmType&);
120 DualDecompositionBundle(
const GmType&,
const Parameter&);
121 virtual std::string name()
const {
return "DualDecompositionSubGradient";};
122 virtual const GmType& graphicalModel()
const {
return gm_;};
124 template<
class VisitorType>
126 virtual ValueType bound()
const;
127 virtual ValueType value()
const;
129 virtual int evaluate(
const ConicBundle::DVector&,
double,
double&, ConicBundle::DVector&, std::vector<ConicBundle::DVector>&,
130 std::vector<ConicBundle::PrimalData*>&, ConicBundle::PrimalExtender*&);
133 virtual void allocate();
134 virtual DualDecompositionBaseParameter& parameter();
135 int dualStep(
const size_t iteration);
136 template <
class T_IndexType,
class T_LabelType>
137 void getPartialSubGradient(
const size_t,
const std::vector<T_IndexType>&, std::vector<T_LabelType>&)
const;
138 double euclideanSubGradientNorm();
141 std::vector<std::vector<LabelType> > subStates_;
142 ConicBundle::CBSolver* solver;
143 size_t nullStepCounter_;
145 Accumulation<ValueType,LabelType,AccumulationType> acUpperBound_;
146 Accumulation<ValueType,LabelType,AccumulationType> acNegLowerBound_;
147 ValueType upperBound_;
148 ValueType lowerBound_;
151 std::vector<ValueType> mem_;
152 std::vector<ValueType> mem2_;
162 template<
class GM,
class INF,
class DUALBLOCK>
163 DualDecompositionBundle<GM,INF,DUALBLOCK>::~DualDecompositionBundle()
168 template<
class GM,
class INF,
class DUALBLOCK>
169 DualDecompositionBundle<GM,INF,DUALBLOCK>::DualDecompositionBundle(
const GmType& gm)
170 : DualDecompositionBase<GmType, DualBlockType >(gm)
173 subStates_.resize(subGm_.size());
174 for(
size_t i=0; i<subGm_.size(); ++i)
175 subStates_[i].resize(subGm_[i].numberOfVariables());
177 solver =
new ConicBundle::CBSolver(para_.noBundle_);
179 solver->init_problem(numDualsMinimal_);
180 solver->add_function(*
this);
181 solver->set_out(&std::cout,0);
183 solver->set_max_bundlesize(*
this,para_.maxBundlesize_);
186 solver->set_active_bounds_fixing(para_.activeBoundFixing_);
187 solver->set_term_relprec(para_.relativeDualBoundPrecision_);
188 solver->set_min_weight(para_.minDualWeight_);
189 solver->set_max_weight(para_.maxDualWeight_);
193 template<
class GM,
class INF,
class DUALBLOCK>
194 DualDecompositionBundle<GM,INF,DUALBLOCK>::DualDecompositionBundle(
const GmType& gm,
const Parameter& para)
195 : DualDecompositionBase<GmType, DualBlockType >(gm)
200 subStates_.resize(subGm_.size());
201 for(
size_t i=0; i<subGm_.size(); ++i)
202 subStates_[i].resize(subGm_[i].numberOfVariables());
204 solver =
new ConicBundle::CBSolver(para_.noBundle_);
206 solver->init_problem(numDualsMinimal_);
207 solver->add_function(*
this);
208 solver->set_out(&std::cout,0);
209 solver->set_max_bundlesize(*
this,para_.maxBundlesize_);
212 solver->set_active_bounds_fixing(para.activeBoundFixing_);
213 solver->set_term_relprec(para_.relativeDualBoundPrecision_);
214 solver->set_min_weight(para_.minDualWeight_);
215 solver->set_max_weight(para_.maxDualWeight_);
222 template <
class GM,
class INF,
class DUALBLOCK>
223 void DualDecompositionBundle<GM,INF,DUALBLOCK>::allocate()
225 mem_.resize(numDualsOvercomplete_,0);
226 mem2_.resize(numDualsOvercomplete_,0);
227 ValueType *data1Front = &mem_[0];
228 ValueType *data1Back = &mem_[numDualsOvercomplete_];
229 ValueType *data2Front = &mem2_[0];
230 ValueType *data2Back = &mem2_[numDualsOvercomplete_];
231 for(
typename std::vector<DualBlockType>::iterator it=dualBlocks_.begin(); it!=dualBlocks_.end(); ++it){
232 for(
size_t i=0; i<(*it).duals_.size(); ++i){
233 DualVariableType& dv1 = (*it).duals_[i];
234 DualVariableType& dv2 = (*it).duals2_[i];
235 if(i+1==(*it).duals_.size()){
236 data1Back -= dv1.size();
237 data2Back -= dv2.size();
238 dv1.assign( dv1.shapeBegin(),dv1.shapeEnd(),data1Back);
239 dv2.assign( dv2.shapeBegin(),dv2.shapeEnd(),data2Back);
242 dv1.assign( dv1.shapeBegin(),dv1.shapeEnd(),data1Front);
243 dv2.assign( dv2.shapeBegin(),dv2.shapeEnd(),data2Front);
244 data1Front += dv1.size();
245 data2Front += dv2.size();
255 template <
class GM,
class INF,
class DUALBLOCK>
256 DualDecompositionBaseParameter& DualDecompositionBundle<GM,INF,DUALBLOCK>::parameter()
263 template<
class GM,
class INF,
class DUALBLOCK>
267 EmptyVisitorType visitor;
268 return infer(visitor);
271 template<
class GM,
class INF,
class DUALBLOCK>
272 template<
class VisitorType>
274 infer(VisitorType& visitor)
276 std::cout.precision(15);
277 visitor.begin(*
this);
278 for(
size_t iteration=0; iteration<para_.maximalNumberOfIterations_; ++iteration){
282 if(dualBlocks_.size() == 0){
284 for(
size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
285 InfType inf(subGm_[subModelId],para_.subPara_);
287 inf.arg(subStates_[subModelId]);
291 std::vector<LabelType> temp;
292 std::vector<LabelType> temp2;
293 const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
294 (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
295 acNegLowerBound_(-lowerBound_,temp2);
296 acUpperBound_(upperBound_, temp);
300 ret = dualStep(iteration);
304 std::cout.precision(15);
305 if(visitor(*
this)!=0){
316 AccumulationType::iop(0.0001,-0.0001,o);
317 OPENGM_ASSERT(AccumulationType::bop(lowerBound_, upperBound_+o));
318 OPENGM_ASSERT(AccumulationType::bop(-acNegLowerBound_.value(), acUpperBound_.value()+o));
320 if( fabs(acUpperBound_.value() + acNegLowerBound_.value()) <= para_.minimalAbsAccuracy_
321 || fabs((acUpperBound_.value()+ acNegLowerBound_.value())/acUpperBound_.value()) <= para_.minimalRelAccuracy_
334 template<
class GM,
class INF,
class DUALBLOCK>
336 arg(std::vector<LabelType>& conf,
const size_t n)
const 342 acUpperBound_.state(conf);
347 template<
class GM,
class INF,
class DUALBLOCK>
348 typename GM::ValueType DualDecompositionBundle<GM,INF,DUALBLOCK>::value()
const 350 return acUpperBound_.value();
353 template<
class GM,
class INF,
class DUALBLOCK>
354 typename GM::ValueType DualDecompositionBundle<GM,INF,DUALBLOCK>::bound()
const 356 return -acNegLowerBound_.value();
362 template <
class GM,
class INF,
class DUALBLOCK>
363 int DualDecompositionBundle<GM,INF,DUALBLOCK>::dualStep(
const size_t iteration)
366 if(para_.useHeuristicStepsize_){
367 solver->set_min_weight(para_.minDualWeight_);
368 solver->set_max_weight(para_.maxDualWeight_);
370 else if(iteration == 0){
371 solver->set_min_weight(100);
372 solver->set_max_weight(100);
375 if(solver->get_objval() == solver->get_candidate_value() || iteration==1){
377 double primalDualGap = fabs(acUpperBound_.value() + acNegLowerBound_.value());
379 double subgradientNorm = (*this).euclideanSubGradientNorm();
380 double stepsize = (primalDualGap)/subgradientNorm * para_.stepsizeStride_;
382 if(para_.minDualWeight_>=0)
383 stepsize = std::min(1/para_.minDualWeight_, stepsize);
384 if(para_.maxDualWeight_>=0)
385 stepsize = std::max(1/para_.maxDualWeight_, stepsize);
387 double t = 1/stepsize;
388 solver->set_next_weight(t);
389 solver->set_min_weight(t);
390 solver->set_max_weight(t);
399 retval=solver->do_descent_step(1);
402 std::cout<<
"descent_step returned "<<retval<<std::endl;
405 return solver->termination_code();
408 template <
class GM,
class INF,
class DUALBLOCK>
409 int DualDecompositionBundle<GM,INF,DUALBLOCK>::evaluate
411 const ConicBundle::DVector& dual,
413 double& objective_value,
414 ConicBundle::DVector& cut_vals,
415 std::vector<ConicBundle::DVector>& subgradients,
416 std::vector<ConicBundle::PrimalData*>& primal_solutions,
417 ConicBundle::PrimalExtender*& primal_extender
420 typename std::vector<DualBlockType>::iterator it;
421 typename SubFactorListType::const_iterator lit;
423 for(
size_t i=0; i<numDualsMinimal_; ++i){
426 for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
427 const size_t numDuals = (*it).duals_.size();
428 (*it).duals_[numDuals-1] = -(*it).duals_[0];
429 for(
size_t i=1; i<numDuals-1;++i){
430 (*it).duals_[numDuals-1] -= (*it).duals_[i];
441 for(
size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
442 InfType inf(subGm_[subModelId],para_.subPara_);
444 inf.arg(subStates_[subModelId]);
447 primalTime_ += primalTimer_.elapsedTime();
450 std::vector<LabelType> temp;
451 std::vector<LabelType> temp2;
452 const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
453 (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
454 acNegLowerBound_(-lowerBound_,temp2);
455 acUpperBound_(upperBound_, temp);
456 objective_value = -lowerBound_;
459 std::vector<size_t> s;
460 mem2_.assign(mem2_.size(),0);
461 for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
462 const size_t numDuals = (*it).duals_.size();
463 lit = (*((*it).subFactorList_)).begin();
464 s.resize((*lit).subIndices_.size());
465 for(
size_t i=0; i<numDuals; ++i){
466 getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s);
468 (*it).duals2_[i](s.begin()) += -1.0;
470 for(
size_t i=0; i<numDuals-1; ++i){
471 (*it).duals2_[i] -= (*it).duals2_[numDuals-1] ;
476 ConicBundle::PrimalDVector h(numDualsMinimal_,0);
477 cut_vals.push_back(objective_value);
478 for(
size_t i=0; i<numDualsMinimal_; ++i){
481 subgradients.push_back(h);
488 template <
class GM,
class INF,
class DUALBLOCK>
489 template <
class T_IndexType,
class T_LabelType>
490 inline void DualDecompositionBundle<GM,INF,DUALBLOCK>::getPartialSubGradient
492 const size_t subModelId,
493 const std::vector<T_IndexType>& subIndices,
494 std::vector<T_LabelType> & s
498 for(
size_t n=0; n<s.size(); ++n){
499 s[n] = subStates_[subModelId][subIndices[n]];
503 template <
class GM,
class INF,
class DUALBLOCK>
504 double DualDecompositionBundle<GM,INF,DUALBLOCK>::euclideanSubGradientNorm()
507 std::vector<size_t> s,s2;
508 typename std::vector<DUALBLOCK>::const_iterator it;
509 typename SubFactorListType::const_iterator lit;
510 for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
511 const size_t numDuals = (*it).duals_.size();
512 const SubFactorType& sf = (*((*it).subFactorList_)).back();
513 lit = (*((*it).subFactorList_)).begin();
514 s.resize((*lit).subIndices_.size());
515 s2.resize((*lit).subIndices_.size());
516 getPartialSubGradient(sf.subModelId_, sf.subIndices_, s2);
517 for(
size_t i=0; i<numDuals-1; ++i){
518 getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s);
530 #endif // WITH_CONICBUNDLE
std::vector< DualBlockType > dualBlocks_
void infer(const typename INF::GraphicalModelType &gm, const typename INF::Parameter ¶m, std::vector< typename INF::LabelType > &conf)
size_t numDualsOvercomplete_
Platform-independent runtime measurements.
#define OPENGM_ASSERT(expression)
std::vector< SubGmType > subGm_
#define OPENGM_GM_TYPE_TYPEDEFS