aGrUM  0.17.2
a C++ library for (probabilistic) graphical models
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  const StructuredInference< GUM_SCALAR >& source) {
86  this->_prm = source._prm;
87  this->_sys = source._sys;
88 
89  if (this->__gspan) delete this->__gspan;
90 
91  this->__gspan = new GSpan< GUM_SCALAR >(*(this->_prm), *(this->_sys));
92  return *this;
93  }
94 
95  template < typename GUM_SCALAR >
97  const typename PRMInference< GUM_SCALAR >::Chain& chain) {}
98 
99  template < typename GUM_SCALAR >
101  const typename PRMInference< GUM_SCALAR >::Chain& chain) {}
102 
103  template < typename GUM_SCALAR >
105  const typename PRMInference< GUM_SCALAR >::Chain& chain,
107  timer.reset();
108  __found_query = false;
109  __query = chain;
111 
112  if (!this->hasEvidence() && (chain.second->cpf().nbrDim() == 1)) {
113  Instantiation i(m);
114 
115  for (i.setFirst(); !i.end(); i.inc())
116  m.set(i, chain.second->cpf().get(i));
117 
118  return;
119  } else if (this->hasEvidence(chain)) {
120  Instantiation i(m);
121  const Potential< GUM_SCALAR >* e =
122  this->evidence(__query.first)[__query.second->id()];
123 
124  for (i.setFirst(); !i.end(); i.inc())
125  m.set(i, e->get(i));
126 
127  return;
128  }
129 
130  __buildReduceGraph(data);
132 
133  if (data.pool.size() > 1) {
134  for (const auto pot: data.pool)
135  if (pot->contains(__query.second->type().variable())) pots.insert(pot);
136 
137  if (pots.size() == 1) {
139  const_cast< Potential< GUM_SCALAR >* >(*(pots.begin()));
140  GUM_ASSERT(pot->contains(__query.second->type().variable()));
141  GUM_ASSERT(pot->variablesSequence().size() == 1);
142  Instantiation i(*pot), j(m);
143 
144  for (i.setFirst(), j.setFirst(); !i.end(); i.inc(), j.inc())
145  m.set(j, pot->get(i));
146  } else {
148  Potential< GUM_SCALAR >* tmp = Comb.combine(pots);
149  Instantiation i(m), j(*tmp);
150 
151  for (i.setFirst(), j.setFirst(); !i.end(); i.inc(), j.inc())
152  m.set(i, tmp->get(j));
153 
154  delete tmp;
155  }
156  } else {
157  Potential< GUM_SCALAR >* pot = *(data.pool.begin());
158  GUM_ASSERT(pot->contains(__query.second->type().variable()));
159  GUM_ASSERT(pot->variablesSequence().size() == 1);
160  Instantiation i(*pot), j(m);
161 
162  for (i.setFirst(), j.setFirst(); !i.end(); i.inc(), j.inc())
163  m.set(j, pot->get(i));
164  }
165 
166  m.normalize();
167 
168  if (__pdata) {
169  delete __pdata;
170  __pdata = 0;
171  }
172 
173  full_time = timer.step();
174  }
175 
176  template < typename GUM_SCALAR >
178  const std::vector< typename PRMInference< GUM_SCALAR >::Chain >& queries,
180  GUM_ERROR(FatalError, "not implemented");
181  }
182 
183  template < typename GUM_SCALAR >
185  std::stringstream s;
186  s << "Triangulation time: " << triang_time << std::endl;
187  s << "Pattern mining time: " << mining_time << std::endl;
188  s << "Pattern elimination time: " << pattern_time << std::endl;
189  s << "Inner node elimination time: " << inner_time << std::endl;
190  s << "Observed node elimination time: " << obs_time << std::endl;
191  s << "Full inference time: " << full_time << std::endl;
192  s << "#patterns: " << __gspan->patterns().size() << std::endl;
193  Size count = 0;
194  typedef std::vector< gspan::Pattern* >::const_iterator Iter;
195 
196  for (Iter p = __gspan->patterns().begin(); p != __gspan->patterns().end();
197  ++p) {
198  if (__gspan->matches(**p).size()) {
199  s << "Pattern n°" << count++
200  << " match count: " << __gspan->matches(**p).size() << std::endl;
201  s << "Pattern n°" << count++ << " instance count: " << (**p).size()
202  << std::endl;
203  }
204  }
205 
206  return s.str();
207  }
208 
209  template < typename GUM_SCALAR >
212  // Launch the pattern mining
213  plopTimer.reset();
214 
215  if (__mining) __gspan->discoverPatterns();
216 
218  // Reducing each used pattern
219  plopTimer.reset();
220  typedef std::vector< gspan::Pattern* >::const_iterator Iter;
221 
222  for (Iter p = __gspan->patterns().begin(); p != __gspan->patterns().end();
223  ++p)
224  if (__gspan->matches(**p).size()) __reducePattern(*p);
225 
227  // reducing instance not already reduced in a pattern
229  // Adding edges using the pools
231  // Placing the query where it belongs
232  NodeId id = data.var2node.second(&(__query.second->type().variable()));
233  data.outputs().erase(id);
234  data.queries().insert(id);
235  // Triangulating, then eliminating
237  &(data.reducedGraph), &(data.mods), &(data.partial_order));
238  const std::vector< NodeId >& elim_order = t.eliminationOrder();
239 
240  for (size_t i = 0; i < data.outputs().size(); ++i)
241  eliminateNode(data.var2node.first(elim_order[i]), data.pool, __trash);
242  }
243 
244  template < typename GUM_SCALAR >
246  const gspan::Pattern* p) {
249  __gspan->matches(*p));
250  __buildPatternGraph(data, pool, **(data.matches.begin()));
251  __removeBarrenNodes(data, pool);
253  &(data.graph), &(data.mod), data.partial_order());
254  const std::vector< NodeId >& elim_order = t.eliminationOrder();
255 
256  for (size_t i = 0; i < data.inners().size(); ++i)
257  if (!data.barren.exists(elim_order[i]))
258  eliminateNode(data.vars.second(elim_order[i]), pool, __trash);
259 
260  typename GSpan< GUM_SCALAR >::MatchedInstances fake_patterns;
262  data.matches.begin();
263 
264  for (const auto elt: **iter)
265  __reducedInstances.insert(elt);
266 
267  if (data.obs().size())
268  __elim_map.insert(
269  *iter,
270  __eliminateObservedNodesInSource(data, pool, **iter, elim_order));
271  else
272  __elim_map.insert(*iter, new Set< Potential< GUM_SCALAR >* >(pool));
273 
274  ++iter;
275 
276  if (data.obs().size()) {
277  for (; iter != data.matches.end(); ++iter) {
278  try {
279  __elim_map.insert(
280  *iter, __eliminateObservedNodes(data, pool, **iter, elim_order));
281  } catch (OperationNotAllowed&) { fake_patterns.insert(*iter); }
282  }
283  } else {
284  for (; iter != data.matches.end(); ++iter) {
285  try {
286  __elim_map.insert(*iter, __translatePotSet(data, pool, **iter));
287  } catch (OperationNotAllowed&) { fake_patterns.insert(*iter); }
288  }
289  }
290 
291  for (const auto pat: fake_patterns) {
292  for (const auto elt: *pat)
293  __reducedInstances.erase(elt);
294 
295  data.matches.erase(pat);
296  }
297 
298  obs_time += plopTimer.step();
299 
300  if (data.queries().size())
301  for (const auto m: data.matches)
302  if (!(m->exists(
303  const_cast< PRMInstance< GUM_SCALAR >* >(__query.first))))
304  eliminateNode(&(m->atPos(__query_data.first)
305  ->get(__query_data.second)
306  .type()
307  .variable()),
308  *(__elim_map[m]),
309  __trash);
310  }
311 
312  template < typename GUM_SCALAR >
315  const Sequence< PRMInstance< GUM_SCALAR >* >& match,
318  NodeId id,
319  std::pair< Idx, std::string >& v) {
320  if ((*inst).hasRefAttr((*inst).get(v.second).id())) {
321  std::vector< std::pair< PRMInstance< GUM_SCALAR >*, std::string > >& refs =
322  inst->getRefAttr(inst->get(v.second).id());
323 
324  for (auto r = refs.begin(); r != refs.end(); ++r) {
325  if (!match.exists(r->first)) {
326  data.outputs().insert(id);
327  break;
328  }
329  }
330  }
331 
332  if (!(data.outputs().size() && (data.outputs().exists(id)))) {
333  for (const auto m: data.matches) {
334  if (this->hasEvidence(
335  std::make_pair((*m)[v.first], &((*m)[v.first]->get(v.second))))) {
336  GUM_ASSERT(inst->type().name() == (*m)[v.first]->type().name());
337  GUM_ASSERT(inst->get(v.second).safeName()
338  == (*m)[v.first]->get(v.second).safeName());
339  data.obs().insert(id);
340  break;
341  }
342  }
343 
344  if (!(data.obs().size() && (data.obs().exists(id))))
345  data.inners().insert(id);
346  }
347  }
348 
349  template < typename GUM_SCALAR >
352  Set< Potential< GUM_SCALAR >* >& pool,
353  const Sequence< PRMInstance< GUM_SCALAR >* >& match) {
354  std::pair< Idx, std::string > v;
355  Potential< GUM_SCALAR >* pot = 0;
356 
357  for (const auto inst: match) {
358  for (const auto& elt: *inst) {
359  NodeId id = data.graph.addNode();
360  v = std::make_pair(match.pos(inst), elt.second->safeName());
361  data.map.insert(id, v);
362  data.node2attr.insert(id, __str(inst, elt.second));
363  data.mod.insert(id, elt.second->type()->domainSize());
364  data.vars.insert(id, &(elt.second->type().variable()));
365  pool.insert(
366  const_cast< Potential< GUM_SCALAR >* >(&(elt.second->cpf())));
367  pot =
368  &(const_cast< Potential< GUM_SCALAR >& >(inst->get(v.second).cpf()));
369 
370  for (const auto var: pot->variablesSequence()) {
371  try {
372  if (id != data.vars.first(var))
373  data.graph.addEdge(id, data.vars.first(var));
374  } catch (DuplicateElement&) {
375  } catch (NotFound&) {}
376  }
377 
378  __insertNodeInElimLists(data, match, inst, elt.second, id, v);
379 
380  if (data.inners().exists(id)
381  && (inst->type().containerDag().children(elt.second->id()).size()
382  == 0)
383  && __allInstanceNoRefAttr(data, v))
384  data.barren.insert(id);
385  }
386  }
387 
388  if (!__found_query) {
389  for (const auto mat: data.matches) {
390  if (mat->exists(
391  const_cast< PRMInstance< GUM_SCALAR >* >(__query.first))) {
392  Idx pos =
393  mat->pos(const_cast< PRMInstance< GUM_SCALAR >* >(__query.first));
394  DiscreteVariable& var =
395  match.atPos(pos)->get(__query.second->safeName()).type().variable();
396  NodeId id = data.vars.first(&var);
397  data.barren.erase(id);
398  data.inners().erase(id);
399  data.obs().erase(id);
400  data.outputs().erase(id);
401  data.queries().insert(id);
402  __found_query = true;
403  __query_data = std::make_pair(pos, __query.second->safeName());
404  break;
405  }
406  }
407  }
408  }
409 
410  template < typename GUM_SCALAR >
413  std::pair< Idx, std::string > attr) {
414  for (const auto mat: data.matches)
415  if (mat->atPos(attr.first)
416  ->hasRefAttr(mat->atPos(attr.first)->get(attr.second).id()))
417  return false;
418 
419  return true;
420  }
421 
422  template < typename GUM_SCALAR >
425  Set< Potential< GUM_SCALAR >* >& pool) {
426  Sequence< NodeId > candidates;
427 
428  for (const auto node: data.barren) {
429  for (const auto pot: pool)
430  if (pot->contains(*data.vars.second(node))) {
431  pool.erase(pot);
432  break;
433  }
434 
435  for (const auto nei: data.graph.neighbours(node))
436  if (data.inners().exists(nei)) {
437  try {
438  candidates.insert(nei);
439  } catch (DuplicateElement&) {}
440  }
441  }
442 
443  NodeId node;
444  Potential< GUM_SCALAR >* my_pot = nullptr;
445  short count = 0;
446 
447  while (candidates.size()) {
448  node = candidates.back();
449  candidates.erase(node);
450  count = 0;
451 
452  for (const auto pot: pool) {
453  if (pot->contains(*data.vars.second(node))) {
454  ++count;
455  my_pot = pot;
456  }
457  }
458 
459  if (count == 1) {
460  pool.erase(my_pot);
461  data.barren.insert(node);
462 
463  for (const auto nei: data.graph.neighbours(node)) {
464  if (data.inners().exists(nei)) {
465  try {
466  candidates.insert(nei);
467  } catch (DuplicateElement&) {}
468  }
469  }
470  }
471  }
472  }
473 
474  template < typename GUM_SCALAR >
478  const Set< Potential< GUM_SCALAR >* >& pool,
479  const Sequence< PRMInstance< GUM_SCALAR >* >& match,
480  const std::vector< NodeId >& elim_order) {
481  Set< Potential< GUM_SCALAR >* >* my_pool =
482  new Set< Potential< GUM_SCALAR >* >(pool);
483  std::pair< Idx, std::string > target;
484  size_t end = data.inners().size() + data.obs().size();
485 
486  for (size_t idx = data.inners().size(); idx < end; ++idx) {
487  target = data.map[data.vars.first(data.vars.second(elim_order[idx]))];
488  eliminateNode(&(match[target.first]->get(target.second).type().variable()),
489  *my_pool,
490  __trash);
491  }
492 
493  return my_pool;
494  }
495 
496  template < typename GUM_SCALAR >
500  const Set< Potential< GUM_SCALAR >* >& pool,
501  const Sequence< PRMInstance< GUM_SCALAR >* >& match,
502  const std::vector< NodeId >& elim_order) {
503  Set< Potential< GUM_SCALAR >* >* my_pool =
504  __translatePotSet(data, pool, match);
505  std::pair< Idx, std::string > target;
506  size_t end = data.inners().size() + data.obs().size();
507 
508  for (size_t idx = data.inners().size(); idx < end; ++idx) {
509  target = data.map[data.vars.first(data.vars.second(elim_order[idx]))];
510  eliminateNode(&(match[target.first]->get(target.second).type().variable()),
511  *my_pool,
512  __trash);
513  }
514 
515  return my_pool;
516  }
517 
518  template < typename GUM_SCALAR >
522  const Set< Potential< GUM_SCALAR >* >& pool,
523  const Sequence< PRMInstance< GUM_SCALAR >* >& match) {
524 #ifdef DEBUG
525 
527  data.matches.begin();
528  iter != data.matches.end();
529  ++iter) {
530  GUM_ASSERT((**iter).size() == match.size());
531 
532  for (Size idx = 0; idx < match.size(); ++idx) {
533  GUM_ASSERT((**iter).atPos(idx)->type() == match.atPos(idx)->type());
534  }
535  }
536 
537 #endif
538  Set< Potential< GUM_SCALAR >* >* my_pool =
540  std::pair< Idx, std::string > target;
542  const Sequence< PRMInstance< GUM_SCALAR >* >& source =
543  **(data.matches.begin());
544 
545  for (Size idx = 0; idx < match.size(); ++idx) {
546  __reducedInstances.insert(match[idx]);
547  const auto& chains = source[idx]->type().slotChains();
548 
549  for (const auto sc: chains) {
550 #ifdef DEBUG
551  GUM_ASSERT(!(sc->isMultiple()));
552 #endif
553 
554  try {
555  bij.insert(&(source[idx]
556  ->getInstance(sc->id())
557  .get(sc->lastElt().safeName())
558  .type()
559  .variable()),
560  &(match[idx]
561  ->getInstance(sc->id())
562  .get(sc->lastElt().safeName())
563  .type()
564  .variable()));
565  } catch (DuplicateElement&) {
566  try {
567  if (bij.first(&(match[idx]
568  ->getInstance(sc->id())
569  .get(sc->lastElt().safeName())
570  .type()
571  .variable()))
572  != &(source[idx]
573  ->getInstance(sc->id())
574  .get(sc->lastElt().safeName())
575  .type()
576  .variable())) {
577  delete my_pool;
578  GUM_ERROR(OperationNotAllowed, "fake pattern");
579  }
580  } catch (NotFound&) {
581  delete my_pool;
582  GUM_ERROR(OperationNotAllowed, "fake pattern");
583  }
584  }
585  }
586  }
587 
588  for (const auto p: pool) {
589  for (const auto v: p->variablesSequence()) {
590  try {
591  target = data.map[data.vars.first(v)];
592  bij.insert(
593  v, &(match[target.first]->get(target.second).type().variable()));
594  } catch (NotFound&) {
595  GUM_ASSERT(bij.existsFirst(v));
596  } catch (DuplicateElement&) {}
597  }
598 
599  try {
600  my_pool->insert(copyPotential(bij, *p));
601  } catch (Exception&) {
602  for (const auto pot: *my_pool)
603  delete pot;
604 
605  delete my_pool;
606  GUM_ERROR(OperationNotAllowed, "fake pattern");
607  }
608  }
609 
610  return my_pool;
611  }
612 
613  template < typename GUM_SCALAR >
615  typename StructuredInference< GUM_SCALAR >::RGData& rg_data) {
617  Potential< GUM_SCALAR >* pot = nullptr;
618  PRMInstance< GUM_SCALAR >* inst = nullptr;
619 
620  for (const auto& elt: *this->_sys) {
621  inst = elt.second;
622 
623  if (!__reducedInstances.exists(inst)) {
624  // Checking if its not an empty class
625  if (inst->size()) {
627 
628  try {
629  data = __cdata_map[&(inst->type())];
630  } catch (NotFound&) {
632  __cdata_map.insert(&(inst->type()), data);
633  }
634 
635  data->instances.insert(inst);
636  // Filling up the partial ordering
637  List< NodeSet > partial_order;
638 
639  if (data->inners().size()) partial_order.push_back(data->inners());
640 
641  if (data->aggregators().size())
642  for (const auto agg: data->aggregators())
643  partial_order[0].insert(agg);
644 
645  if (data->outputs().size()) partial_order.push_back(data->outputs());
646 
647  if (__query.first == inst) {
648  // First case, the instance contains the query
649  partial_order[0].erase(__query.second->id());
650 
651  if (partial_order[0].empty()) partial_order.erase(0);
652 
653  if (partial_order.size() > 1) {
654  partial_order[1].erase(__query.second->id());
655 
656  if (partial_order[1].empty()) partial_order.erase(1);
657  }
658 
659  NodeSet query_set;
660  query_set.insert(__query.second->id());
661  partial_order.insert(query_set);
662 
663  // Adding the potentials
664  for (auto attr = inst->begin(); attr != inst->end(); ++attr)
665  pool.insert(&(
666  const_cast< Potential< GUM_SCALAR >& >((*(attr.val())).cpf())));
667 
668  // Adding evidences if any
669  if (this->hasEvidence(inst))
670  for (const auto& elt: this->evidence(inst))
671  pool.insert(const_cast< Potential< GUM_SCALAR >* >(elt.second));
672 
674  &(data->moral_graph), &(data->mods), &(partial_order));
675  const std::vector< NodeId >& v = t.eliminationOrder();
676 
677  if (partial_order.size() > 1)
678  for (size_t idx = 0; idx < partial_order[0].size(); ++idx)
680  &(inst->get(v[idx]).type().variable()), pool, __trash);
681  } else if (this->hasEvidence(inst)) {
682  // Second case, the instance has evidences
683  // Adding the potentials
684  for (const auto elt: *inst)
685  pool.insert(
686  &const_cast< Potential< GUM_SCALAR >& >(elt.second->cpf()));
687 
688  // Adding evidences
689  for (const auto& elt: this->evidence(inst))
690  pool.insert(const_cast< Potential< GUM_SCALAR >* >(elt.second));
691 
693  &(data->moral_graph), &(data->mods), &(partial_order));
694 
695  for (size_t idx = 0; idx < partial_order[0].size(); ++idx)
697  &(inst->get(t.eliminationOrder()[idx]).type().variable()),
698  pool,
699  __trash);
700  } else {
701  // Last cast, the instance neither contains evidences nor
702  // instances
703  // We translate the class level potentials into the instance ones
704  // and
705  // proceed with elimination
706  for (const auto srcPot: data->pool) {
707  pot = copyPotential(inst->bijection(), *srcPot);
708  pool.insert(pot);
709  __trash.insert(pot);
710  }
711 
712  for (const auto agg: data->c.aggregates())
713  pool.insert(&(const_cast< Potential< GUM_SCALAR >& >(
714  inst->get(agg->id()).cpf())));
715 
716  // We eliminate inner aggregators with their parents if necessary
717  // (see
718  // CData constructor)
719  Size size = data->inners().size() + data->aggregators().size();
720 
721  for (size_t idx = data->inners().size(); idx < size; ++idx)
723  &(inst->get(data->elim_order()[idx]).type().variable()),
724  pool,
725  __trash);
726  }
727 
728  for (const auto pot: pool)
729  rg_data.pool.insert(pot);
730  }
731  }
732  }
733  }
734 
735  template < typename GUM_SCALAR >
738  // We first add edges between variables already in pool (i.e. those of the
739  // reduced instances)
740  NodeId id_1, id_2;
741 
742  for (const auto pot: data.pool) {
743  const Sequence< const DiscreteVariable* >& vars = pot->variablesSequence();
744 
745  for (Size var_1 = 0; var_1 < vars.size(); ++var_1) {
746  if (data.var2node.existsFirst(vars.atPos(var_1))) {
747  id_1 = data.var2node.second(vars.atPos(var_1));
748  } else {
749  id_1 = data.reducedGraph.addNode();
750  data.var2node.insert(vars.atPos(var_1), id_1);
751  data.mods.insert(id_1, vars.atPos(var_1)->domainSize());
752  data.outputs().insert(id_1);
753  }
754 
755  for (Size var_2 = var_1 + 1; var_2 < vars.size(); ++var_2) {
756  if (data.var2node.existsFirst(vars.atPos(var_2))) {
757  id_2 = data.var2node.second(vars.atPos(var_2));
758  } else {
759  id_2 = data.reducedGraph.addNode();
760  data.var2node.insert(vars.atPos(var_2), id_2);
761  data.mods.insert(id_2, vars.atPos(var_2)->domainSize());
762  data.outputs().insert(id_2);
763  }
764 
765  try {
766  data.reducedGraph.addEdge(id_1, id_2);
767  } catch (DuplicateElement&) {}
768  }
769  }
770  }
771 
772  // Adding potentials obtained from reduced patterns
773  for (const auto& elt: __elim_map) {
774  // We add edges between variables in the same reduced patterns
775  for (const auto pot: *elt.second) {
776  data.pool.insert(pot);
778  pot->variablesSequence();
779 
780  for (Size var_1 = 0; var_1 < vars.size(); ++var_1) {
781  if (data.var2node.existsFirst(vars.atPos(var_1))) {
782  id_1 = data.var2node.second(vars.atPos(var_1));
783  } else {
784  id_1 = data.reducedGraph.addNode();
785  data.var2node.insert(vars.atPos(var_1), id_1);
786  data.mods.insert(id_1, vars.atPos(var_1)->domainSize());
787  data.outputs().insert(id_1);
788  }
789 
790  for (Size var_2 = var_1 + 1; var_2 < vars.size(); ++var_2) {
791  if (data.var2node.existsFirst(vars.atPos(var_2))) {
792  id_2 = data.var2node.second(vars.atPos(var_2));
793  } else {
794  id_2 = data.reducedGraph.addNode();
795  data.var2node.insert(vars.atPos(var_2), id_2);
796  data.mods.insert(id_2, vars.atPos(var_2)->domainSize());
797  data.outputs().insert(id_2);
798  }
799 
800  try {
801  data.reducedGraph.addEdge(id_1, id_2);
802  } catch (DuplicateElement&) {}
803  }
804  }
805  }
806  }
807  }
808 
809  template < typename GUM_SCALAR >
812  partial_order.insert(NodeSet());
813  partial_order.insert(NodeSet());
814  }
815 
816  template < typename GUM_SCALAR >
818  const gspan::Pattern& p,
820  pattern(p),
821  matches(m), __real_order(0) {
823 
824  for (int i = 0; i < 4; ++i)
825  __partial_order.push_front(NodeSet());
826  }
827 
828  template < typename GUM_SCALAR >
830  const typename StructuredInference< GUM_SCALAR >::PData& source) :
831  pattern(source.pattern),
832  matches(source.matches), graph(source.graph), mod(source.mod),
833  node2attr(source.node2attr), vars(source.vars),
836  }
837 
838  template < typename GUM_SCALAR >
839  const List< NodeSet >*
841  if (!__real_order) {
843 
844  for (const auto set: __partial_order)
845  if (set.size() > 0) __real_order->insert(set);
846  }
847 
848  return __real_order;
849  }
850 
851  template < typename GUM_SCALAR >
853  const PRMClass< GUM_SCALAR >& a_class) :
854  c(a_class),
855  __elim_order(0) {
857 
858  // First step we add Attributes and Aggregators
859  for (const auto node: c.containerDag().nodes()) {
860  switch (c.get(node).elt_type()) {
862  pool.insert(
863  &(const_cast< Potential< GUM_SCALAR >& >(c.get(node).cpf())));
864  // break omited : We want to execute the next block
865  // for attributes
866  }
867 
870  mods.insert(node, c.get(node).type()->domainSize());
871  break;
872  }
873 
874  default: { /* do nothing */
875  }
876  }
877  }
878 
879  // Second, we add edges, moralise the graph and build the partial ordering
880  for (const auto node: moral_graph.nodes()) {
881  const auto& parents = c.containerDag().parents(node);
882 
883  // Adding edges and marrying parents
884  for (auto tail = parents.begin(); tail != parents.end(); ++tail) {
887  moral_graph.addEdge(*tail, node);
888  NodeSet::const_iterator marry = tail;
889  ++marry;
890 
891  while (marry != parents.end()) {
894  moral_graph.addEdge(*tail, *marry);
895 
896  ++marry;
897  }
898  }
899  }
900 
901  // Adding nodes to the partial ordering
902  switch (c.get(node).elt_type()) {
904  if (c.isOutputNode(c.get(node)))
905  outputs().insert(node);
906  else
907  aggregators().insert(node);
908 
909  // If the aggregators is not an output and have parents which are
910  // not outputs, we must eliminate the parents after adding the
911  // aggregator's CPT
912  for (const auto par: c.containerDag().parents(node)) {
913  const auto& prnt = c.get(par);
914 
915  if ((!c.isOutputNode(prnt))
918  inners().erase(prnt.id());
919  aggregators().insert(prnt.id());
920  }
921  }
922 
923  break;
924  }
925 
927  pool.insert(
928  const_cast< Potential< GUM_SCALAR >* >(&(c.get(node).cpf())));
929 
930  if (c.isOutputNode(c.get(node)))
931  outputs().insert(node);
932  else if (!aggregators().exists(node))
933  inners().insert(node);
934 
935  break;
936  }
937 
938  default: { /* Do nothing */
939  }
940  }
941  }
942 
943  if (inners().size()) partial_order.insert(inners());
944 
945  if (aggregators().size()) partial_order.insert(aggregators());
946 
947  if (outputs().size()) partial_order.insert(outputs());
948 
949  GUM_ASSERT(partial_order.size());
951  __elim_order = t.eliminationOrder();
952 
953  for (size_t i = 0; i < inners().size(); ++i)
954  eliminateNode(&(c.get(__elim_order[i]).type().variable()), pool, __trash);
955  }
956 
957  template < typename GUM_SCALAR >
960 
961  for (const auto pot: __trash)
962  delete pot;
963  }
964 
965  template < typename GUM_SCALAR >
967  const PRMInstance< GUM_SCALAR >* i = (this->_sys->begin()).val();
968  __query = std::make_pair(i, i->begin().val());
969  __found_query = false;
971  __buildReduceGraph(data);
972  }
973 
974  template < typename GUM_SCALAR >
976  __mining = b;
977  }
978 
979  template < typename GUM_SCALAR >
981  const PRMInstance< GUM_SCALAR >* i,
982  const PRMAttribute< GUM_SCALAR >* a) const {
983  return i->name() + __dot + a->safeName();
984  }
985 
986  template < typename GUM_SCALAR >
988  const PRMInstance< GUM_SCALAR >* i,
989  const PRMAttribute< GUM_SCALAR >& a) const {
990  return i->name() + __dot + a.safeName();
991  }
992 
993  template < typename GUM_SCALAR >
995  const PRMInstance< GUM_SCALAR >* i,
996  const PRMSlotChain< GUM_SCALAR >& a) const {
997  return i->name() + __dot + a.lastElt().safeName();
998  }
999 
1000  template < typename GUM_SCALAR >
1003  }
1004 
1005  template < typename GUM_SCALAR >
1008  }
1009 
1010  template < typename GUM_SCALAR >
1011  INLINE std::string StructuredInference< GUM_SCALAR >::name() const {
1012  return "StructuredInference";
1013  }
1014 
1015  template < typename GUM_SCALAR >
1017  return *__gspan;
1018  }
1019 
1020  template < typename GUM_SCALAR >
1021  INLINE const GSpan< GUM_SCALAR >&
1023  return *__gspan;
1024  }
1025 
1026  template < typename GUM_SCALAR >
1029  NodeId id,
1031  data.graph.eraseNode(id);
1032  GUM_ASSERT(!data.graph.exists(id));
1033  data.mod.erase(id);
1034  GUM_ASSERT(!data.mod.exists(id));
1035  data.node2attr.eraseFirst(id);
1036  GUM_ASSERT(!data.node2attr.existsFirst(id));
1037  data.map.erase(id);
1038  GUM_ASSERT(!data.map.exists(id));
1039  data.vars.eraseFirst(id);
1040  GUM_ASSERT(!data.vars.existsFirst(id));
1041  data.inners().erase(id);
1042  GUM_ASSERT(!data.inners().exists(id));
1043  pool.erase(data.pots[id]);
1044  GUM_ASSERT(!pool.exists(data.pots[id]));
1045  data.pots.erase(id);
1046  GUM_ASSERT(!data.pots.exists(id));
1047  }
1048 
1049  } /* namespace prm */
1050 } /* 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-2020 Pierre-Henri WUILLEMIN () et Christophe GONZALES () info_at_agrum_dot_org.
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:658
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-2020 Pierre-Henri WUILLEMIN () et Christophe GONZALES () info_at_agrum_dot_org.
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:519
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:609
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:703
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:615
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