aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
pattern.cpp
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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 Implementation of the Pattern class.
25  *
26  * @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 #include <agrum/PRM/gspan/pattern.h>
30 
31 #ifdef GUM_NO_INLINE
32 # include <agrum/PRM/gspan/pattern_inl.h>
33 #endif // GUM_NO_INLINE
34 
35 namespace gum {
36  namespace prm {
37  namespace gspan {
38 
42 
43  for (NodeId node = 1; node <= source.size(); ++node) {
45  node,
46  addNodeWithLabel(const_cast< LabelData& >(source.label(node))));
47  }
48 
49  for (const auto& edge: source.code().codes)
51  node_map[edge->j],
52  const_cast< LabelData& >(
54  }
55 
56  bool Pattern::isMinimal() {
57  for (const auto node: nodes()) {
58  for (const auto next: parents(node)) {
59  Size u = label(node).id;
60  Size v = label(next).id;
61  EdgeCode edge_code(1, 2, u, label(next, node).id, v);
62 
63  if (edge_code < *(code().codes.front())) {
64  return false;
65  } else if (edge_code == (*code().codes.front())) {
66  if (expandCodeIsMinimal__(node, next)) { return false; }
67  }
68  }
69 
70  for (const auto next: children(node)) {
71  Size u = label(node).id;
72  Size v = label(next).id;
73  EdgeCode edge_code(1, 2, u, label(node, next).id, v);
74 
75  if (edge_code < *(code().codes.front())) {
76  return false;
77  } else if (edge_code == (*code().codes.front())) {
78  if (expandCodeIsMinimal__(node, next)) { return false; }
79  }
80  }
81  }
82 
83  return true;
84  }
85 
88  sBuff << "digraph " << name << " {\n";
89 
90  for (const auto& arc: arcs()) {
91  sBuff << label(arc.tail()).id << " -> ";
92  sBuff << label(arc.head()).id << ";\n";
93  }
94 
95  sBuff << "}\n";
96  return sBuff.str();
97  }
98 
101  Pattern p;
104 
105  try {
106  p.addArc(1, 2, label(u, v));
107  } catch (NotFound&) { p.addArc(1, 2, label(v, u)); }
108 
109  for (const auto nei: children(u))
110  if (nei != v)
111  if (rec__(p, node_map, u, nei)) return true;
112 
113  for (const auto nei: parents(u))
114  if (nei != v)
115  if (rec__(p, node_map, u, nei)) return true;
116 
117  for (const auto nei: children(v))
118  if (nei != u)
119  if (rec__(p, node_map, v, nei)) return true;
120 
121  for (const auto nei: parents(v))
122  if (nei != u)
123  if (rec__(p, node_map, v, nei)) return true;
124 
125  return false;
126  }
127 
130  NodeId u,
131  NodeId v) {
132  if (node_map.existsFirst(v)) {
133  if (node_map.second(u) < node_map.second(v)) {
134  // Invalid forward edge
135  return false;
136  } else if ((p.existsArc(node_map.second(u), node_map.second(v)))
138  // Duplicate arc !
139  return false;
140  }
141  } else {
143  }
144 
145  // Retrieving arc label data
146  LabelData* data = 0;
147 
148  try {
149  data = &(label(u, v));
150  } catch (NotFound&) { data = &(label(v, u)); }
151 
152  // Adding arc
153  try {
155  } catch (OperationNotAllowed&) {
156  // Invalid neighbor
157  if (node_map.second(u) < node_map.second(v)) {
160  }
161 
162  return false;
163  }
164 
165  // Check if this is minimal or if equal find another growth
166  size_t depth = p.code().codes.size() - 1;
167 
168  if (*(p.code().codes.back()) < *(code().codes[depth])) {
169  return true;
170  } else if (*(p.code().codes.back()) == *(code().codes[depth])) {
171  std::list< NodeId > r_path;
173 
174  for (const auto node: r_path) {
175  for (const auto nei: children(node_map.first(node)))
176  if (rec__(p, node_map, node_map.first(node), nei)) return true;
177 
178  for (const auto nei: parents(node_map.first(node)))
179  if (rec__(p, node_map, node_map.first(node), nei)) return true;
180  }
181  }
182 
183  if (p.code().codes.back()->isForward()) node_map.eraseFirst(v);
184 
185  p.pop_back();
186  return false;
187  }
188 
191  NodeId a_u,
192  NodeId a_v) {
193  std::vector< std::pair< NodeId, NodeId > > stack;
196  NodeId u = 0;
197  NodeId v = 0;
198 
199  while (!stack.empty()) {
200  bool go = true;
201  u = stack.back().first;
202  v = stack.back().second;
203  stack.pop_back();
204 
205  if ((u == 0) && (v == 0)) {
206  p.pop_back();
207  } else {
208  if (node_map.existsFirst(v)) {
209  if (node_map.second(u) < node_map.second(v)) {
210  // Invalid forward edge
211  go = false;
212  } else if ((p.existsArc(node_map.second(u), node_map.second(v)))
213  || (p.existsArc(node_map.second(v),
214  node_map.second(u)))) {
215  // Duplicate arc !
216  go = false;
217  }
218  } else {
220  }
221 
222  if (go) {
223  // Retrieving arc label data
224  LabelData* data = 0;
225 
226  try {
227  data = &(label(u, v));
228  } catch (NotFound&) { data = &(label(v, u)); }
229 
230  // Adding arc
231  try {
233  } catch (OperationNotAllowed&) {
234  // Invalid neighbor
235  if (node_map.second(u) < node_map.second(v)) {
238  }
239 
240  go = false;
241  }
242 
243  if (go) {
244  // Check if this is minimal or if equal find another growth
245  size_t depth = p.code().codes.size() - 1;
246 
247  if (*(p.code().codes.back()) < *(code().codes[depth])) {
248  return true;
249  } else if (*(p.code().codes.back()) == *(code().codes[depth])) {
250  std::list< NodeId > r_path;
253 
254  for (const auto node: r_path) {
255  for (const auto nei: children(node)) {
257  ++(rec_call.back());
258  }
259 
260  for (const auto nei: parents(node)) {
262  ++(rec_call.back());
263  }
264  }
265  }
266 
267  if (p.code().codes.back()->isForward()) node_map.eraseFirst(v);
268  }
269  }
270  }
271  }
272 
273  return false;
274  }
275 
276  } /* namespace gspan */
277  } /* namespace prm */
278 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
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.