aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
SVED_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief Inline implementation of SVED.
25  *
26  * @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 #include <agrum/PRM/inference/SVED.h>
29 
30 namespace gum {
31  namespace prm {
32 
33  template < typename GUM_SCALAR >
34  SVED< GUM_SCALAR >::~SVED() {
36 
37  for (const auto& elt: _elim_orders_)
38  delete elt.second;
39 
40  if (_class_elim_order_ != nullptr) delete _class_elim_order_;
41  }
42 
43  template < typename GUM_SCALAR >
45  NodeId node,
46  BucketSet& pool,
47  BucketSet& trash) {
48  Set< const PRMInstance< GUM_SCALAR >* > ignore;
50  // Extracting required attributes and slotchains
53  // Downward elimination
54  List< const PRMInstance< GUM_SCALAR >* > elim_list;
55 
56  for (const auto attr: attr_set) {
57  try {
58  for (auto iter = query->getRefAttr(attr).begin(); iter != query->getRefAttr(attr).end();
59  ++iter)
60  if ((!ignore.exists(iter->first)) && (_bb_.exists(iter->first)))
62  } catch (NotFound&) {
63  // Ok
64  }
65  }
66 
67  // Eliminating all nodes in query instance, except query
71 
73 
74  for (const auto attr: attr_set)
75  pool.insert(&(const_cast< Potential< GUM_SCALAR >& >(query->get(attr).cpf())));
76 
77  for (size_t idx = 0; idx < t.eliminationOrder().size(); ++idx) {
78  if (t.eliminationOrder()[idx] != node) {
79  auto var_id = t.eliminationOrder()[idx];
80  const auto& var = bn.variable(var_id);
82  }
83  }
84 
86  // Eliminating instance in elim_list
87  List< const PRMInstance< GUM_SCALAR >* > tmp_list;
89 
90  while (!elim_list.empty()) {
94  } else if (_bb_.exists(elim_list.front())) {
96  }
97 
99  }
100 
101  // Upward elimination
102  for (const auto chain: sc_set)
103  for (const auto parent: query->getInstances(chain))
104  if ((!ignore.exists(parent)) && (_bb_.exists(*parent)))
106  }
107 
108  template < typename GUM_SCALAR >
110  const PRMInstance< GUM_SCALAR >* from,
111  const PRMInstance< GUM_SCALAR >* i,
112  BucketSet& pool,
113  BucketSet& trash,
114  List< const PRMInstance< GUM_SCALAR >* >& elim_list,
115  Set< const PRMInstance< GUM_SCALAR >* >& ignore) {
116  ignore.insert(i);
117  // Extracting required attributes and slotchains
119  Set< NodeId >& sc_set = _getSCSet_(i);
120  // Calling elimination over child instance
121  List< const PRMInstance< GUM_SCALAR >* > my_list;
122 
123  for (const auto attr: attr_set) {
124  try {
125  for (auto iter = i->getRefAttr(attr).begin(); iter != i->getRefAttr(attr).end(); ++iter)
126  if ((!ignore.exists(iter->first)) && (_bb_.exists(iter->first)))
128  } catch (NotFound&) {
129  // Ok
130  }
131  }
132 
133  // Eliminating all nodes in current instance
134  if (this->hasEvidence(i)) {
136  } else {
138 
139  for (const auto agg: i->type().aggregates())
141 
142  try {
145 
146  for (auto node: _getElimOrder_(i->type())) {
147  const auto& var = bn.variable(node);
149  }
150 
152  } catch (NotFound&) {
153  // Raised if there is no inner nodes to eliminate
154  }
155  }
156 
157  // Calling elimination over child's parents
158  while (!my_list.empty()) {
159  if (_checkElimOrder_(i, my_list.front())) {
160  if ((!ignore.exists(my_list.front())) && (_bb_.exists(my_list.front())))
162  } else if (_bb_.exists(my_list.front())) {
164  }
165 
166  my_list.popFront();
167  }
168 
169  // Adding parents instance to elim_list
170  for (const auto chain: sc_set)
171  for (const auto parent: i->getInstances(chain))
172  if ((!ignore.exists(parent)) && _bb_.exists(parent) && (parent != from))
174  }
175 
176  template < typename GUM_SCALAR >
178  const PRMInstance< GUM_SCALAR >* i,
179  BucketSet& pool,
180  BucketSet& trash,
181  List< const PRMInstance< GUM_SCALAR >* >& elim_list,
182  Set< const PRMInstance< GUM_SCALAR >* >& ignore) {
183  ignore.insert(i);
184  // Extracting required attributes and slotchains
186  Set< NodeId >& sc_set = _getSCSet_(i);
187 
188  // Downward elimination
189  for (const auto attr: attr_set) {
190  try {
191  for (auto iter = i->getRefAttr(attr).begin(); iter != i->getRefAttr(attr).end(); ++iter)
192  if ((!ignore.exists(iter->first)) && (_bb_.exists(iter->first)))
194  } catch (NotFound&) {
195  // Ok
196  }
197  }
198 
199  // Eliminating all nodes in i instance
200  if (this->hasEvidence(i)) {
202  } else {
204 
205  for (const auto agg: i->type().aggregates())
207 
208  try {
211 
212  for (auto node: _getElimOrder_(i->type())) {
213  const auto& var = bn.variable(node);
215  }
217  } catch (NotFound&) {
218  // Raised if there is no inner nodes to eliminate
219  }
220  }
221 
222  // Eliminating instance in elim_list
223  List< const PRMInstance< GUM_SCALAR >* > tmp_list;
224 
225  while (!elim_list.empty()) {
226  if (_checkElimOrder_(i, elim_list.front())) {
229  } else if (_bb_.exists(elim_list.front())) {
231  }
232 
234  }
235 
236  // Upward elimination
237  for (const auto chain: sc_set)
238  for (const auto parent: i->getInstances(chain))
239  if ((!ignore.exists(parent)) && (_bb_.exists(parent)))
241  }
242 
243  template < typename GUM_SCALAR >
245  BucketSet& pool,
246  BucketSet& trash) {
247  // Adding required evidences
248  for (const auto& elt: this->evidence(i))
250  pool.insert(const_cast< Potential< GUM_SCALAR >* >(elt.second));
251 
252  // Adding potentials and eliminating the remaining nodes
253  for (const auto& a: *i)
255  pool.insert(&(const_cast< Potential< GUM_SCALAR >& >(a.second->cpf())));
256 
260 
261  for (auto var = full_elim_order.begin(); var != full_elim_order.end(); ++var)
262  eliminateNode(&(i->get(*var).type().variable()), pool, trash);
263  }
264 
265  template < typename GUM_SCALAR >
267  BucketSet& pool,
268  BucketSet& trash) {
269  BucketSet* lifted_pool = nullptr;
270 
271  try {
273  } catch (NotFound&) {
276  }
277 
278  for (const auto lifted_pot: *lifted_pool) {
280  pool.insert(pot);
281  trash.insert(pot);
282  }
283  }
284 
285  template < typename GUM_SCALAR >
287  BucketSet& trash) {
288  PRMClass< GUM_SCALAR >& c = const_cast< PRMClass< GUM_SCALAR >& >(i->type());
291 
292  for (const auto node: _bb_.requisiteNodes(i))
294  lifted_pool->insert(const_cast< Potential< GUM_SCALAR >* >(&(c.get(node).cpf())));
295 
297 
298  for (const auto& elt: *i) {
299  if (_bb_.requisiteNodes(*i).exists(elt.first)) {
301  if (c.isOutputNode(c.get(elt.first)))
303  else if (!outers.exists(elt.first))
305  } else if (PRMClassElement< GUM_SCALAR >::isAggregate(c.get(elt.first))) {
307 
308  // We need to put in the output_elim_order aggregator's parents
309  // which are
310  // innner nodes
311  for (const auto par: c.containerDag().parents(elt.first))
313  && i->type().isInnerNode(i->type().get(par))
314  && _bb_.requisiteNodes(i).exists(par)) {
315  inners.erase(par);
316  outers.insert(par);
317  }
318  }
319  } else {
321  }
322  }
323 
324  // Now we proceed with the elimination of inner attributes
327 
329 
331 
333 
334  GUM_ASSERT(inners.size() || outers.size());
336 
337  for (size_t idx = 0; idx < inners.size(); ++idx)
339 
340  // If there is not only inner and input Attributes
341  if (outers.size()) {
344  t.eliminationOrder().end()));
345  }
346  }
347 
348  template < typename GUM_SCALAR >
352  std::list< NodeId > l;
353 
354  for (const auto node: cdg.dag().nodes()) {
355  if (cdg.dag().parents(node).empty()) { l.push_back(node); }
356  }
357 
359 
360  while (!l.empty()) {
362 
365  }
366 
367  for (const auto child: cdg.dag().children(l.front())) {
369  }
370 
371  l.pop_front();
372  }
373 
375  for (auto c: class_elim_order) {
376  std::string name = c->name();
377  auto pos = name.find_first_of("<");
378  if (pos != std::string::npos) { name = name.substr(0, pos); }
379  try {
381  } catch (DuplicateElement&) {}
382  }
383  }
384 
385  template < typename GUM_SCALAR >
387  const PRMInstance< GUM_SCALAR >* i = chain.first;
388  const PRMAttribute< GUM_SCALAR >* elt = chain.second;
390  _bb_.compute(i, elt->id());
392 
393  std::vector< const Potential< GUM_SCALAR >* > result;
394  for (auto pot: pool) {
396  }
397 
398  while (result.size() > 1) {
399  const auto& p1 = *(result.back());
400  result.pop_back();
401  const auto& p2 = *(result.back());
402  result.pop_back();
403  auto mult = new Potential< GUM_SCALAR >(p1 * p2);
405  trash.insert(mult);
406  }
407 
408  m = *(result.back());
409  m.normalize();
410 
411  GUM_ASSERT(m.nbrDim() == (Size)1);
412 
413  // cleaning up the mess
414  for (const auto pot: trash)
415  delete pot;
416 
417  for (const auto& elt: _lifted_pools_)
418  delete elt.second;
419 
421 
422  for (const auto& elt: _req_set_) {
423  delete elt.second.first;
424  delete elt.second.second;
425  }
426 
427  _req_set_.clear();
428 
429  for (const auto elt: _elim_orders_)
430  delete elt.second;
431 
433  }
434 
435  template < typename GUM_SCALAR >
436  void SVED< GUM_SCALAR >::joint_(const std::vector< Chain >& queries,
437  Potential< GUM_SCALAR >& j) {
438  GUM_ERROR(FatalError, "Not implemented.")
439  }
440 
441  template < typename GUM_SCALAR >
443  Set< NodeId >* attr_set = new Set< NodeId >();
444  Set< NodeId >* sc_set = new Set< NodeId >();
445 
446  for (const auto node: _bb_.requisiteNodes(i)) {
447  switch (i->type().get(node).elt_type()) {
450  attr_set->insert(node);
451  break;
452  }
453 
455  sc_set->insert(node);
456  break;
457  }
458 
459  default: {
461  "There should not be elements other"
462  " than PRMAttribute<GUM_SCALAR> and SlotChain.");
463  }
464  }
465  }
466 
468  std::pair< Set< NodeId >*, Set< NodeId >* >(attr_set, sc_set));
469  }
470 
471  template < typename GUM_SCALAR >
473  const PRMSystem< GUM_SCALAR >& model) :
475  _class_elim_order_(0), _bb_(*this) {
477  }
478 
479 
480  template < typename GUM_SCALAR >
482  BucketSet& pool) {
483  for (const auto& elt: this->evidence(i))
484  pool.insert(const_cast< Potential< GUM_SCALAR >* >(elt.second));
485  }
486 
487  template < typename GUM_SCALAR >
488  INLINE std::vector< NodeId >&
490  return *(_elim_orders_[&c]);
491  }
492 
493  template < typename GUM_SCALAR >
495  auto pos = s.find_first_of("<");
496  if (pos != std::string::npos) { return s.substr(0, pos); }
497  return s;
498  }
499 
500  template < typename GUM_SCALAR >
502  const PRMInstance< GUM_SCALAR >* second) {
503  if (_class_elim_order_ == 0) { _initElimOrder_(); }
504 
505  auto first_name = _trim_(first->type().name());
506  auto second_name = _trim_(second->type().name());
508  }
509 
510  template < typename GUM_SCALAR >
513  const PRMAggregate< GUM_SCALAR >* agg) {
514  return &(const_cast< Potential< GUM_SCALAR >& >(i->get(agg->safeName()).cpf()));
515  }
516 
517  template < typename GUM_SCALAR >
518  INLINE void
520  // Do nothing
521  }
522 
523  template < typename GUM_SCALAR >
524  INLINE void
526  // Do nothing
527  }
528 
529  template < typename GUM_SCALAR >
531  try {
532  return *(_req_set_[&(_bb_.requisiteNodes(i))].first);
533  } catch (NotFound&) {
534  _initReqSets_(i);
535  return *(_req_set_[&(_bb_.requisiteNodes(i))].first);
536  }
537  }
538 
539  template < typename GUM_SCALAR >
541  try {
542  return *(_req_set_[&(_bb_.requisiteNodes(i))].second);
543  } catch (NotFound&) {
544  _initReqSets_(i);
545  return *(_req_set_[&(_bb_.requisiteNodes(i))].second);
546  }
547  }
548 
549  template < typename GUM_SCALAR >
550  INLINE void
552  List< const PRMInstance< GUM_SCALAR >* >& elim_list,
553  List< const PRMInstance< GUM_SCALAR >* >& reduced_list,
554  Set< const PRMInstance< GUM_SCALAR >* >& ignore,
555  BucketSet& pool,
556  BucketSet& trash) {
557  while (!elim_list.empty()) {
558  if (_checkElimOrder_(i, elim_list.front())) {
559  if ((!ignore.exists(elim_list.front())) && (_bb_.exists(elim_list.front()))) {
561  }
562  } else if (_bb_.exists(elim_list.front())) {
564  }
565 
567  }
568  }
569 
570  template < typename GUM_SCALAR >
572  return "SVED";
573  }
574 
575  } /* namespace prm */
576 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)