aGrUM  0.16.0
structuredInference_tpl.h
Go to the documentation of this file.
1 
31 
32 namespace gum {
33  namespace prm {
34 
35  template < typename GUM_SCALAR >
37  const PRM< GUM_SCALAR >& prm,
38  const PRMSystem< GUM_SCALAR >& system,
40  PRMInference< GUM_SCALAR >(prm, system),
41  __gspan(0), __pdata(0), __mining(false), __dot(".") {
42  GUM_CONSTRUCTOR(StructuredInference);
43  __gspan = new GSpan< GUM_SCALAR >(prm, system, strategy);
44  triang_time = 0.0;
45  mining_time = 0.0;
46  pattern_time = 0.0;
47  inner_time = 0.0;
48  obs_time = 0.0;
49  full_time = 0.0;
50  }
51 
52  template < typename GUM_SCALAR >
54  const StructuredInference< GUM_SCALAR >& source) :
55  PRMInference< GUM_SCALAR >(source),
56  __gspan(0), __pdata(0), __mining(source.__mining), __found_query(false),
57  __dot(".") {
58  GUM_CONS_CPY(StructuredInference);
59  __gspan = new GSpan< GUM_SCALAR >(*(this->_prm), *(this->_sys));
60  }
61 
62  template < typename GUM_SCALAR >
64  GUM_DESTRUCTOR(StructuredInference);
65  delete this->__gspan;
66 
67  for (const auto& elt : __elim_map)
68  delete elt.second;
69 
70  for (const auto& elt : __cdata_map)
71  delete elt.second;
72 
73  for (const auto elt : __trash)
74  delete (elt);
75 
76  for (const auto& elt : __outputs)
77  delete elt.second;
78 
79  if (__pdata) delete __pdata;
80  }
81 
82  template < typename GUM_SCALAR >
85  this->_prm = source._prm;
86  this->_sys = source._sys;
87 
88  if (this->__gspan) delete this->__gspan;
89 
90  this->__gspan = new GSpan< GUM_SCALAR >(*(this->_prm), *(this->_sys));
91  return *this;
92  }
93 
94  template < typename GUM_SCALAR >
96  const typename PRMInference< GUM_SCALAR >::Chain& chain) {}
97 
98  template < typename GUM_SCALAR >
100  const typename PRMInference< GUM_SCALAR >::Chain& chain) {}
101 
102  template < typename GUM_SCALAR >
104  const typename PRMInference< GUM_SCALAR >::Chain& chain,
106  timer.reset();
107  __found_query = false;
108  __query = chain;
110 
111  if (!this->hasEvidence() && (chain.second->cpf().nbrDim() == 1)) {
112  Instantiation i(m);
113 
114  for (i.setFirst(); !i.end(); i.inc())
115  m.set(i, chain.second->cpf().get(i));
116 
117  return;
118  } else if (this->hasEvidence(chain)) {
119  Instantiation i(m);
120  const Potential< GUM_SCALAR >* e =
121  this->evidence(__query.first)[__query.second->id()];
122 
123  for (i.setFirst(); !i.end(); i.inc())
124  m.set(i, e->get(i));
125 
126  return;
127  }
128 
129  __buildReduceGraph(data);
131 
132  if (data.pool.size() > 1) {
133  for (const auto pot : data.pool)
134  if (pot->contains(__query.second->type().variable())) pots.insert(pot);
135 
136  if (pots.size() == 1) {
138  const_cast< Potential< GUM_SCALAR >* >(*(pots.begin()));
139  GUM_ASSERT(pot->contains(__query.second->type().variable()));
140  GUM_ASSERT(pot->variablesSequence().size() == 1);
141  Instantiation i(*pot), j(m);
142 
143  for (i.setFirst(), j.setFirst(); !i.end(); i.inc(), j.inc())
144  m.set(j, pot->get(i));
145  } else {
147  Potential< GUM_SCALAR >* tmp = Comb.combine(pots);
148  Instantiation i(m), j(*tmp);
149 
150  for (i.setFirst(), j.setFirst(); !i.end(); i.inc(), j.inc())
151  m.set(i, tmp->get(j));
152 
153  delete tmp;
154  }
155  } else {
156  Potential< GUM_SCALAR >* pot = *(data.pool.begin());
157  GUM_ASSERT(pot->contains(__query.second->type().variable()));
158  GUM_ASSERT(pot->variablesSequence().size() == 1);
159  Instantiation i(*pot), j(m);
160 
161  for (i.setFirst(), j.setFirst(); !i.end(); i.inc(), j.inc())
162  m.set(j, pot->get(i));
163  }
164 
165  m.normalize();
166 
167  if (__pdata) {
168  delete __pdata;
169  __pdata = 0;
170  }
171 
172  full_time = timer.step();
173  }
174 
175  template < typename GUM_SCALAR >
177  const std::vector< typename PRMInference< GUM_SCALAR >::Chain >& queries,
179  GUM_ERROR(FatalError, "not implemented");
180  }
181 
182  template < typename GUM_SCALAR >
184  std::stringstream s;
185  s << "Triangulation time: " << triang_time << std::endl;
186  s << "Pattern mining time: " << mining_time << std::endl;
187  s << "Pattern elimination time: " << pattern_time << std::endl;
188  s << "Inner node elimination time: " << inner_time << std::endl;
189  s << "Observed node elimination time: " << obs_time << std::endl;
190  s << "Full inference time: " << full_time << std::endl;
191  s << "#patterns: " << __gspan->patterns().size() << std::endl;
192  Size count = 0;
193  typedef std::vector< gspan::Pattern* >::const_iterator Iter;
194 
195  for (Iter p = __gspan->patterns().begin(); p != __gspan->patterns().end();
196  ++p) {
197  if (__gspan->matches(**p).size()) {
198  s << "Pattern n°" << count++
199  << " match count: " << __gspan->matches(**p).size() << std::endl;
200  s << "Pattern n°" << count++ << " instance count: " << (**p).size()
201  << std::endl;
202  }
203  }
204 
205  return s.str();
206  }
207 
208  template < typename GUM_SCALAR >
211  // Launch the pattern mining
212  plopTimer.reset();
213 
214  if (__mining) __gspan->discoverPatterns();
215 
217  // Reducing each used pattern
218  plopTimer.reset();
219  typedef std::vector< gspan::Pattern* >::const_iterator Iter;
220 
221  for (Iter p = __gspan->patterns().begin(); p != __gspan->patterns().end();
222  ++p)
223  if (__gspan->matches(**p).size()) __reducePattern(*p);
224 
226  // reducing instance not already reduced in a pattern
228  // Adding edges using the pools
230  // Placing the query where it belongs
231  NodeId id = data.var2node.second(&(__query.second->type().variable()));
232  data.outputs().erase(id);
233  data.queries().insert(id);
234  // Triangulating, then eliminating
236  &(data.reducedGraph), &(data.mods), &(data.partial_order));
237  const std::vector< NodeId >& elim_order = t.eliminationOrder();
238 
239  for (size_t i = 0; i < data.outputs().size(); ++i)
240  eliminateNode(data.var2node.first(elim_order[i]), data.pool, __trash);
241  }
242 
243  template < typename GUM_SCALAR >
245  const gspan::Pattern* p) {
248  __gspan->matches(*p));
249  __buildPatternGraph(data, pool, **(data.matches.begin()));
250  __removeBarrenNodes(data, pool);
252  &(data.graph), &(data.mod), data.partial_order());
253  const std::vector< NodeId >& elim_order = t.eliminationOrder();
254 
255  for (size_t i = 0; i < data.inners().size(); ++i)
256  if (!data.barren.exists(elim_order[i]))
257  eliminateNode(data.vars.second(elim_order[i]), pool, __trash);
258 
259  typename GSpan< GUM_SCALAR >::MatchedInstances fake_patterns;
261  data.matches.begin();
262 
263  for (const auto elt : **iter)
264  __reducedInstances.insert(elt);
265 
266  if (data.obs().size())
267  __elim_map.insert(
268  *iter,
269  __eliminateObservedNodesInSource(data, pool, **iter, elim_order));
270  else
271  __elim_map.insert(*iter, new Set< Potential< GUM_SCALAR >* >(pool));
272 
273  ++iter;
274 
275  if (data.obs().size()) {
276  for (; iter != data.matches.end(); ++iter) {
277  try {
278  __elim_map.insert(
279  *iter, __eliminateObservedNodes(data, pool, **iter, elim_order));
280  } catch (OperationNotAllowed&) { fake_patterns.insert(*iter); }
281  }
282  } else {
283  for (; iter != data.matches.end(); ++iter) {
284  try {
285  __elim_map.insert(*iter, __translatePotSet(data, pool, **iter));
286  } catch (OperationNotAllowed&) { fake_patterns.insert(*iter); }
287  }
288  }
289 
290  for (const auto pat : fake_patterns) {
291  for (const auto elt : *pat)
292  __reducedInstances.erase(elt);
293 
294  data.matches.erase(pat);
295  }
296 
297  obs_time += plopTimer.step();
298 
299  if (data.queries().size())
300  for (const auto m : data.matches)
301  if (!(m->exists(
302  const_cast< PRMInstance< GUM_SCALAR >* >(__query.first))))
303  eliminateNode(&(m->atPos(__query_data.first)
304  ->get(__query_data.second)
305  .type()
306  .variable()),
307  *(__elim_map[m]),
308  __trash);
309  }
310 
311  template < typename GUM_SCALAR >
314  const Sequence< PRMInstance< GUM_SCALAR >* >& match,
317  NodeId id,
318  std::pair< Idx, std::string >& v) {
319  if ((*inst).hasRefAttr((*inst).get(v.second).id())) {
320  std::vector< std::pair< PRMInstance< GUM_SCALAR >*, std::string > >& refs =
321  inst->getRefAttr(inst->get(v.second).id());
322 
323  for (auto r = refs.begin(); r != refs.end(); ++r) {
324  if (!match.exists(r->first)) {
325  data.outputs().insert(id);
326  break;
327  }
328  }
329  }
330 
331  if (!(data.outputs().size() && (data.outputs().exists(id)))) {
332  for (const auto m : data.matches) {
333  if (this->hasEvidence(
334  std::make_pair((*m)[v.first], &((*m)[v.first]->get(v.second))))) {
335  GUM_ASSERT(inst->type().name() == (*m)[v.first]->type().name());
336  GUM_ASSERT(inst->get(v.second).safeName()
337  == (*m)[v.first]->get(v.second).safeName());
338  data.obs().insert(id);
339  break;
340  }
341  }
342 
343  if (!(data.obs().size() && (data.obs().exists(id))))
344  data.inners().insert(id);
345  }
346  }
347 
348  template < typename GUM_SCALAR >
351  Set< Potential< GUM_SCALAR >* >& pool,
352  const Sequence< PRMInstance< GUM_SCALAR >* >& match) {
353  std::pair< Idx, std::string > v;
354  Potential< GUM_SCALAR >* pot = 0;
355 
356  for (const auto inst : match) {
357  for (const auto& elt : *inst) {
358  NodeId id = data.graph.addNode();
359  v = std::make_pair(match.pos(inst), elt.second->safeName());
360  data.map.insert(id, v);
361  data.node2attr.insert(id, __str(inst, elt.second));
362  data.mod.insert(id, elt.second->type()->domainSize());
363  data.vars.insert(id, &(elt.second->type().variable()));
364  pool.insert(
365  const_cast< Potential< GUM_SCALAR >* >(&(elt.second->cpf())));
366  pot =
367  &(const_cast< Potential< GUM_SCALAR >& >(inst->get(v.second).cpf()));
368 
369  for (const auto var : pot->variablesSequence()) {
370  try {
371  if (id != data.vars.first(var))
372  data.graph.addEdge(id, data.vars.first(var));
373  } catch (DuplicateElement&) {
374  } catch (NotFound&) {}
375  }
376 
377  __insertNodeInElimLists(data, match, inst, elt.second, id, v);
378 
379  if (data.inners().exists(id)
380  && (inst->type().containerDag().children(elt.second->id()).size()
381  == 0)
382  && __allInstanceNoRefAttr(data, v))
383  data.barren.insert(id);
384  }
385  }
386 
387  if (!__found_query) {
388  for (const auto mat : data.matches) {
389  if (mat->exists(
390  const_cast< PRMInstance< GUM_SCALAR >* >(__query.first))) {
391  Idx pos =
392  mat->pos(const_cast< PRMInstance< GUM_SCALAR >* >(__query.first));
393  DiscreteVariable& var =
394  match.atPos(pos)->get(__query.second->safeName()).type().variable();
395  NodeId id = data.vars.first(&var);
396  data.barren.erase(id);
397  data.inners().erase(id);
398  data.obs().erase(id);
399  data.outputs().erase(id);
400  data.queries().insert(id);
401  __found_query = true;
402  __query_data = std::make_pair(pos, __query.second->safeName());
403  break;
404  }
405  }
406  }
407  }
408 
409  template < typename GUM_SCALAR >
412  std::pair< Idx, std::string > attr) {
413  for (const auto mat : data.matches)
414  if (mat->atPos(attr.first)
415  ->hasRefAttr(mat->atPos(attr.first)->get(attr.second).id()))
416  return false;
417 
418  return true;
419  }
420 
421  template < typename GUM_SCALAR >
424  Set< Potential< GUM_SCALAR >* >& pool) {
425  Sequence< NodeId > candidates;
426 
427  for (const auto node : data.barren) {
428  for (const auto pot : pool)
429  if (pot->contains(*data.vars.second(node))) {
430  pool.erase(pot);
431  break;
432  }
433 
434  for (const auto nei : data.graph.neighbours(node))
435  if (data.inners().exists(nei)) {
436  try {
437  candidates.insert(nei);
438  } catch (DuplicateElement&) {}
439  }
440  }
441 
442  NodeId node;
443  Potential< GUM_SCALAR >* my_pot = nullptr;
444  short count = 0;
445 
446  while (candidates.size()) {
447  node = candidates.back();
448  candidates.erase(node);
449  count = 0;
450 
451  for (const auto pot : pool) {
452  if (pot->contains(*data.vars.second(node))) {
453  ++count;
454  my_pot = pot;
455  }
456  }
457 
458  if (count == 1) {
459  pool.erase(my_pot);
460  data.barren.insert(node);
461 
462  for (const auto nei : data.graph.neighbours(node)) {
463  if (data.inners().exists(nei)) {
464  try {
465  candidates.insert(nei);
466  } catch (DuplicateElement&) {}
467  }
468  }
469  }
470  }
471  }
472 
473  template < typename GUM_SCALAR >
477  const Set< Potential< GUM_SCALAR >* >& pool,
478  const Sequence< PRMInstance< GUM_SCALAR >* >& match,
479  const std::vector< NodeId >& elim_order) {
480  Set< Potential< GUM_SCALAR >* >* my_pool =
481  new Set< Potential< GUM_SCALAR >* >(pool);
482  std::pair< Idx, std::string > target;
483  size_t end = data.inners().size() + data.obs().size();
484 
485  for (size_t idx = data.inners().size(); idx < end; ++idx) {
486  target = data.map[data.vars.first(data.vars.second(elim_order[idx]))];
487  eliminateNode(&(match[target.first]->get(target.second).type().variable()),
488  *my_pool,
489  __trash);
490  }
491 
492  return my_pool;
493  }
494 
495  template < typename GUM_SCALAR >
499  const Set< Potential< GUM_SCALAR >* >& pool,
500  const Sequence< PRMInstance< GUM_SCALAR >* >& match,
501  const std::vector< NodeId >& elim_order) {
502  Set< Potential< GUM_SCALAR >* >* my_pool =
503  __translatePotSet(data, pool, match);
504  std::pair< Idx, std::string > target;
505  size_t end = data.inners().size() + data.obs().size();
506 
507  for (size_t idx = data.inners().size(); idx < end; ++idx) {
508  target = data.map[data.vars.first(data.vars.second(elim_order[idx]))];
509  eliminateNode(&(match[target.first]->get(target.second).type().variable()),
510  *my_pool,
511  __trash);
512  }
513 
514  return my_pool;
515  }
516 
517  template < typename GUM_SCALAR >
521  const Set< Potential< GUM_SCALAR >* >& pool,
522  const Sequence< PRMInstance< GUM_SCALAR >* >& match) {
523 #ifdef DEBUG
524 
526  data.matches.begin();
527  iter != data.matches.end();
528  ++iter) {
529  GUM_ASSERT((**iter).size() == match.size());
530 
531  for (Size idx = 0; idx < match.size(); ++idx) {
532  GUM_ASSERT((**iter).atPos(idx)->type() == match.atPos(idx)->type());
533  }
534  }
535 
536 #endif
537  Set< Potential< GUM_SCALAR >* >* my_pool =
539  std::pair< Idx, std::string > target;
541  const Sequence< PRMInstance< GUM_SCALAR >* >& source =
542  **(data.matches.begin());
543 
544  for (Size idx = 0; idx < match.size(); ++idx) {
545  __reducedInstances.insert(match[idx]);
546  const auto& chains = source[idx]->type().slotChains();
547 
548  for (const auto sc : chains) {
549 #ifdef DEBUG
550  GUM_ASSERT(!(sc->isMultiple()));
551 #endif
552 
553  try {
554  bij.insert(&(source[idx]
555  ->getInstance(sc->id())
556  .get(sc->lastElt().safeName())
557  .type()
558  .variable()),
559  &(match[idx]
560  ->getInstance(sc->id())
561  .get(sc->lastElt().safeName())
562  .type()
563  .variable()));
564  } catch (DuplicateElement&) {
565  try {
566  if (bij.first(&(match[idx]
567  ->getInstance(sc->id())
568  .get(sc->lastElt().safeName())
569  .type()
570  .variable()))
571  != &(source[idx]
572  ->getInstance(sc->id())
573  .get(sc->lastElt().safeName())
574  .type()
575  .variable())) {
576  delete my_pool;
577  GUM_ERROR(OperationNotAllowed, "fake pattern");
578  }
579  } catch (NotFound&) {
580  delete my_pool;
581  GUM_ERROR(OperationNotAllowed, "fake pattern");
582  }
583  }
584  }
585  }
586 
587  for (const auto p : pool) {
588  for (const auto v : p->variablesSequence()) {
589  try {
590  target = data.map[data.vars.first(v)];
591  bij.insert(
592  v, &(match[target.first]->get(target.second).type().variable()));
593  } catch (NotFound&) {
594  GUM_ASSERT(bij.existsFirst(v));
595  } catch (DuplicateElement&) {}
596  }
597 
598  try {
599  my_pool->insert(copyPotential(bij, *p));
600  } catch (Exception&) {
601  for (const auto pot : *my_pool)
602  delete pot;
603 
604  delete my_pool;
605  GUM_ERROR(OperationNotAllowed, "fake pattern");
606  }
607  }
608 
609  return my_pool;
610  }
611 
612  template < typename GUM_SCALAR >
614  typename StructuredInference< GUM_SCALAR >::RGData& rg_data) {
616  Potential< GUM_SCALAR >* pot = nullptr;
617  PRMInstance< GUM_SCALAR >* inst = nullptr;
618 
619  for (const auto& elt : *this->_sys) {
620  inst = elt.second;
621 
622  if (!__reducedInstances.exists(inst)) {
623  // Checking if its not an empty class
624  if (inst->size()) {
626 
627  try {
628  data = __cdata_map[&(inst->type())];
629  } catch (NotFound&) {
631  __cdata_map.insert(&(inst->type()), data);
632  }
633 
634  data->instances.insert(inst);
635  // Filling up the partial ordering
636  List< NodeSet > partial_order;
637 
638  if (data->inners().size()) partial_order.push_back(data->inners());
639 
640  if (data->aggregators().size())
641  for (const auto agg : data->aggregators())
642  partial_order[0].insert(agg);
643 
644  if (data->outputs().size()) partial_order.push_back(data->outputs());
645 
646  if (__query.first == inst) {
647  // First case, the instance contains the query
648  partial_order[0].erase(__query.second->id());
649 
650  if (partial_order[0].empty()) partial_order.erase(0);
651 
652  if (partial_order.size() > 1) {
653  partial_order[1].erase(__query.second->id());
654 
655  if (partial_order[1].empty()) partial_order.erase(1);
656  }
657 
658  NodeSet query_set;
659  query_set.insert(__query.second->id());
660  partial_order.insert(query_set);
661 
662  // Adding the potentials
663  for (auto attr = inst->begin(); attr != inst->end(); ++attr)
664  pool.insert(&(
665  const_cast< Potential< GUM_SCALAR >& >((*(attr.val())).cpf())));
666 
667  // Adding evidences if any
668  if (this->hasEvidence(inst))
669  for (const auto& elt : this->evidence(inst))
670  pool.insert(const_cast< Potential< GUM_SCALAR >* >(elt.second));
671 
673  &(data->moral_graph), &(data->mods), &(partial_order));
674  const std::vector< NodeId >& v = t.eliminationOrder();
675 
676  if (partial_order.size() > 1)
677  for (size_t idx = 0; idx < partial_order[0].size(); ++idx)
679  &(inst->get(v[idx]).type().variable()), pool, __trash);
680  } else if (this->hasEvidence(inst)) {
681  // Second case, the instance has evidences
682  // Adding the potentials
683  for (const auto elt : *inst)
684  pool.insert(
685  &const_cast< Potential< GUM_SCALAR >& >(elt.second->cpf()));
686 
687  // Adding evidences
688  for (const auto& elt : this->evidence(inst))
689  pool.insert(const_cast< Potential< GUM_SCALAR >* >(elt.second));
690 
692  &(data->moral_graph), &(data->mods), &(partial_order));
693 
694  for (size_t idx = 0; idx < partial_order[0].size(); ++idx)
696  &(inst->get(t.eliminationOrder()[idx]).type().variable()),
697  pool,
698  __trash);
699  } else {
700  // Last cast, the instance neither contains evidences nor
701  // instances
702  // We translate the class level potentials into the instance ones
703  // and
704  // proceed with elimination
705  for (const auto srcPot : data->pool) {
706  pot = copyPotential(inst->bijection(), *srcPot);
707  pool.insert(pot);
708  __trash.insert(pot);
709  }
710 
711  for (const auto agg : data->c.aggregates())
712  pool.insert(&(const_cast< Potential< GUM_SCALAR >& >(
713  inst->get(agg->id()).cpf())));
714 
715  // We eliminate inner aggregators with their parents if necessary
716  // (see
717  // CData constructor)
718  Size size = data->inners().size() + data->aggregators().size();
719 
720  for (size_t idx = data->inners().size(); idx < size; ++idx)
722  &(inst->get(data->elim_order()[idx]).type().variable()),
723  pool,
724  __trash);
725  }
726 
727  for (const auto pot : pool)
728  rg_data.pool.insert(pot);
729  }
730  }
731  }
732  }
733 
734  template < typename GUM_SCALAR >
737  // We first add edges between variables already in pool (i.e. those of the
738  // reduced instances)
739  NodeId id_1, id_2;
740 
741  for (const auto pot : data.pool) {
742  const Sequence< const DiscreteVariable* >& vars = pot->variablesSequence();
743 
744  for (Size var_1 = 0; var_1 < vars.size(); ++var_1) {
745  if (data.var2node.existsFirst(vars.atPos(var_1))) {
746  id_1 = data.var2node.second(vars.atPos(var_1));
747  } else {
748  id_1 = data.reducedGraph.addNode();
749  data.var2node.insert(vars.atPos(var_1), id_1);
750  data.mods.insert(id_1, vars.atPos(var_1)->domainSize());
751  data.outputs().insert(id_1);
752  }
753 
754  for (Size var_2 = var_1 + 1; var_2 < vars.size(); ++var_2) {
755  if (data.var2node.existsFirst(vars.atPos(var_2))) {
756  id_2 = data.var2node.second(vars.atPos(var_2));
757  } else {
758  id_2 = data.reducedGraph.addNode();
759  data.var2node.insert(vars.atPos(var_2), id_2);
760  data.mods.insert(id_2, vars.atPos(var_2)->domainSize());
761  data.outputs().insert(id_2);
762  }
763 
764  try {
765  data.reducedGraph.addEdge(id_1, id_2);
766  } catch (DuplicateElement&) {}
767  }
768  }
769  }
770 
771  // Adding potentials obtained from reduced patterns
772  for (const auto& elt : __elim_map) {
773  // We add edges between variables in the same reduced patterns
774  for (const auto pot : *elt.second) {
775  data.pool.insert(pot);
777  pot->variablesSequence();
778 
779  for (Size var_1 = 0; var_1 < vars.size(); ++var_1) {
780  if (data.var2node.existsFirst(vars.atPos(var_1))) {
781  id_1 = data.var2node.second(vars.atPos(var_1));
782  } else {
783  id_1 = data.reducedGraph.addNode();
784  data.var2node.insert(vars.atPos(var_1), id_1);
785  data.mods.insert(id_1, vars.atPos(var_1)->domainSize());
786  data.outputs().insert(id_1);
787  }
788 
789  for (Size var_2 = var_1 + 1; var_2 < vars.size(); ++var_2) {
790  if (data.var2node.existsFirst(vars.atPos(var_2))) {
791  id_2 = data.var2node.second(vars.atPos(var_2));
792  } else {
793  id_2 = data.reducedGraph.addNode();
794  data.var2node.insert(vars.atPos(var_2), id_2);
795  data.mods.insert(id_2, vars.atPos(var_2)->domainSize());
796  data.outputs().insert(id_2);
797  }
798 
799  try {
800  data.reducedGraph.addEdge(id_1, id_2);
801  } catch (DuplicateElement&) {}
802  }
803  }
804  }
805  }
806  }
807 
808  template < typename GUM_SCALAR >
811  partial_order.insert(NodeSet());
812  partial_order.insert(NodeSet());
813  }
814 
815  template < typename GUM_SCALAR >
817  const gspan::Pattern& p,
819  pattern(p),
820  matches(m), __real_order(0) {
822 
823  for (int i = 0; i < 4; ++i)
824  __partial_order.push_front(NodeSet());
825  }
826 
827  template < typename GUM_SCALAR >
829  const typename StructuredInference< GUM_SCALAR >::PData& source) :
830  pattern(source.pattern),
831  matches(source.matches), graph(source.graph), mod(source.mod),
832  node2attr(source.node2attr), vars(source.vars),
835  }
836 
837  template < typename GUM_SCALAR >
838  const List< NodeSet >*
840  if (!__real_order) {
842 
843  for (const auto set : __partial_order)
844  if (set.size() > 0) __real_order->insert(set);
845  }
846 
847  return __real_order;
848  }
849 
850  template < typename GUM_SCALAR >
852  const PRMClass< GUM_SCALAR >& a_class) :
853  c(a_class),
854  __elim_order(0) {
856 
857  // First step we add Attributes and Aggregators
858  for (const auto node : c.containerDag().nodes()) {
859  switch (c.get(node).elt_type()) {
861  pool.insert(
862  &(const_cast< Potential< GUM_SCALAR >& >(c.get(node).cpf())));
863  // break omited : We want to execute the next block
864  // for attributes
865  }
866 
869  mods.insert(node, c.get(node).type()->domainSize());
870  break;
871  }
872 
873  default: { /* do nothing */
874  }
875  }
876  }
877 
878  // Second, we add edges, moralise the graph and build the partial ordering
879  for (const auto node : moral_graph.nodes()) {
880  const auto& parents = c.containerDag().parents(node);
881 
882  // Adding edges and marrying parents
883  for (auto tail = parents.begin(); tail != parents.end(); ++tail) {
886  moral_graph.addEdge(*tail, node);
887  NodeSet::const_iterator marry = tail;
888  ++marry;
889 
890  while (marry != parents.end()) {
893  moral_graph.addEdge(*tail, *marry);
894 
895  ++marry;
896  }
897  }
898  }
899 
900  // Adding nodes to the partial ordering
901  switch (c.get(node).elt_type()) {
903  if (c.isOutputNode(c.get(node)))
904  outputs().insert(node);
905  else
906  aggregators().insert(node);
907 
908  // If the aggregators is not an output and have parents which are
909  // not outputs, we must eliminate the parents after adding the
910  // aggregator's CPT
911  for (const auto par : c.containerDag().parents(node)) {
912  const auto& prnt = c.get(par);
913 
914  if ((!c.isOutputNode(prnt))
917  inners().erase(prnt.id());
918  aggregators().insert(prnt.id());
919  }
920  }
921 
922  break;
923  }
924 
926  pool.insert(
927  const_cast< Potential< GUM_SCALAR >* >(&(c.get(node).cpf())));
928 
929  if (c.isOutputNode(c.get(node)))
930  outputs().insert(node);
931  else if (!aggregators().exists(node))
932  inners().insert(node);
933 
934  break;
935  }
936 
937  default: { /* Do nothing */
938  }
939  }
940  }
941 
942  if (inners().size()) partial_order.insert(inners());
943 
944  if (aggregators().size()) partial_order.insert(aggregators());
945 
946  if (outputs().size()) partial_order.insert(outputs());
947 
948  GUM_ASSERT(partial_order.size());
950  __elim_order = t.eliminationOrder();
951 
952  for (size_t i = 0; i < inners().size(); ++i)
953  eliminateNode(&(c.get(__elim_order[i]).type().variable()), pool, __trash);
954  }
955 
956  template < typename GUM_SCALAR >
959 
960  for (const auto pot : __trash)
961  delete pot;
962  }
963 
964  template < typename GUM_SCALAR >
966  const PRMInstance< GUM_SCALAR >* i = (this->_sys->begin()).val();
967  __query = std::make_pair(i, i->begin().val());
968  __found_query = false;
970  __buildReduceGraph(data);
971  }
972 
973  template < typename GUM_SCALAR >
975  __mining = b;
976  }
977 
978  template < typename GUM_SCALAR >
980  const PRMInstance< GUM_SCALAR >* i,
981  const PRMAttribute< GUM_SCALAR >* a) const {
982  return i->name() + __dot + a->safeName();
983  }
984 
985  template < typename GUM_SCALAR >
987  const PRMInstance< GUM_SCALAR >* i,
988  const PRMAttribute< GUM_SCALAR >& a) const {
989  return i->name() + __dot + a.safeName();
990  }
991 
992  template < typename GUM_SCALAR >
994  const PRMInstance< GUM_SCALAR >* i,
995  const PRMSlotChain< GUM_SCALAR >& a) const {
996  return i->name() + __dot + a.lastElt().safeName();
997  }
998 
999  template < typename GUM_SCALAR >
1002  }
1003 
1004  template < typename GUM_SCALAR >
1007  }
1008 
1009  template < typename GUM_SCALAR >
1010  INLINE std::string StructuredInference< GUM_SCALAR >::name() const {
1011  return "StructuredInference";
1012  }
1013 
1014  template < typename GUM_SCALAR >
1016  return *__gspan;
1017  }
1018 
1019  template < typename GUM_SCALAR >
1020  INLINE const GSpan< GUM_SCALAR >&
1022  return *__gspan;
1023  }
1024 
1025  template < typename GUM_SCALAR >
1028  NodeId id,
1030  data.graph.eraseNode(id);
1031  GUM_ASSERT(!data.graph.exists(id));
1032  data.mod.erase(id);
1033  GUM_ASSERT(!data.mod.exists(id));
1034  data.node2attr.eraseFirst(id);
1035  GUM_ASSERT(!data.node2attr.existsFirst(id));
1036  data.map.erase(id);
1037  GUM_ASSERT(!data.map.exists(id));
1038  data.vars.eraseFirst(id);
1039  GUM_ASSERT(!data.vars.existsFirst(id));
1040  data.inners().erase(id);
1041  GUM_ASSERT(!data.inners().exists(id));
1042  pool.erase(data.pots[id]);
1043  GUM_ASSERT(!pool.exists(data.pots[id]));
1044  data.pots.erase(id);
1045  GUM_ASSERT(!data.pots.exists(id));
1046  }
1047 
1048  } /* namespace prm */
1049 } /* namespace gum */
List< NodeSet > partial_order
The partial order used of variable elimination.
void __buildPatternGraph(PData &data, Set< Potential< GUM_SCALAR > * > &pool, const Sequence< PRMInstance< GUM_SCALAR > * > &match)
Build the DAG corresponding to Pattern data.pattern, initialize pool with all the Potentials of all v...
A class to combine efficiently several MultiDim tablesMultiDimCombinationDefault is a class designed ...
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
void insert(const T1 &first, const T2 &second)
Inserts a new association in the gum::Bijection.
HashTable< const PRMClass< GUM_SCALAR > *, CData *> __cdata_map
Mapping between a Class<GUM_SCALAR> and data about instances reduced using only Class<GUM_SCALAR> lev...
aGrUM&#39;s Potential is a multi-dimensional array with tensor operators.
Definition: potential.h:60
void __reducePattern(const gspan::Pattern *p)
Proceed with the elimination of all inner variables (observed or not) of all usable matches of Patter...
NodeProperty< Size > mods
The class variables modalities.
UndiGraph reducedGraph
The reduced graph.
virtual void _marginal(const typename PRMInference< GUM_SCALAR >::Chain &chain, Potential< GUM_SCALAR > &m)
See PRMInference::_marginal().
virtual void addNodeWithId(const NodeId id)
try to insert a node with the given id
Val & push_back(Args &&... args)
An alias for pushBack used for STL compliance.
PData(const gspan::Pattern &p, typename GSpan< GUM_SCALAR >::MatchedInstances &m)
Default constructor.
double step() const
Returns the delta time between now and the last reset() call (or the constructor).
Definition: timer_inl.h:42
NodeSet & queries()
Returns the set of queried nodes given all the matches of pattern.
List< NodeSet > partial_order
Partial order used for triangulation, first is outputs nodes, second query nodes. ...
Set< Potential< GUM_SCALAR > *> __trash
Keeping track of create potentials to delete them after inference.
PRMAttribute< GUM_SCALAR > & get(NodeId id)
Getter on an PRMAttribute<GUM_SCALAR> of this PRMInstance<GUM_SCALAR>.
const T1 & first(const T2 &second) const
Returns the first value of a pair given its second value.
const std::string & name() const
Returns the name of this object.
Definition: PRMObject_inl.h:35
virtual GUM_SCALAR get(const Instantiation &i) const final
Default implementation of MultiDimContainer::get().
GSpan< GUM_SCALAR >::MatchedInstances & matches
A reference over the usable matches of pattern.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
void eraseFirst(const T1 &first)
Erases an association containing the given first element.
Size size() const noexcept
Returns the size of the sequence.
Definition: sequence_tpl.h:38
EMap & evidence(const PRMInstance< GUM_SCALAR > &i)
Returns EMap of evidences over i.
GSpan< GUM_SCALAR > * __gspan
Pointer over th GSpan<GUM_SCALAR> instance used by this class.
An PRMInstance is a Bayesian Network fragment defined by a Class and used in a PRMSystem.
Definition: PRMInstance.h:63
const Potential< GUM_SCALAR > & normalize() const
normalisation of this do nothing if sum is 0
UndiGraph moral_graph
The class moral graph. NodeId matches those in c.
PData * __pdata
The pattern data of the pattern which one of its matches contains the query.
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1022
virtual void addEdge(const NodeId first, const NodeId second)
insert a new edge into the undirected graph
Definition: undiGraph_inl.h:35
NodeSet & outputs()
Returns the set of outputs nodes given all the matches of pattern.
PRMClass< GUM_SCALAR > & type()
Returns the type of this instance.
NodeProperty< std::pair< Idx, std::string > > map
To ease translating potentials from one match to another.
bool __mining
Flag which tells to use pattern mining or not.
virtual void erase(const DiscreteVariable &var) final
Removes a var from the variables of the multidimensional matrix.
Set< Potential< GUM_SCALAR > *> * __eliminateObservedNodesInSource(typename StructuredInference::PData &data, const Set< Potential< GUM_SCALAR > * > &pool, const Sequence< PRMInstance< GUM_SCALAR > * > &match, const std::vector< NodeId > &elim_order)
List< NodeSet > * __real_order
A copy of __partial_order without empty sets.
Set< const PRMInstance< GUM_SCALAR > *> instances
The Set of Instances reduces at class level.
Bijection< const DiscreteVariable *, NodeId > var2node
Mapping between DiscreteVariable and NodeId.
void __insertNodeInElimLists(typename StructuredInference::PData &data, const Sequence< PRMInstance< GUM_SCALAR > * > &match, PRMInstance< GUM_SCALAR > *inst, PRMAttribute< GUM_SCALAR > *attr, NodeId id, std::pair< Idx, std::string > &v)
Abstract class representing an element of PRM class.
Private structure to represent data about a Class<GUM_SCALAR>.
void __reduceAloneInstances(RGData &data)
Add the reduced potentials of instances not in any used patterns.
UndiGraph graph
A yet to be triangulated undigraph.
NodeSet & obs()
Returns the set of inner and observed nodes given all the matches of pattern.
std::string __dot
Unreduce the match containing the query.
void erase(const Key &k)
Erases an element from the set.
Definition: set_tpl.h:656
bool exists(const NodeId id) const
alias for existsNode
Base class for discrete random variable.
Generic doubly linked lists.
Definition: list.h:372
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
NodeSet & outputs()
Returns the set of outputs nodes.
bool __found_query
Flag with an explicit name.
iterator begin() const
The usual unsafe begin iterator to parse the set.
Definition: set_tpl.h:517
void __addEdgesInReducedGraph(RGData &data)
Add the nodes in the reduced graph.
PRM< GUM_SCALAR > const * _prm
The PRM<GUM_SCALAR> on which inference is done.
Definition: PRMInference.h:213
virtual NodeId addNode()
insert a new node and return its id
const gspan::Pattern & pattern
The pattern for which this represents data about it.
Size size() const
Returns the number of attributes in this PRMInstance<GUM_SCALAR>.
NodeSet & queries()
Returns the set of query nodes (which will not be eliminated).
StructuredInference & operator=(const StructuredInference &source)
Copy operator.
NodeProperty< Potential< GUM_SCALAR > *> pots
To handle barren nodes.
void __buildReduceGraph(RGData &data)
This calls __reducePattern() over each pattern and then build the reduced graph which is used for inf...
const NodeSet & neighbours(const NodeId id) const
returns the set of edges adjacent to a given node
virtual void eraseNode(const NodeId id)
remove a node and its adjacent edges from the graph
Definition: undiGraph_inl.h:58
std::vector< std::pair< PRMInstance< GUM_SCALAR > *, std::string > > & getRefAttr(NodeId id)
Returns a vector of pairs of refering attributes of id.
NodeSet & outputs()
Returns the set of outputs nodes (which will be eliminated).
Representation of a setA Set is a structure that contains arbitrary elements.
Definition: set.h:165
const std::string & safeName() const
Returns the safe name of this PRMClassElement, if any.
void reset()
Reset the timer.
Definition: timer_inl.h:32
bool existsFirst(const T1 &first) const
Returns true if first is the first element in a pair in the gum::Bijection.
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:607
void __removeBarrenNodes(typename StructuredInference::PData &data, Set< Potential< GUM_SCALAR > * > &pool)
void erase(Size i)
Erases the ith element of the List (the first one is in position 0).
Definition: list_tpl.h:1909
HashTable< const Sequence< PRMInstance< GUM_SCALAR > *> *, Set< Potential< GUM_SCALAR > *> *> __elim_map
Mapping between a Pattern&#39;s match and its potential pool after inner variables were eliminated...
<agrum/PRM/structuredInference.h>
Bijection< NodeId, const DiscreteVariable *> vars
Bijection between graph&#39;s nodes and their corresponding DiscreteVariable, for inference purpose...
Private structure to represent data about a pattern.
class for graph triangulations for which we enforce a given partial ordering on the nodes elimination...
PRMInference< GUM_SCALAR >::Chain __query
The query.
void inc()
Operator increment.
StructuredInference(const PRM< GUM_SCALAR > &prm, const PRMSystem< GUM_SCALAR > &system, gspan::SearchStrategy< GUM_SCALAR > *strategy=0)
Default constructor.
Set< Potential< GUM_SCALAR > *> pool
The potential pool obtained by C elimination of inner nodes.
Size size() const noexcept
Returns the number of elements in the list.
Definition: list_tpl.h:1851
const Bijection< const DiscreteVariable *, const DiscreteVariable *> & bijection() const
Returns a mapping between DiscreteVariable used in this and the ones used in this PRMInstance<GUM_SCA...
Set< const PRMInstance< GUM_SCALAR > *> __reducedInstances
This keeps track of reduced instances.
const std::vector< NodeId > & eliminationOrder()
returns an elimination ordering compatible with the triangulated graph
Set< NodeId > barren
Set of barren nodes.
const NodeGraphPart & nodes() const
return *this as a NodeGraphPart
A PRMSystem is a container of PRMInstance and describe a relational skeleton.
Definition: PRMObject.h:229
Base class for all aGrUM&#39;s exceptions.
Definition: exceptions.h:106
virtual std::string name() const
Tells this algorithm to use pattern mining or not.
Set of pairs of elements with fast search for both elements.
Definition: bijection.h:1805
Potential< GUM_SCALAR > * copyPotential(const Bijection< const DiscreteVariable *, const DiscreteVariable * > &bij, const Potential< GUM_SCALAR > &source)
Returns a copy of a Potential after applying a bijection over the variables in source.
Definition: utils_prm_tpl.h:29
List< NodeSet > __partial_order
We&#39;ll use a PartialOrderedTriangulation with three sets: output, nodes and obs with children outside ...
void eliminateNode(const DiscreteVariable *var, Set< Potential< GUM_SCALAR > * > &pool, Set< Potential< GUM_SCALAR > * > &trash)
Proceeds with the elimination of var in pool.
NodeSet & inners()
Returns the set of inner nodes.
Set< Potential< GUM_SCALAR > *> * __eliminateObservedNodes(typename StructuredInference::PData &data, const Set< Potential< GUM_SCALAR > * > &pool, const Sequence< PRMInstance< GUM_SCALAR > * > &match, const std::vector< NodeId > &elim_order)
Add in data.queries() any queried variable in one of data.pattern matches.
A PRMSlotChain represents a sequence of gum::prm::PRMClassElement<GUM_SCALAR> where the n-1 first gum...
Definition: PRMObject.h:221
bool hasEvidence() const
Returns true if i has evidence on PRMAttribute<GUM_SCALAR> a.
PRMSystem< GUM_SCALAR > const * _sys
The Model on which inference is done.
Definition: PRMInference.h:216
NodeProperty< Size > mod
The pattern&#39;s variables modalities.
NodeSet & aggregators()
Returns the set of aggregators and their parents.
Unsafe iterators for the Set class.
Definition: set.h:1025
std::pair< const PRMInstance< GUM_SCALAR > *, const PRMAttribute< GUM_SCALAR > *> Chain
Code alias.
Definition: PRMInference.h:57
Set< Potential< GUM_SCALAR > *> * __translatePotSet(typename StructuredInference::PData &data, const Set< Potential< GUM_SCALAR > * > &pool, const Sequence< PRMInstance< GUM_SCALAR > * > &match)
Translate a given Potential Set into one w.r.t. variables in match.
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:83
virtual void _joint(const std::vector< typename PRMInference< GUM_SCALAR >::Chain > &queries, Potential< GUM_SCALAR > &j)
See PRMInference::_joint().
void erase(const Key &k)
Remove an element from the sequence.
Definition: sequence_tpl.h:453
HashTable< const PRMClass< GUM_SCALAR > *, std::vector< NodeId > *> __outputs
std::string __str(const PRMInstance< GUM_SCALAR > *i, const PRMAttribute< GUM_SCALAR > *a) const
Val & insert(const Val &val)
Inserts a new element at the end of the chained list (alias of pushBack).
Definition: list_tpl.h:1619
This abstract class is used as base class for all inference class on PRM<GUM_SCALAR>.
Definition: PRMInference.h:52
bool __allInstanceNoRefAttr(typename StructuredInference::PData &data, std::pair< Idx, std::string > attr)
Private structure to represent data about a reduced graph.
std::vector< NodeId > & elim_order()
The elimination order for nodes of this class.
This class represents a Probabilistic Relational PRMSystem<GUM_SCALAR>.
Definition: PRM.h:66
const iterator & end()
Returns a reference over the iterator at the end of the list of gum::prm::PRMAttribute<GUM_SCALAR> in...
A PRMClass is an object of a PRM representing a fragment of a Bayesian Network which can be instantia...
Definition: PRMClass.h:66
This class discovers pattern in a PRM<GUM_SCALAR>&#39;s PRMSystem<GUM_SCALAR> to speed up structured infe...
Definition: DFSTree.h:57
std::pair< Idx, std::string > __query_data
virtual void set(const Instantiation &i, const GUM_SCALAR &value) const final
Default implementation of MultiDimContainer::set().
void setFirst()
Assign the first values to the tuple of the Instantiation.
virtual ~StructuredInference()
Destructor.
Size Idx
Type for indexes.
Definition: types.h:53
CData(const PRMClass< GUM_SCALAR > &c)
Default constructor.
NodeSet & inners()
Returns the set of inner nodes.
GSpan< GUM_SCALAR > & gspan()
Returns the instance of gspan used to search patterns.
virtual void _evidenceRemoved(const typename PRMInference< GUM_SCALAR >::Chain &chain)
See PRMInference::_evidenceRemoved().
PRMAttribute is a member of a Class in a PRM.
Definition: PRMAttribute.h:61
Bijection< NodeId, std::string > node2attr
A bijection to easily keep track between graph and attributes, its of the form instance_name DOT attr...
virtual void _evidenceAdded(const typename PRMInference< GUM_SCALAR >::Chain &chain)
See PRMInference::_evidenceAdded().
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48
PRMClassElement< GUM_SCALAR > & lastElt()
Returns the last element of the slot chain, typically this is an gum::PRMAttribute or a gum::PRMAggre...
virtual const Sequence< const DiscreteVariable *> & variablesSequence() const final
Returns a const ref to the sequence of DiscreteVariable*.
iterator begin()
Returns an iterator at the begining of the list of gum::prm::PRMAttribute<GUM_SCALAR> in this PRMInst...
Set< Potential< GUM_SCALAR > *> pool
The pool of potentials matching the reduced graph.
Size size() const noexcept
Returns the number of elements in the set.
Definition: set_tpl.h:701
void setPatternMining(bool b)
Tells this algorithm to use pattern mining or not.
static INLINE bool isAggregate(const PRMClassElement< GUM_SCALAR > &elt)
Return true if obj is of type PRMAggregate.
virtual bool contains(const DiscreteVariable &var) const final
Returns true if var is in *this.
virtual TABLE< GUM_SCALAR > * combine(const Set< const TABLE< GUM_SCALAR > * > &set)
Creates and returns the result of the combination of the tables within set.
This contains all the information we want for a node in a DFSTree.
Definition: pattern.h:73
This is an abstract class used to tune search strategies in the gspan algorithm.
Definition: DFSTree.h:61
Size NodeId
Type for node ids.
Definition: graphElements.h:98
NodeProperty< Size > mods
Mapping between NodeId and modalities.
void insert(const Key &k)
Inserts a new element into the set.
Definition: set_tpl.h:613
const Key & back() const
Returns the last element of the sequence.
Definition: sequence_tpl.h:568
const PRMClass< GUM_SCALAR > & c
The class about what this data is about.
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
const Key & atPos(Idx i) const
Returns the object at the pos i.
Definition: sequence_tpl.h:500
Set< Potential< GUM_SCALAR > *> __trash
void __removeNode(typename StructuredInference::PData &data, NodeId id, Set< Potential< GUM_SCALAR > * > &pool)
bool end() const
Returns true if the Instantiation reached the end.
Potential< GUM_SCALAR > * multPotential(const Potential< GUM_SCALAR > &t1, const Potential< GUM_SCALAR > &t2)
void searchPatterns()
Search for patterns without doing any computations.
void insert(const Key &k)
Insert an element at the end of the sequence.
Definition: sequence_tpl.h:408