OpenGM  2.3.x
Discrete Graphical Model Library
high_level_fusion_mover.hxx
Go to the documentation of this file.
1 
2 
3 template<class T>
4 struct MaybeSetValue{
5  T val_;
6  bool isSet_;
7 
8 };
9 
10 
11 
12 template<class INDEX_TYPE>
14 public:
15  IntegralUnorderedMaxSizeSet(const size_t maxIndex)
16  : maxSize_(maxIndex+1),
17  indexInSet_(maxIndex+1,0),
18  setSize_(0){
19  }
20 
21 
22  typedef INDEX_TYPE IndexType;
23  void insert(const IndexType index){
24  if(indexInSet_[index]==0){
25  setElements_[setSize_]=index;
26  indexInSet_[index]=1;
27  }
28  }
29  bool hasIndex()const{
30  return indexInSet_[index]!=0;
31  }
32 
33  void removeAll()const{
34  for(size_t i=0;i<setSize_;++i){
35  indexInSet_[setElements_[i]]=0;
36  }
37  }
38 
39 private:
40  std::vector<unsigned char> indexInSet_;
41  std::vector<INDEX_TYPE > setElements_;
42  size_t setSize_;
43 };
44 
45 
46 
47 
48 
49 template<class GM,class ACC>
50 class HighLevelFusionMover{
51 public:
52  typedef ACC AccumulationType;
53  typedef GM GmType;
54  typedef GM GraphicalModelType;
55  typedef INF InfType;
56  typedef double QpboValueType
58 
59 
60  // function types
61  typedef detail_fusion::ViewFixVariablesFunction<GM> FixFunction;
62  typedef detail_fusion::FuseViewFunction<GM> FuseViewingFunction;
63  typedef detail_fusion::FuseViewFixFunction<GM> FuseViewingFixingFunction;
64  typedef ExplicitFunction<ValueType, IndexType, LabelType> ArrayFunction;
65 
66 
67 
68 
69  #ifdef WITH_QPBO
70  typedef kolmogorov::qpbo::QPBO<QpboValueType> QpboType;
71  #endif
72 
73 
74  typedef std::vector<LabelType> StateVector;
75 
76 
77  enum FusionSolver{
78  QpboFusionSolver,
79  CplexFusionSolver,
80  BpFusionSolver,
81  Ad3FusionSolver,
82  LfFusionSolver,
83  DefaultFusionSolver
84  };
85 
86 
87  struct ReductionParameter
88  {
89  public:
90  bool Persistency_;
91  bool Tentacle_;
92  bool ConnectedComponents_;
93  Parameter(
94  const bool Persistency=false,
95  const bool Tentacle=false,
96  const bool ConnectedComponents=true
97  ),
98  :
99  Persistency_ (Persistency),
100  Tentacle_ (Tentacle),
101  ConnectedComponents_ (ConnectedComponents)
102  {
103  };
104  };
105 
106 
107  struct FusionSolverParam{
108  FusionSolverParam(
109  const size_t subgraphSize=3,
110  const size_t steps=0,
111  const double damping=0.75
112  )
113  :
114  subgraphSize_(subgraphSize),
115  steps_(steps),
116  damping_(damping)
117  {
118  size_t subgraphSize_;
119  size_t steps_;
120  double damping_;
121  };
122 
123 
124  enum UnknownStateBehavior{
125  TakeA,
126  TakeB,
127  TakeBest,
128  Random
129  };
130 
131 
132 
133  struct Parameter{
134  Parameter(
135  const FusionSolver fusionSolver = DefaultFusionSolver,
136  const bool useReduction = true,
137  const ReductionParameter & reductionParameter = ReductionParameter(),
138  const UnknownStateBehavior unknownStateBehavior = TakeA
139  )
140  : fusionSolver_(fusionSolver),
141  useReduction_(useReduction),
142  reductionParameter_(reductionParameter),
143  unknownStateBehavior_(unknownStateBehavior){
144  }
145 
146  FusionSolver fusionSolver_;
147  bool useReduction_;
148  ReductionParameter reductionParameter_;
149  UnknownStateBehavior unknownStateBehavior_;
150  };
151 
152 
153  struct FusionMoveResult{
154  bool changeOrImprovement_;
155 
156  };
157 
158  HighLevelFusionMover(const GM & gm,const Parameter & parameter)
159  : gm_(gm),
160  parameter_(parameter){
161 
162  this->setUpParameter();
163 
164  }
165 
166 
167  FusionMoveResult fuse(
168  const StateVector & proposalLabelsA,
169  const StateVector & proposalLabelsB,
170  StateVector & resultLabels
171  ){
172  // mapping from local <=> global vi
173  this->getForwardBackwardMapping(proposalLabelsA,proposalLabelsB);
174 
175  return fuse2Impl(proposalLabelsA,proposalLabelsB,resultLabels);
176  }
177 
178  // fuse inplace
179  FusionMoveResult fuse(
180  const StateVector & proposalLabelsA,
181  StateVector & proposalLabelsBAndResult,
182  ){
183  // mapping from local <=> global vi
184  this->getForwardBackwardMapping(proposalLabelsA,proposalLabelsB);
185 
186  return fuse2Impl(proposalLabelsA,proposalLabelsBAndResult,proposalLabelsBAndResult);
187  }
188 
189  // fuse vector
190  template<class PROPOSAL_LABEL_ITERATOR>
191  FusionMoveResult fuse(
192  PROPOSAL_LABEL_ITERATOR proposalLabelsBegin,
193  PROPOSAL_LABEL_ITERATOR proposalLabelsEnd,
194  StateVector & resultLabels
195  ){
196  //
197  raise RuntimeError("not yet implemented");
198  }
199 
200 private:
201  template<class PROPOSAL_LABELS_A,class PROPOSAL_LABELS_B>
202  void getForwardBackwardMapping(
203  const PROPOSAL_LABELS_A & proposalLabelsA,
204  const PROPOSAL_LABELS_B & proposalLabelsB
205  ){
206  nLocalVar_ = 0;
207  for (IndexType vi = 0; vi < gm_.numberOfVariables(); ++vi)
208  {
209  if (proposalLabelsA[vi] != proposalLabelsB[vi])
210  {
211  localToGlobalVi_[nLocalVar_] = vi;
212  globalToLocalVi_[vi] = nLocalVar_;
213  ++nLocalVar_;
214  }
215  }
216  }
217 
218  template<class PROPOSAL_LABELS_A,class PROPOSAL_LABELS_B,class MODEL_PROXY>
219  void setupSubmodelProxy(
220  const PROPOSAL_LABELS_A & proposalLabelsA,
221  const PROPOSAL_LABELS_B & proposalLabelsB
222  MODEL_PROXY & modelProxy
223  )
224  {
225  for (IndexType lvi = 0; lvi < nLocalVar_; ++lvi)
226  {
227  const IndexType fi = gm_.factorOfVariable(vi, f);
228  const IndexType fOrder = gm_.numberOfVariables(fi);
229 
230  // first order
231  if (fOrder == 1)
232  {
233  OPENGM_CHECK_OP( localToGlobalVi_[lvi], == , gm_[fi].variableIndex(0), "internal error");
234  OPENGM_CHECK_OP( globalToLocalVi_[gm_[fi].variableIndex(0)], == , lvi, "internal error");
235 
236  const IndexType vis[] = {lvi};
237  const IndexType globalVi = localToGlobalVi_[lvi];
238 
239  // preallocate me!!!
240  const float aTwo=2;
241  ArrayFunction f(&aTwo,&aTwo+1);
242  const LabelType c[] = { proposalLabelsA[globalVi],proposalLabelsB[globalVi]};
243  f(0) = gm_[fi](c );
244  f(1) = gm_[fi](c + 1);
245  modelProxy.addFactor(f, vis, vis + 1);
246  }
247  // high order
248  else if ( addedFactors_.hasIndex(fi) == false )
249  {
250  addedFactors_.insert(fi);
251  IndexType fixedVar = 0;
252  IndexType notFixedVar = 0;
253 
254  for (IndexType vf = 0; vf < fOrder; ++vf)
255  {
256  const IndexType viFactor = gm_[fi].variableIndex(vf);
257  if (proposalLabelsA[viFactor] != proposalLabelsB[viFactor])
258  notFixedVar += 1;
259  else
260  fixedVar += 1;
261  }
262  OPENGM_CHECK_OP(notFixedVar, > , 0, "internal error");
263 
264  if (fixedVar == 0)
265  {
266  OPENGM_CHECK_OP(notFixedVar, == , fOrder, "interal error");
267  // preallocate me
268  std::vector<IndexType> lvis(fOrder);
269  for (IndexType vf = 0; vf < fOrder; ++vf)
270  lvis[vf] = globalToLocalVi_[gm_[fi].variableIndex(vf)];
271 
272  FuseViewingFunction f(gm_[fi], *argA_, *argB_);
273  modelProxy.addFactor(f, lvis.begin(), lvis.end());
274  }
275  else
276  {
277  OPENGM_CHECK_OP(notFixedVar + fixedVar, == , fOrder, "interal error")
278 
279  // get local vis
280  std::vector<IndexType> lvis;
281  lvis.reserve(notFixedVar);
282  for (IndexType vf = 0; vf < fOrder; ++vf)
283  {
284  const IndexType gvi = gm_[fi].variableIndex(vf);
285  if ( proposalLabelsA[gvi] != proposalLabelsB[gvi])
286  lvis.push_back(globalToLocalVi_[gvi]);
287  }
288  OPENGM_CHECK_OP(lvis.size(), == , notFixedVar, "internal error");
289  FuseViewingFixingFunction f(gm_[fi], *argA_, *argB_);
290  modelProxy.addFactor(f, lvis.begin(), lvis.end());
291  }
292  }
293  }
294  addedFactors_.removeAll();
295  }
296 
297  template<class PROPOSAL_LABELS_A,class PROPOSAL_LABELS_B,class PROPOSAL_LABELS_RESULT>
298  FusionMoveResult fuse2Impl(
299  const PROPOSAL_LABELS_A & proposalLabelsA,
300  const PROPOSAL_LABELS_B & proposalLabelsB,
301  PROPOSAL_LABELS_RESULT & proposalLabelsResult
302  ){
303 
304 
305 
306  // do the basic fusion
307  if(param_.fusionSolver_==QpboFusionSolver)
308  return this->fuse2Qpbo(proposalLabelsA,proposalLabelsB,proposalLabelsResult);
309 
310  // do some kind of improvement?
311 
312  }
313 
314  template<class PROPOSAL_LABELS_A,class PROPOSAL_LABELS_B,class PROPOSAL_LABELS_RESULT>
315  FusionMoveResult fuse2Qpbo(
316  const PROPOSAL_LABELS_A & proposalLabelsA,
317  const PROPOSAL_LABELS_B & proposalLabelsB,
318  PROPOSAL_LABELS_RESULT & proposalLabelsResult
319  ){
320  if(maxFactorOrder_<=2)
321  return this->fuse2QpboImproment2Order(proposalLabelsA,proposalLabelsB,proposalLabelsResult);
322  else
323  return this->fuse2QpboAnyOrder(proposalLabelsA,proposalLabelsB,proposalLabelsResult);
324  }
325 
326  template<class PROPOSAL_LABELS_A,class PROPOSAL_LABELS_B,class PROPOSAL_LABELS_RESULT>
327  FusionMoveResult fuse2Native(
328  const PROPOSAL_LABELS_A & proposalLabelsA,
329  const PROPOSAL_LABELS_B & proposalLabelsB,
330  PROPOSAL_LABELS_RESULT & proposalLabelsResult
331  ){
332 
333  }
334 
335  template<class PROPOSAL_LABELS_A,class PROPOSAL_LABELS_B,class PROPOSAL_LABELS_RESULT>
336  FusionMoveResult fuse2QpboImproment2Order(
337  const PROPOSAL_LABELS_A & proposalLabelsA,
338  const PROPOSAL_LABELS_B & proposalLabelsB,
339  PROPOSAL_LABELS_RESULT & proposalLabelsResult
340  ){
341 
342  #ifdef WITH_QPBO
343  // set up qpbo problem
344  setupSubmodelProxy(proposalLabelsA,proposalLabelsB,qpboModelProxy_);
345 
346  // solve qpbo with improvement
347  srand( 42 );
348  qpboModelProxy_.model_->Improve();
349 
350  // get result arg
351  if(param_.unknownStateBehavior_==TakeA || param_.unknownStateBehavior_==TakeB){
352  for (IndexType lvi = 0; lvi < nLocalVar_; ++lvi)
353  {
354  const IndexType globalVi = localToGlobalVi_[lvi];
355  const LabelType l = modelProxy.model_->GetLabel(lvi);
356  if (l == 0)
357  proposalLabelsResult[globalVi] = proposalLabelsA)[globalVi] ;
358  if (l == 1)
359  proposalLabelsResult[globalVi] = proposalLabelsB[globalVi] ;
360  else
361  {
362  if(param_.unknownStateBehavior_==TakeA )
363  proposalLabelsResult[globalVi] = proposalLabelsA)[globalVi] ;
364  else
365  proposalLabelsResult[globalVi] = proposalLabelsB)[globalVi] ;
366  }
367  }
368  }
369  else{
370  throw RuntimeError("not yet implemented");
371  }
372 
373 
374  //reset the qpbo solver proxy
375  qpboModelProxy_.reset();
376 
377  return FusionMoveResult();
378 
379  #else
380  throw RuntimeError("fuse2QpboImproment2Order needs WITH_QPBO to be enabled");
381  return FusionMoveResult();
382  #endif
383  }
384 
385  template<class PROPOSAL_LABELS_A,class PROPOSAL_LABELS_B,class PROPOSAL_LABELS_RESULT>
386  FusionMoveResult fuse2QpboAnyOrder(
387  const PROPOSAL_LABELS_A & proposalLabelsA,
388  const PROPOSAL_LABELS_B & proposalLabelsB,
389  PROPOSAL_LABELS_RESULT & proposalLabelsResult
390  ){
391 
392 
393  }
394 
395 
396 
397 
398 
399 
400  void setUpParameter(){
401 
402  }
403 
404  // input data
405  const GM & gm_;
406  const Parameter parameter_;
407 
408 
409 
410  // working data
412  size_t maxFactorOrder_;
413 
414  std::vector<IndexType> localToGlobalVi_;
415  std::vector<IndexType> globalToLocalVi_;
416  IndexType nLocalVar_;
417 
418 
419  ValueType valueA_;
420  ValueType valueB_;
421  bool evaluatedA_;
422  bool evaluatedB_;
423 
424  // QPBO RELATED DATA
425  #ifdef WITH_QPBO
426  detail_fusion::QpboModelProxy<QpboType> qpboModelProxy_;
427  #endif
428 
429 };
STL namespace.
IntegralUnorderedMaxSizeSet(const size_t maxIndex)
#define OPENGM_CHECK_OP(A, OP, B, TXT)
Definition: submodel2.hxx:24
void insert(const IndexType index)
#define OPENGM_GM_TYPE_TYPEDEFS
Definition: inference.hxx:13