aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
pattern.cpp
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 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  }
46 
47  for (const auto& edge: source.code().codes)
49  node_map[edge->j],
50  const_cast< LabelData& >(source.label(node_map[edge->i], node_map[edge->j])));
51  }
52 
53  bool Pattern::isMinimal() {
54  for (const auto node: nodes()) {
55  for (const auto next: parents(node)) {
56  Size u = label(node).id;
57  Size v = label(next).id;
58  EdgeCode edge_code(1, 2, u, label(next, node).id, v);
59 
60  if (edge_code < *(code().codes.front())) {
61  return false;
62  } else if (edge_code == (*code().codes.front())) {
63  if (_expandCodeIsMinimal_(node, next)) { return false; }
64  }
65  }
66 
67  for (const auto next: children(node)) {
68  Size u = label(node).id;
69  Size v = label(next).id;
70  EdgeCode edge_code(1, 2, u, label(node, next).id, v);
71 
72  if (edge_code < *(code().codes.front())) {
73  return false;
74  } else if (edge_code == (*code().codes.front())) {
75  if (_expandCodeIsMinimal_(node, next)) { return false; }
76  }
77  }
78  }
79 
80  return true;
81  }
82 
85  sBuff << "digraph " << name << " {\n";
86 
87  for (const auto& arc: arcs()) {
88  sBuff << label(arc.tail()).id << " -> ";
89  sBuff << label(arc.head()).id << ";\n";
90  }
91 
92  sBuff << "}\n";
93  return sBuff.str();
94  }
95 
98  Pattern p;
101 
102  try {
103  p.addArc(1, 2, label(u, v));
104  } catch (NotFound&) { p.addArc(1, 2, label(v, u)); }
105 
106  for (const auto nei: children(u))
107  if (nei != v)
108  if (_rec_(p, node_map, u, nei)) return true;
109 
110  for (const auto nei: parents(u))
111  if (nei != v)
112  if (_rec_(p, node_map, u, nei)) return true;
113 
114  for (const auto nei: children(v))
115  if (nei != u)
116  if (_rec_(p, node_map, v, nei)) return true;
117 
118  for (const auto nei: parents(v))
119  if (nei != u)
120  if (_rec_(p, node_map, v, nei)) return true;
121 
122  return false;
123  }
124 
126  if (node_map.existsFirst(v)) {
127  if (node_map.second(u) < node_map.second(v)) {
128  // Invalid forward edge
129  return false;
130  } else if ((p.existsArc(node_map.second(u), node_map.second(v)))
132  // Duplicate arc !
133  return false;
134  }
135  } else {
137  }
138 
139  // Retrieving arc label data
140  LabelData* data = 0;
141 
142  try {
143  data = &(label(u, v));
144  } catch (NotFound&) { data = &(label(v, u)); }
145 
146  // Adding arc
147  try {
149  } catch (OperationNotAllowed&) {
150  // Invalid neighbor
151  if (node_map.second(u) < node_map.second(v)) {
154  }
155 
156  return false;
157  }
158 
159  // Check if this is minimal or if equal find another growth
160  size_t depth = p.code().codes.size() - 1;
161 
162  if (*(p.code().codes.back()) < *(code().codes[depth])) {
163  return true;
164  } else if (*(p.code().codes.back()) == *(code().codes[depth])) {
165  std::list< NodeId > r_path;
167 
168  for (const auto node: r_path) {
169  for (const auto nei: children(node_map.first(node)))
170  if (_rec_(p, node_map, node_map.first(node), nei)) return true;
171 
172  for (const auto nei: parents(node_map.first(node)))
173  if (_rec_(p, node_map, node_map.first(node), nei)) return true;
174  }
175  }
176 
177  if (p.code().codes.back()->isForward()) node_map.eraseFirst(v);
178 
179  p.pop_back();
180  return false;
181  }
182 
185  NodeId a_u,
186  NodeId a_v) {
187  std::vector< std::pair< NodeId, NodeId > > stack;
190  NodeId u = 0;
191  NodeId v = 0;
192 
193  while (!stack.empty()) {
194  bool go = true;
195  u = stack.back().first;
196  v = stack.back().second;
197  stack.pop_back();
198 
199  if ((u == 0) && (v == 0)) {
200  p.pop_back();
201  } else {
202  if (node_map.existsFirst(v)) {
203  if (node_map.second(u) < node_map.second(v)) {
204  // Invalid forward edge
205  go = false;
206  } else if ((p.existsArc(node_map.second(u), node_map.second(v)))
208  // Duplicate arc !
209  go = false;
210  }
211  } else {
213  }
214 
215  if (go) {
216  // Retrieving arc label data
217  LabelData* data = 0;
218 
219  try {
220  data = &(label(u, v));
221  } catch (NotFound&) { data = &(label(v, u)); }
222 
223  // Adding arc
224  try {
226  } catch (OperationNotAllowed&) {
227  // Invalid neighbor
228  if (node_map.second(u) < node_map.second(v)) {
231  }
232 
233  go = false;
234  }
235 
236  if (go) {
237  // Check if this is minimal or if equal find another growth
238  size_t depth = p.code().codes.size() - 1;
239 
240  if (*(p.code().codes.back()) < *(code().codes[depth])) {
241  return true;
242  } else if (*(p.code().codes.back()) == *(code().codes[depth])) {
243  std::list< NodeId > r_path;
246 
247  for (const auto node: r_path) {
248  for (const auto nei: children(node)) {
250  ++(rec_call.back());
251  }
252 
253  for (const auto nei: parents(node)) {
255  ++(rec_call.back());
256  }
257  }
258  }
259 
260  if (p.code().codes.back()->isForward()) node_map.eraseFirst(v);
261  }
262  }
263  }
264  }
265 
266  return false;
267  }
268 
269  } /* namespace gspan */
270  } /* namespace prm */
271 } /* 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.