HypothesesTree.cpp
Go to the documentation of this file.
1 /*
2  * HypothesesTree.cpp
3  *
4  * Created on: March, 2011
5  * Author: Jos Elfring, Sjoerd van den Dries
6  * Affiliation: Eindhoven University of Technology
7  */
8 
10 
11 #include "wire/logic/Assignment.h"
14 #include "wire/logic/Hypothesis.h"
15 
19 
20 #include "wire/core/Evidence.h"
21 #include "wire/core/EvidenceSet.h"
22 #include "wire/core/Property.h"
23 #include "wire/core/ClassModel.h"
24 
25 #include <queue>
26 #include <cassert>
27 #include <float.h>
28 
29 #ifdef MHF_MEASURE_TIME
30  #include <time.h>
31 #endif
32 
33 //#define DEBUG_INFO(_msg, ...) printf(_msg, ##__VA_ARGS__)
34 #define DEBUG_INFO(_msg, ...)
35 
36 namespace mhf {
37 
38 /* ****************************************************************************** */
39 /* * CONSTRUCTOR / DESTRUCTOR * */
40 /* ****************************************************************************** */
41 
42 HypothesisTree::HypothesisTree(int num_max_hyps, double max_min_prob_ratio) : n_updates_(0), t_last_update_(-1),
43  tree_height_(0), num_max_hyps_(num_max_hyps), max_min_prob_ratio_(max_min_prob_ratio) {
44 
45  // create empty hypothesis (contains no objects) with timestep 0
46  Hypothesis* empty_hyp = new Hypothesis(t_last_update_, 1.0);
47 
48  // add empty hypothesis to leaf list and set as root
49  leafs_.push_back(empty_hyp);
50  root_ = empty_hyp;
51  MAP_hypothesis_ = empty_hyp;
52 }
53 
56  delete root_;
57 }
58 
59 /* ****************************************************************************** */
60 /* * PUBLIC MHT OPERATIONS * */
61 /* ****************************************************************************** */
62 
64  DEBUG_INFO("HypothesesTree::processMeasurements\n");
65 
66  if (ev_set.size() == 0) {
67  return;
68  }
69 
70 #ifdef MHF_MEASURE_TIME
71  timespec t_start_total, t_end_total;
72  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t_start_total);
73 #endif
74 
75  //** Propagate all objects, compute association probabilities and add all possible measurement-track assignments
76  for(EvidenceSet::const_iterator it_ev = ev_set.begin(); it_ev != ev_set.end(); ++it_ev) {
78  }
79 
80  t_last_update_ = ev_set.getTimestamp();
81 
82  expandTree(ev_set);
83 
84  pruneTree(ev_set.getTimestamp());
85 
87 
88  // clear old hypotheses leafs
89  // The hypotheses will still be there to form a tree, but do not contain any objects anymore
91 
93 
95 
96  DEBUG_INFO("*** Free memory: assignment matrices ***\n");
97 
98  ++n_updates_;
99 
100 #ifdef MHF_MEASURE_TIME
101  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t_end_total);
102  printf("Total update took %f seconds.\n", (t_end_total.tv_sec - t_start_total.tv_sec) + double(t_end_total.tv_nsec - t_start_total.tv_nsec) / 1e9);
103 #endif
104 
105  DEBUG_INFO("HypothesesTree::processMeasurements - end\n");
106 }
107 
108 /* ****************************************************************************** */
109 /* * PROTECTED MHT OPERATIONS * */
110 /* ****************************************************************************** */
111 
113  bool operator()(const AssignmentSet* a1, const AssignmentSet* a2) const {
114  return a1->getProbability() < a2->getProbability();
115  }
116 };
117 
119  DEBUG_INFO("applyAssignments - begin\n");
120 
121  // iterate over all leaf hypotheses
122  for (std::list<Hypothesis*>::iterator it = leafs_.begin(); it != leafs_.end(); ++it) {
123  DEBUG_INFO(" materializing hyp %p, with parent %p\n", (*it), (*it)->getParent());
124  (*it)->applyAssignments();
125  }
126 
127  DEBUG_INFO("applyAssignments - end\n");
128 }
129 
131 
132  DEBUG_INFO("expandTree - start\n");
133 
134  //** Create new objects based on measurements
135 
136  std::list<Assignment*> new_assignments;
137  std::list<Assignment*> clutter_assignments;
138  for(EvidenceSet::const_iterator it_ev = ev_set.begin(); it_ev != ev_set.end(); ++it_ev) {
139  // new
140  new_assignments.push_back(new Assignment(Assignment::NEW, *it_ev, 0, KnowledgeDatabase::getInstance().getProbabilityNew(**it_ev)));
141 
142  // clutter
143  clutter_assignments.push_back(new Assignment(Assignment::CLUTTER, *it_ev, 0, KnowledgeDatabase::getInstance().getProbabilityClutter(**it_ev)));
144  }
145 
146 #ifdef MHF_MEASURE_TIME
147  timespec t_start, t_end;
148  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t_start);
149 #endif
150 
151  //** expand all current leaf hypotheses
152 
153  std::priority_queue<AssignmentSet*, std::vector<AssignmentSet*>, compareAssignmentSets > assignment_sets;
154 
155  DEBUG_INFO(" - Create assignment matrices and assignment sets\n");
156 
157  for (std::list<Hypothesis*>::iterator it_hyp = leafs_.begin(); it_hyp != leafs_.end(); ++it_hyp) {
158  Hypothesis* hyp = *it_hyp;
159 
160  // add new object assignments to current hypothesis
161  for(std::list<Assignment*>::iterator it_ass = new_assignments.begin(); it_ass != new_assignments.end(); ++it_ass) {
162  hyp->addPotentialAssignment(*it_ass);
163  }
164 
165  // add clutter assignments to current hypothesis
166  for(std::list<Assignment*>::iterator it_ass = clutter_assignments.begin(); it_ass != clutter_assignments.end(); ++it_ass) {
167  hyp->addPotentialAssignment(*it_ass);
168  }
169 
170  // evidence-to-object assignments are added in addEvidence() method already
171 
172  // sort assignment matrix based on assignment probabilities
174 
175  // create empty assignment set, add assignments and update probability (product hypothesis and assignment probs)
176  AssignmentSet* ass_set = new AssignmentSet(hyp, hyp->getAssignmentMatrix());
177  assignment_sets.push(ass_set);
178  }
179 
180  DEBUG_INFO(" - Generate hypotheses\n");
181 
182  double min_prob = 0;
183 
184  // set all current leafs to inactive
185  for (std::list<Hypothesis*>::iterator it_hyp = leafs_.begin(); it_hyp != leafs_.end(); ++it_hyp) {
186  (*it_hyp)->setInactive();
187  }
188 
189  leafs_.clear();
190 
191  int n_iterations = 0;
192 
193  // add hypotheses as long as there are criteria are met
194  while(!assignment_sets.empty() && leafs_.size() < num_max_hyps_ && assignment_sets.top()->getProbability() > min_prob) {
195  // assignment_sets.top()->print();
196 
197  // Get most probable assignment
198  ++n_iterations;
199  DEBUG_INFO(" #assignment sets = %i\n", (int)assignment_sets.size());
200  AssignmentSet* ass_set = assignment_sets.top();
201 
202  DEBUG_INFO(" inspecting assignment set %p with probability %.16f\n", ass_set, ass_set->getProbability());
203 
204  // remove most probable assignment (stored in ass_set pointer above)
205  assignment_sets.pop();
206  Hypothesis* hyp = ass_set->getHypothesis();
207 
208  if (ass_set->isValid()) {
209  /* ************ assignment set is complete! Create hypothesis ************ */
210 
211  Hypothesis* hyp_child = new Hypothesis(ev_set.getTimestamp(), ass_set->getProbability());
212  hyp_child->setAssignments(ass_set);
213  hyp->addChildHypothesis(hyp_child);
214 
215  if (leafs_.empty()) {
216  // first hypothesis found (and therefore the best one)
217  min_prob = hyp_child->getProbability() * max_min_prob_ratio_;
218 
219  MAP_hypothesis_ = hyp_child;
220  }
221 
222  /*
223  if (leafs_.size() <= 3) {
224  ass_set->print();
225  }
226  */
227 
228  //printf("%i: new leaf with prob %f\n", leafs_.size(), hyp_child->probability_);
229 
230  DEBUG_INFO(" NEW LEAF: %p\n", hyp_child);
231  leafs_.push_back(hyp_child);
232  DEBUG_INFO(" #leafs = %i, #old leafs = %i\n", (int)leafs_.size(), n_old_leafs);
233 
234  /* ************************************************************************* */
235  }
236 
237  std::list<AssignmentSet*> child_assignment_sets;
238  ass_set->expand(child_assignment_sets);
239  for(std::list<AssignmentSet*>::iterator it_child = child_assignment_sets.begin(); it_child != child_assignment_sets.end(); ++it_child) {
240  assignment_sets.push(*it_child);
241  }
242 
243  }
244 
245  DEBUG_INFO(" - Free memory (remaining assignment sets)\n");
246 
247  assert(leafs_.size() > 0);
248 
249  // delete remaining assignment sets (the ones that where not used to generate hypotheses)
250  while(!assignment_sets.empty()) {
251  delete assignment_sets.top();
252  assignment_sets.pop();
253  }
254 
255  DEBUG_INFO(" ... done\n");
256 
257  ++tree_height_;
258 
260 
261 #ifdef MHF_MEASURE_TIME
262  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t_end);
263  printf("Expansion of hypotheses took %f seconds.\n", (t_end.tv_sec - t_start.tv_sec) + double(t_end.tv_nsec - t_start.tv_nsec) / 1e9);
264 #endif
265 
266  DEBUG_INFO("expandTree - done\n");
267 }
268 
270  // Calculate sum of all probabilities
271  double p_total = 0;
272  for(std::list<Hypothesis* >::iterator it_hyp = leafs_.begin(); it_hyp != leafs_.end(); ++it_hyp) {
273  p_total += (*it_hyp)->getProbability();
274  }
275 
276  // Normalize all probabilities
277  for(std::list<Hypothesis* >::iterator it_hyp = leafs_.begin(); it_hyp != leafs_.end(); ++it_hyp) {
278  (*it_hyp)->setProbability((*it_hyp)->getProbability() / p_total);
279  }
280 
282 }
283 
284 void HypothesisTree::pruneTree(const Time& timestamp) {
285  //return;
286 
287 
288  DEBUG_INFO("pruneTree - begin\n");
289 
290  DEBUG_INFO(" old #leafs = %i\n", (int)leafs_.size());
291 
292  // determine best branch leaf per hypothesis
293 
294  DEBUG_INFO(" - determine best leaf per branch\n");
296  DEBUG_INFO(" ... done\n");
297 
298  double prob_ratios[] = {1e-8, 1e-7, 1e-6, 1e-5, 1e-5, 1e-4, 1};
299 
300  std::list<Hypothesis*> hyp_stack;
301  hyp_stack.push_back(root_);
302 
303  while(!hyp_stack.empty()) {
304  Hypothesis* hyp = hyp_stack.front();
305  hyp_stack.pop_front();
306 
307  std::list<Hypothesis*>& children = hyp->getChildHypotheses();
308  if (!children.empty()) {
309 
310  // determine best branch of root hypothesis (highest sum of leaf probabilities)
311  Hypothesis* best_child = *children.begin();
312  for (std::list<Hypothesis*>::const_iterator it_child = children.begin(); it_child != children.end(); ++it_child) {
313  if ((*it_child)->getProbability() > best_child->getProbability()) {
314  best_child = *it_child;
315  }
316  //printf(" (%p, %f)", *it_child, (*it_child)->getProbability());
317  }
318 
319  double prob_ratio = 0;
320 
321  if (hyp->getHeight() > 6) {
322  prob_ratio = 0;
323  } else {
324  prob_ratio = prob_ratios[hyp->getHeight()];
325  }
326 
327  double min_prob = best_child->getProbability() * prob_ratio;
328 
329  for (std::list<Hypothesis*>::iterator it_child = children.begin(); it_child != children.end();) {
330  bool prune_child = false;
331 
332  if (*it_child != best_child) {
333  if ((*it_child)->getProbability() == 0) {
334  prune_child = true;
335  } else if (hyp->getHeight() > 6) {
336  DEBUG_INFO(" - Determine hyp similarity between %p and %p\n", best_child->getBestLeaf(), (*it_child)->getBestLeaf());
337  double similarity = 1;
338  DEBUG_INFO(" ... done\n");
339 
340  //printf(" similarity = %f\n", similarity);
341 
342  prune_child = (similarity > 0.5);
343  } else if ((*it_child)->getProbability() < min_prob) {
344  prune_child = true;
345  }
346  }
347 
348  if (prune_child) {
349  // prune hypothesis and all child hypothesis
350  (*it_child)->deleteChildren();
351  delete (*it_child);
352  it_child = children.erase(it_child);
353  } else {
354  hyp_stack.push_front(*it_child);
355  ++it_child;
356  }
357  }
358 
359  }
360  }
361 
362  // clear leaf list and add new leafs of tree
363  leafs_.clear();
365 
367 
368  DEBUG_INFO(" #leafs after pruning = %i\n", (int)leafs_.size());
369 
370  DEBUG_INFO("pruneTree - end\n");
371 }
372 
373 /* ****************************************************************************** */
374 /* * GETTERS * */
375 /* ****************************************************************************** */
376 
377 const std::list<Hypothesis*>& HypothesisTree::getHypotheses() const {
378  return leafs_;
379 }
380 
382  return tree_height_;
383 }
384 
385 
387  return *MAP_hypothesis_;
388 }
389 
390 const std::list<SemanticObject*>& HypothesisTree::getMAPObjects() const {
391  DEBUG_INFO("getMAPObjects - begin\n");
392  return getMAPHypothesis().getObjects();
393 }
394 
395 
396 /* ****************************************************************************** */
397 /* * PRINT METHODS * */
398 /* ****************************************************************************** */
399 
401  std::cout << " Number of hypotheses = " << leafs_.size() << std::endl;
402  std::cout << " Max probability = " << getMAPHypothesis().getProbability() << std::endl;
403  std::cout << " Tree height = " << tree_height_ << std::endl;
404 }
405 
406 }
AssignmentMatrix * getAssignmentMatrix() const
Definition: Hypothesis.cpp:78
Hypothesis * determineBestLeaf()
Definition: Hypothesis.cpp:212
HypothesisTree(int num_max_hyps, double max_min_prob_ratio)
bool operator()(const AssignmentSet *a1, const AssignmentSet *a2) const
static ObjectStorage & getInstance()
std::list< Hypothesis * > leafs_
const Hypothesis * getBestLeaf() const
Definition: Hypothesis.cpp:43
double getProbability() const
Hypothesis * MAP_hypothesis_
std::vector< Evidence * >::const_iterator end() const
Definition: EvidenceSet.cpp:41
std::vector< Evidence * >::const_iterator begin() const
Definition: EvidenceSet.cpp:37
double getProbability() const
Definition: Hypothesis.cpp:69
void setAssignments(AssignmentSet *assignments)
Definition: Hypothesis.cpp:87
static KnowledgeDatabase & getInstance()
iterator(field< oT > &in_M, const bool at_end=false)
double Time
Definition: datatypes.h:52
void addEvidence(const EvidenceSet &ev_set)
const Hypothesis & getMAPHypothesis() const
std::vector< Evidence * >::const_iterator const_iterator
Definition: EvidenceSet.h:93
int getHeight() const
Definition: Hypothesis.cpp:52
void expandTree(const EvidenceSet &ev_set)
unsigned int size() const
Returns the number of evidence items in the set.
Definition: EvidenceSet.cpp:29
A set of Evidence items which all originate from the same point int time.
Definition: EvidenceSet.h:55
const Time & getTimestamp() const
Returns the time from which all evidence in the set originates.
Definition: EvidenceSet.cpp:33
const_iterator(const field< oT > &in_M, const bool at_end=false)
void match(const Evidence &ev)
#define DEBUG_INFO(_msg,...)
double calculateBranchProbabilities()
Definition: Hypothesis.cpp:189
void deleteChildren()
Definition: Hypothesis.cpp:277
unsigned int num_max_hyps_
void findActiveLeafs(std::list< Hypothesis * > &active_leafs)
Definition: Hypothesis.cpp:228
const std::list< SemanticObject * > & getMAPObjects() const
Hypothesis * deleteSinglePaths()
Definition: Hypothesis.cpp:286
std::list< Hypothesis * > & getChildHypotheses()
Definition: Hypothesis.cpp:48
void addPotentialAssignment(Assignment *assignment)
Definition: Hypothesis.cpp:125
const std::list< SemanticObject * > & getObjects() const
Definition: Hypothesis.cpp:60
void addChildHypothesis(Hypothesis *h)
Definition: Hypothesis.cpp:108
const std::list< Hypothesis * > & getHypotheses() const
void pruneTree(const Time &timestamp)
void clearInactive()
Definition: Hypothesis.cpp:267
Definition: ClassModel.h:44


wire_core
Author(s): Sjoerd van den Dries, Jos Elfring
autogenerated on Fri Apr 16 2021 02:32:27