aGrUM  0.14.2
pattern.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
28 
29 #ifdef GUM_NO_INLINE
31 #endif // GUM_NO_INLINE
32 
33 namespace gum {
34  namespace prm {
35  namespace gspan {
36 
37  Pattern::Pattern(const Pattern& source) : DiGraph(), __last(0) {
38  GUM_CONS_CPY(Pattern);
39  NodeProperty< NodeId > node_map;
40 
41  for (NodeId node = 1; node <= source.size(); ++node) {
42  node_map.insert(
43  node, addNodeWithLabel(const_cast< LabelData& >(source.label(node))));
44  }
45 
46  for (const auto edge : source.code().codes)
47  addArc(node_map[edge->i],
48  node_map[edge->j],
49  const_cast< LabelData& >(
50  source.label(node_map[edge->i], node_map[edge->j])));
51  }
52 
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 
83  std::string Pattern::toDot(size_t name) const {
84  std::stringstream sBuff;
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;
99  node_map.insert(u, p.addNodeWithLabel(label(u)));
100  node_map.insert(v, p.addNodeWithLabel(label(v)));
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  Bijection< NodeId, NodeId >& node_map,
127  NodeId u,
128  NodeId v) {
129  if (node_map.existsFirst(v)) {
130  if (node_map.second(u) < node_map.second(v)) {
131  // Invalid forward edge
132  return false;
133  } else if ((p.existsArc(node_map.second(u), node_map.second(v)))
134  || (p.existsArc(node_map.second(v), node_map.second(u)))) {
135  // Duplicate arc !
136  return false;
137  }
138  } else {
139  node_map.insert(v, p.addNodeWithLabel(label(v)));
140  }
141 
142  // Retrieving arc label data
143  LabelData* data = 0;
144 
145  try {
146  data = &(label(u, v));
147  } catch (NotFound&) { data = &(label(v, u)); }
148 
149  // Adding arc
150  try {
151  p.addArc(node_map.second(u), node_map.second(v), *data);
152  } catch (OperationNotAllowed&) {
153  // Invalid neighbor
154  if (node_map.second(u) < node_map.second(v)) {
155  p.remove(node_map.second(v));
156  node_map.eraseFirst(v);
157  }
158 
159  return false;
160  }
161 
162  // Check if this is minimal or if equal find another growth
163  size_t depth = p.code().codes.size() - 1;
164 
165  if (*(p.code().codes.back()) < *(code().codes[depth])) {
166  return true;
167  } else if (*(p.code().codes.back()) == *(code().codes[depth])) {
168  std::list< NodeId > r_path;
169  p.rightmostPath(r_path);
170 
171  for (const auto node : r_path) {
172  for (const auto nei : children(node_map.first(node)))
173  if (__rec(p, node_map, node_map.first(node), nei)) return true;
174 
175  for (const auto nei : parents(node_map.first(node)))
176  if (__rec(p, node_map, node_map.first(node), nei)) return true;
177  }
178  }
179 
180  if (p.code().codes.back()->isForward()) node_map.eraseFirst(v);
181 
182  p.pop_back();
183  return false;
184  }
185 
187  Bijection< NodeId, NodeId >& node_map,
188  NodeId a_u,
189  NodeId a_v) {
190  std::vector< std::pair< NodeId, NodeId > > stack;
191  std::vector< size_t > rec_call;
192  stack.push_back(std::make_pair(a_u, a_v));
193  NodeId u = 0;
194  NodeId v = 0;
195 
196  while (!stack.empty()) {
197  bool go = true;
198  u = stack.back().first;
199  v = stack.back().second;
200  stack.pop_back();
201 
202  if ((u == 0) && (v == 0)) {
203  p.pop_back();
204  } else {
205  if (node_map.existsFirst(v)) {
206  if (node_map.second(u) < node_map.second(v)) {
207  // Invalid forward edge
208  go = false;
209  } else if ((p.existsArc(node_map.second(u), node_map.second(v)))
210  || (p.existsArc(node_map.second(v),
211  node_map.second(u)))) {
212  // Duplicate arc !
213  go = false;
214  }
215  } else {
216  node_map.insert(v, p.addNodeWithLabel(label(v)));
217  }
218 
219  if (go) {
220  // Retrieving arc label data
221  LabelData* data = 0;
222 
223  try {
224  data = &(label(u, v));
225  } catch (NotFound&) { data = &(label(v, u)); }
226 
227  // Adding arc
228  try {
229  p.addArc(node_map.second(u), node_map.second(v), *data);
230  } catch (OperationNotAllowed&) {
231  // Invalid neighbor
232  if (node_map.second(u) < node_map.second(v)) {
233  p.remove(node_map.second(v));
234  node_map.eraseFirst(v);
235  }
236 
237  go = false;
238  }
239 
240  if (go) {
241  // Check if this is minimal or if equal find another growth
242  size_t depth = p.code().codes.size() - 1;
243 
244  if (*(p.code().codes.back()) < *(code().codes[depth])) {
245  return true;
246  } else if (*(p.code().codes.back()) == *(code().codes[depth])) {
247  std::list< NodeId > r_path;
248  p.rightmostPath(r_path);
249  stack.push_back(std::make_pair((NodeId)0, (NodeId)0));
250 
251  for (const auto node : r_path) {
252  for (const auto nei : children(node)) {
253  stack.push_back(std::make_pair(node_map.first(node), nei));
254  ++(rec_call.back());
255  }
256 
257  for (const auto nei : parents(node)) {
258  stack.push_back(std::make_pair(node_map.first(node), nei));
259  ++(rec_call.back());
260  }
261  }
262  }
263 
264  if (p.code().codes.back()->isForward()) node_map.eraseFirst(v);
265  }
266  }
267  }
268  }
269 
270  return false;
271  }
272 
273  } /* namespace gspan */
274  } /* namespace prm */
275 } /* namespace gum */
void insert(const T1 &first, const T2 &second)
Inserts a new association in the gum::Bijection.
const T2 & second(const T1 &first) const
Returns the second value of a pair given its first value.
const T1 & first(const T2 &second) const
Returns the first value of a pair given its second value.
Inner class to handle data about labels in this interface graph.
void eraseFirst(const T1 &first)
Erases an association containing the given first element.
Pattern()
Default constructor.
Definition: pattern_inl.h:32
DFSCode & code()
Returns the DFSCode of this Pattern.
Definition: pattern_inl.h:170
NodeId addNodeWithLabel(LabelData &l)
Insert a node with the given LabelData.
Definition: pattern_inl.h:38
bool __expandCodeIsMinimal(NodeId u, NodeId v)
Returns true if the expand code by adding and edge betwenne u and v is minimal with respect to __code...
Definition: pattern.cpp:96
bool isMinimal()
Returns the DFSCode of this Pattern.
Definition: pattern.cpp:53
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
std::vector< EdgeCode *> codes
The vector containing the EdgeCode composing this DFSCode.
Definition: DFSCode.h:87
The class for generic Hash Tables.
Definition: hashTable.h:676
LabelData & label(NodeId node)
Returns the LabelData assigned to node.
Definition: pattern_inl.h:47
represent a DFS code used by gspan.
Definition: edgeCode.h:49
bool existsFirst(const T1 &first) const
Returns true if first is the first element in a pair in the gum::Bijection.
Size size() const
Returns the number of nodes in this Pattern.
Definition: pattern_inl.h:144
const NodeSet & parents(const NodeId id) const
returns the set of nodes with arc ingoing to a given node
Base class for all oriented graphs.
Definition: diGraph.h:108
virtual const std::string toDot() const
to friendly display the content of the graph in the DOT syntax
Definition: diGraph.cpp:65
Set of pairs of elements with fast search for both elements.
Definition: bijection.h:1803
bool __not_rec(Pattern &p, Bijection< NodeId, NodeId > &node_map, NodeId u, NodeId v)
A non recursive bugged version of __rec.
Definition: pattern.cpp:186
const NodeGraphPart & nodes() const
Definition: pattern_inl.h:163
void rightmostPath(std::list< NodeId > &r_path) const
Fill r_path with the rightmost path of this Pattern. The list is supposed empty.
Definition: pattern_inl.h:150
const ArcSet & arcs() const
Definition: pattern_inl.h:167
Idx id
An unique identifier for this label.
bool __rec(Pattern &p, Bijection< NodeId, NodeId > &node_map, NodeId u, NodeId v)
Recurisve method used by __expandCodeIsMinimal.
Definition: pattern.cpp:125
void pop_back()
Remove the last EdgeCode of this pattern.
Definition: pattern_inl.h:204
Inline implementation of the Pattern class.
const NodeSet & children(const NodeId id) const
returns the set of nodes with arc outgoing from a given node
void addArc(NodeId i, NodeId j, LabelData &l)
Add an arc to this Pattern.
Definition: pattern_inl.h:115
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:45
void remove(NodeId node)
Remove a node if it has no neighbors, raise an OperationNotAllowed otherwise.
Definition: pattern_inl.h:222
Headers of the Pattern class.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
This contains all the information we want for a node in a DFSTree.
Definition: pattern.h:70
bool existsArc(const Arc &arc) const
indicates whether a given arc exists
Size NodeId
Type for node ids.
Definition: graphElements.h:97