aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
interfaceGraph_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 gum::InterfaceGraph.
25  *
26  * @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 namespace gum {
30  namespace prm {
31  namespace gspan {
32 
33  // NodeData
34 
35  template < typename GUM_SCALAR >
36  INLINE NodeData< GUM_SCALAR >::NodeData() : n(0), l(0) {
38  }
39 
40  template < typename GUM_SCALAR >
42  n(from.n), l(from.l) {
44  }
45 
46  template < typename GUM_SCALAR >
49  }
50 
51  template < typename GUM_SCALAR >
52  INLINE bool NodeData< GUM_SCALAR >::operator==(const NodeData< GUM_SCALAR >& from) const {
53  return (n == from.n) && (l == from.l);
54  }
55 
56  template < typename GUM_SCALAR >
57  INLINE bool NodeData< GUM_SCALAR >::operator!=(const NodeData< GUM_SCALAR >& from) const {
58  return (n != from.n) && (l != from.l);
59  }
60 
61  // EdgeData<GUM_SCALAR>
62 
63  template < typename GUM_SCALAR >
64  INLINE EdgeData< GUM_SCALAR >::EdgeData() : u(0), v(0), l(0) {
66  }
67 
68  template < typename GUM_SCALAR >
70  u(from.u), v(from.v), l(from.l) {
72  }
73 
74  template < typename GUM_SCALAR >
77  }
78 
79  template < typename GUM_SCALAR >
80  INLINE bool EdgeData< GUM_SCALAR >::operator==(const EdgeData< GUM_SCALAR >& from) const {
81  return (u == from.u) && (l_u == from.l_u) && (v == from.v) && (l_v == from.l_v)
82  && (l == from.l);
83  }
84 
85  template < typename GUM_SCALAR >
86  INLINE bool EdgeData< GUM_SCALAR >::operator!=(const EdgeData< GUM_SCALAR >& from) const {
87  return (u != from.u) && (l_u != from.l_u) && (v != from.v) && (l_v != from.l_v)
88  && (l != from.l);
89  }
90 
91  // InterfaceGraph
92 
93  template < typename GUM_SCALAR >
95  _sys_(&sys), _labels_(new Bijection< Idx, LabelData* >()), _counter_(0),
96  _erase_flag_(true) {
99 
100  // We need to add each instance in _graph_
101  for (auto iter = sys.begin(); iter != sys.end(); ++iter) {
102  NodeData< GUM_SCALAR >* node = new NodeData< GUM_SCALAR >();
103  node->n = iter.val();
106  _idMap_.insert(node->n, iter.key());
107  _nodes_.insert(iter.key(), node);
108  }
109 
110  NodeData< GUM_SCALAR >* u = nullptr;
111  NodeData< GUM_SCALAR >* v = nullptr;
112 
113  for (const auto& elt: _nodes_) {
115 
116  for (const auto chain: data->n->type().slotChains()) {
117  for (const auto inst: data->n->getInstances(chain->id())) {
118  u = (_nodes_[_idMap_[inst]]->l < data->l) ? _nodes_[_idMap_[inst]] : data;
119  v = (u != data) ? data : _nodes_[_idMap_[inst]];
120 
121  if (!_graph_.existsEdge(_idMap_[u->n], _idMap_[v->n])) {
122  EdgeData< GUM_SCALAR >* edge = new EdgeData< GUM_SCALAR >();
123  edge->u = u->n;
124  edge->l_u = u->l;
125  edge->v = v->n;
126  edge->l_v = v->l;
130  }
131  }
132  }
133  }
134  }
135 
136  template < typename GUM_SCALAR >
142  _erase_flag_(false) {
144  }
145 
146  template < typename GUM_SCALAR >
149 
150  if (_erase_flag_) {
151  for (const auto& elt: _nodes_)
152  delete elt.second;
153 
154  for (const auto& elt: _edges_)
155  delete elt.second;
156 
157  for (const auto& elt: _nodeMap_) {
158  delete elt.first;
159  delete elt.second;
160  }
161 
162  for (const auto& elt: _edgeMap_) {
163  delete elt.first;
164  delete elt.second;
165  }
166  }
167 
168  delete _labels_;
169  }
170 
171  template < typename GUM_SCALAR >
174  GUM_ERROR(FatalError, "not implemented")
175  }
176 
177  template < typename GUM_SCALAR >
180  Size size = Size(1);
182  sBuff << node->n->type().name();
183 
184  // First we search for multiple inputs
185  for (const auto chain: node->n->type().slotChains()) {
186  if (chain->isMultiple()) {
187  sBuff << "-" << node->n->getInstances(chain->id()).size();
188  sBuff << chain->name();
189  size *= node->n->getInstances(chain->id()).size()
190  * chain->lastElt().type().variable().domainSize();
191  } else {
193  }
194  }
195 
196  // Second we search for active outputs
197  for (const auto nn: node->n->type().containerDag().nodes()) {
198  if (node->n->type().isOutputNode(node->n->type().get(nn))) {
199  try {
200  sBuff << "-" << node->n->getRefAttr(nn).size() << node->n->get(nn).name();
201  size *= node->n->get(nn).type().variable().domainSize();
202  } catch (NotFound&) {
203  // (nn) is an inactive output node
204  }
205  }
206  }
207 
208  // Label is ready
209  if (!label_map.exists(sBuff.str())) {
210  LabelData* label = new LabelData();
212  label->id = ++_counter_;
213  label->tree_width = size;
214  label->l = sBuff.str();
216  _nodeMap_.insert(label, new Set< NodeData< GUM_SCALAR >* >());
217  }
218 
219  node->l = label_map[sBuff.str()];
220  _nodeMap_[node->l]->insert(node);
221  }
222 
223  template < typename GUM_SCALAR >
226  Size size = Size(1);
228  sBuff << edge->u->type().name() << "-" << edge->v->type().name();
229 
230  // First looking for edge->u output nodes in v
231  for (const auto chain: edge->u->type().slotChains()) {
232  if (edge->u->getInstances(chain->id()).exists(edge->v)) {
233  sBuff << "-" << edge->v->type().name() << "." << chain->lastElt().name();
235  }
236  }
237 
238  // Second looking for edge->v output nodes in u
239  for (const auto chain: edge->v->type().slotChains())
240  if (edge->v->getInstances(chain->id()).exists(edge->u)) {
241  sBuff << "-" << edge->u->type().name() << "." << chain->lastElt().name();
243  }
244 
245  // Label is ready
246  if (!label_map.exists(sBuff.str())) {
247  LabelData* label = new LabelData();
249  label->id = ++_counter_;
250  label->l = sBuff.str();
251  label->tree_width = size;
253  _edgeMap_.insert(label, new Set< EdgeData< GUM_SCALAR >* >());
254  }
255 
256  edge->l = label_map[sBuff.str()];
257  _edgeMap_[edge->l]->insert(edge);
258  }
259 
260  template < typename GUM_SCALAR >
262  return _graph_;
263  }
264 
265  template < typename GUM_SCALAR >
267  return _graph_;
268  }
269 
270  template < typename GUM_SCALAR >
272  return *_labels_;
273  }
274 
275  template < typename GUM_SCALAR >
277  return *_labels_;
278  }
279 
280  template < typename GUM_SCALAR >
282  try {
283  return _nodeMap_[const_cast< LabelData* >(l)]->size();
284  } catch (NotFound&) { return _edgeMap_[const_cast< LabelData* >(l)]->size(); }
285  }
286 
287  template < typename GUM_SCALAR >
288  INLINE Set< NodeData< GUM_SCALAR >* >&
290  return *(_nodeMap_[const_cast< LabelData* >(l)]);
291  }
292 
293  template < typename GUM_SCALAR >
294  INLINE const Set< NodeData< GUM_SCALAR >* >&
296  return *(_nodeMap_[const_cast< LabelData* >(l)]);
297  }
298 
299  template < typename GUM_SCALAR >
300  INLINE Set< EdgeData< GUM_SCALAR >* >&
302  return *(_edgeMap_[const_cast< LabelData* >(l)]);
303  }
304 
305  template < typename GUM_SCALAR >
306  INLINE const Set< EdgeData< GUM_SCALAR >* >&
308  return *(_edgeMap_[const_cast< LabelData* >(l)]);
309  }
310 
311  template < typename GUM_SCALAR >
313  return _labels_->second(id);
314  }
315 
316  template < typename GUM_SCALAR >
318  return _idMap_[const_cast< PRMInstance< GUM_SCALAR >* >(&i)];
319  }
320 
321  template < typename GUM_SCALAR >
323  return _idMap_[const_cast< PRMInstance< GUM_SCALAR >* >(i)];
324  }
325 
326  template < typename GUM_SCALAR >
329  return node(id(i));
330  }
331 
332  template < typename GUM_SCALAR >
333  INLINE const NodeData< GUM_SCALAR >&
335  return node(id(i));
336  }
337 
338  template < typename GUM_SCALAR >
340  return *(_nodes_[id]);
341  }
342 
343  template < typename GUM_SCALAR >
345  return *(_nodes_[id]);
346  }
347 
348  template < typename GUM_SCALAR >
350  try {
351  return *(_edges_[Edge(u, v)]);
352  } catch (NotFound&) { return *(_edges_[Edge(v, u)]); }
353  }
354 
355  template < typename GUM_SCALAR >
357  NodeId v) const {
358  try {
359  return *(_edges_[Edge(u, v)]);
360  } catch (NotFound&) { return *(_edges_[Edge(v, u)]); }
361  }
362 
363  template < typename GUM_SCALAR >
365  out << data.n->name() << "(" << data.l->l << ")";
366  return out;
367  }
368 
369  template < typename GUM_SCALAR >
371  out << data.u->name() << " -> " << data.v->name() << "(" << data.l->l << ")";
372  return out;
373  }
374 
375  } /* namespace gspan */
376  } /* namespace prm */
377 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)
INLINE std::ostream & operator<<(std::ostream &out, const EdgeData< GUM_SCALAR > &data)
Print a EdgeData<GUM_SCALAR> in out.