Generated on Wed Apr 29 2015 11:51:40 for GGL-4.1.2 by doxygen 1.8.3.1
MC_Edge.hh
Go to the documentation of this file.
1 #ifndef SGM_MC_EDGE_HH_
2 #define SGM_MC_EDGE_HH_
3 
4 #include <string>
5 #include <set>
6 #include <climits>
7 #include <cassert>
8 
9 #include <sgm/Pattern.hh>
10 #include <sgm/Graph_Interface.hh>
11 #include <sgm/Match_Reporter.hh>
12 
13 
14 namespace sgm {
15 
16 
17 //=========================================================================
18 
19 
20  /*! @brief Interface edge match constraint
21  *
22  * A match node constraint describes additional properties that have to be
23  * fulfilled by a given matched edge on a given target.
24  *
25  * @author Martin Mann - 2010 - http://www.bioinf.uni-freiburg.de/~mmann/
26  *
27  */
29 
30  public:
31 
32  //! the source ID of the edge to be constrained
34 
35  //! the target ID of the edge to be constrained
37 
38  //! construction
39  //! @param constrainedFromID source ID of the edge to be constrained
40  //! @param constrainedToID target ID of the edge to be constrained
41  MC_Edge( const size_t constrainedFromID
42  , const size_t constrainedToID )
43  : constrainedFromID(constrainedFromID)
44  , constrainedToID(constrainedToID)
45  {}
46 
47  //! copy construction
48  //! @param toCopy the MC_Edge object to copy
49  MC_Edge( const MC_Edge& toCopy )
52  {}
53 
54  //! destruction
55  virtual
57  {}
58 
59  /*!
60  * Checks whether or not this constraint covers the node with the
61  * given ID.
62  *
63  * @param nodeID the ID of the node of interest
64  * @return true if the node is covered by the constraint; false
65  * otherwise
66  */
67  virtual
68  bool
69  isConstraining( const size_t nodeID ) const
70  {
71  // check if this ID is constrained
72  return nodeID == constrainedFromID || nodeID == constrainedToID;
73  }
74 
75  /*!
76  * Creates a new MC_Edge heap object that equals the current
77  * object.
78  * NOTE: YOU have to delete it later on! There is no garbage
79  * collection!
80  * @return a new allocated MC_Edge object that equals this
81  */
82  virtual
83  MC_Edge*
84  clone( void ) const = 0;
85 
86 
87  /*!
88  * Creates a new MC_Edge heap object that equals the current
89  * object but uses the new indices given by old2newIndexMapping.
90  * NOTE: YOU have to delete it later on! There is no garbage
91  * collection!
92  * @param old2newIndexMapping the index mapping to be used for the
93  * remapping
94  * @param unmatchedIndex an optional specific index that marks
95  * unmatched nodes within old2newIndexMapping. if this
96  * constrains one of these nodes, no remapping is done and
97  * NULL is returned
98  * @return a new allocated MC_Edge object
99  */
100  virtual
101  MC_Edge*
102  remap( const Match & old2newIndexMapping, const size_t unmatchedIndex = UINT_MAX ) = 0;
103 
104 
105  /*!
106  * Equality comparison to another match constraint.
107  * @param toCompare the constraint to compare to
108  * @return true if the constraints are equal; false otherwise
109  */
110  virtual
111  bool
112  operator==( const Match_Constraint & toCompare ) const {
113  const MC_Edge* pc = dynamic_cast< const MC_Edge* >(&toCompare);
114  if (pc != NULL) {
115  return this->constrainedFromID == pc->constrainedFromID
116  && this->constrainedToID == pc->constrainedToID;
117  } else {
118  return false;
119  }
120  }
121 
122  };
123 
124 //=========================================================================
125 
126  /*! @brief Forbids an edge within a match
127  *
128  * This match constraint defines a given edge is NOT PRESENT within the
129  * target graph.
130  *
131  * Current idea of GML encoding:
132  *
133  * \verbatim
134 *****************************************************
135  constrainNoEdge [
136  source ::= INTEGER
137  target ::= INTEGER
138  ]
139 *****************************************************
140  \endverbatim
141  *
142  * @author Martin Mann - 2010 - http://www.bioinf.uni-freiburg.de/~mmann/
143  *
144  */
145  class MC_NoEdge : public MC_Edge {
146 
147  public:
148 
149  //! the index of the source node this constraint is for
151  //! the index of the target node this constraint is for
153 
154  /*!
155  * Default construction of the match constraint : undefined values are
156  * initialized with INT_MAX
157  */
159  : MC_Edge((size_t)INT_MAX,(size_t)INT_MAX)
160  {}
161 
162  /*!
163  * Copy construction of the match constraint
164  */
165  MC_NoEdge( const MC_NoEdge& toCopy )
166  : MC_Edge( toCopy )
167  {}
168 
169  /*!
170  * Construction of the match constraint
171  *
172  * @param constrainedFromID the index of the source node
173  * @param constrainedToID the index of the target node
174  */
176  , const size_t constrainedToID )
177  : MC_Edge(constrainedFromID,constrainedToID)
178  {}
179 
180 
181  //! destruction
182  virtual
184  {}
185 
186  /*!
187  * Checks whether or not a match on a given target fullfills the
188  * additional NO-EDGE constraint for the pattern matching.
189  *
190  * @param pattern the pattern graph that was matched
191  * @param target the target graph the pattern was matched on
192  * @param match the match information for the left side pattern of the
193  * pattern on the target graph
194  * @return true if the match is valid; false if the constraint is
195  * violated
196  */
197  virtual
198  bool
199  isValidMatch( const Pattern_Interface & pattern,
200  const Graph_Interface & target,
201  const Match & match ) const
202  {
203  // check if no edges existent
204  return target.getEdgesBegin(
205  match.at(constrainedFromID)
206  , match.at(constrainedToID) )
207  == target.getEdgesEnd(
208  match.at(constrainedFromID)
209  , match.at(constrainedToID)
210  );
211  }
212 
213  virtual
214  bool
215  isConstrainedLabel( const std::string & label ) const
216  {
217  // not label information used
218  return false;
219  }
220 
221  /*!
222  * Creates a new MC_NoEdge heap object that equals the current
223  * object.
224  * NOTE: YOU have to delete it later on! There is no garbage
225  * collection!
226  * @return a new allocated MC_NoEdge object that equals *this
227  */
228  virtual
229  MC_NoEdge*
230  clone( void ) const
231  {
232  return new MC_NoEdge(*this);
233  }
234 
235 
236  /*!
237  * Creates a new MC_NoEdge heap object that equals the current
238  * object but uses the new indices given by old2newIndexMapping.
239  * NOTE: YOU have to delete it later on! There is no garbage
240  * collection!
241  * @param old2newIndexMapping the index mapping to be used for the
242  * remapping
243  * @param unmatchedIndex an optional specific index that marks
244  * unmatched nodes within old2newIndexMapping. if this
245  * constrains one of these nodes, no remapping is done and
246  * NULL is returned
247  * @return a new allocated MC_NoEdge object
248  */
249  virtual
250  MC_NoEdge*
251  remap( const Match & old2newIndexMapping, const size_t unmatchedIndex = UINT_MAX )
252  {
253  assert(this->constrainedFromID < old2newIndexMapping.size());
254  assert(this->constrainedToID < old2newIndexMapping.size());
255 
256  // check if this edge constrains an unmatched node
257  if (old2newIndexMapping.at(this->constrainedFromID) == unmatchedIndex
258  || old2newIndexMapping.at(this->constrainedToID) == unmatchedIndex)
259  {
260  return NULL;
261  }
262 
263  // create copy
264  MC_NoEdge* copy = new MC_NoEdge(*this);
265  // do remapping
266  copy->constrainedFromID = old2newIndexMapping.at(copy->constrainedFromID);
267  copy->constrainedToID = old2newIndexMapping.at(copy->constrainedToID);
268  // return remapped copy
269  return copy;
270  }
271 
272 
273  /*!
274  * Equality comparison to another match constraint.
275  * @param toCompare the constraint to compare to
276  * @return true if the constraints are equal; false otherwise
277  */
278  virtual
279  bool
280  operator==( const Match_Constraint& toCompare ) const
281  {
282  const MC_NoEdge* pc = dynamic_cast< const MC_NoEdge* >(&toCompare);
283  if (pc != NULL) {
284  bool isEqual = MC_Edge::operator==( toCompare );
285  // return final comparison result
286  return isEqual;
287  } else {
288  return false;
289  }
290  }
291 
292 
293 
294  };
295 
296 //=========================================================================
297 
298 
299  /*! @brief Constrains edge labels within a match
300  *
301  * A match constraint that restricts the allowed matched labels for a given
302  * matched edge to a set of maintained labels.
303  *
304  * Via the operator it is defined whether the given set of edge labels is
305  * the allowed (op =) or forbidden (op !) set of labels for the edge. It
306  * defaults to allowed (op =).
307  *
308  * NOTE: This constraint is only useful if the according pattern edge shows
309  * a wildcard label such that it can be matched on any target edge.
310  *
311  * NOTE: if there is NO EDGE between the nodes, the constraint fails!
312  *
313  * Current idea of GML encoding:
314  *
315  * \verbatim
316 *****************************************************
317  constrainEdge [
318  source ::= INTEGER
319  target ::= INTEGER
320  op ::= OPERATOR { = | ! }
321  edgeLabels [
322  label ::= STRING
323  ]
324  ]
325 *****************************************************
326  \endverbatim
327  * @author Martin Mann - http://www.bioinf.uni-freiburg.de/~mmann/
328  *
329  */
330  class MC_EdgeLabel : public MC_Edge {
331 
332  public:
333 
334  //! the type that defines a set of labels
335  typedef std::set< std::string > LabelSet;
336 
338 
339 
340  public:
341 
342  //! the node ID to be constrained
344 
345  //! the node ID to be constrained
347 
348  //! the set of labels this node can be mapped on
349  //! NOTE: if empty, no matching will be allowed !!!
351 
352  //! the type of comparison to be applied, i.e. if to ensure that the
353  //! edge label is among the edgeLabels (ALLOWED) or that it is not
354  //! present (FORBIDDEN)
356 
357  /*!
358  * Default construction of the match constraint : undefined values are
359  * initialized with INT_MAX or empty sets
360  */
362  : MC_Edge((size_t)INT_MAX,(size_t)INT_MAX)
363  , edgeLabels()
365  {}
366 
367  //! construction where the allowed node labels are empty
368  //! @param constrainedFromID the source node ID to be constrained
369  //! @param constrainedToID the target node ID to be constrained
371  , const size_t constrainedToID )
372  : MC_Edge(constrainedFromID, constrainedToID)
373  , edgeLabels()
375  {}
376 
377  //! construction where the allowed node labels are empty
378  //! @param constrainedFromID the source node ID to be constrained
379  //! @param constrainedToID the target node ID to be constrained
380  //! @param edgeLabels the allowed node labels to be matched on
382  , const size_t constrainedToID
383  , const LabelSet& edgeLabels)
384  : MC_Edge( constrainedFromID, constrainedToID )
385  , edgeLabels( edgeLabels )
387  {}
388 
389  //! construction where the allowed node labels are empty
390  //! @param constrainedFromID the source node ID to be constrained
391  //! @param constrainedToID the target node ID to be constrained
392  //! @param edgeLabels the allowed node labels to be matched on
393  //! @param compareType the type of comparison to be applied
395  , const size_t constrainedToID
396  , const LabelSet& edgeLabels
397  , const CompareType& compareType )
398  : MC_Edge( constrainedFromID, constrainedToID )
399  , edgeLabels( edgeLabels )
400  , compareType( compareType )
401  {}
402 
403  //! copy construction
404  //! @param toCopy the MC_EdgeLabel object to copy
405  MC_EdgeLabel( const MC_EdgeLabel& toCopy )
406  : MC_Edge(toCopy)
407  , edgeLabels( toCopy.edgeLabels )
408  , compareType( toCopy.compareType )
409  {}
410 
411  //! destruction
412  virtual
414  {}
415 
416  /*!
417  * Checks whether or not the matched edges between two nodes show
418  * one of the allowed labels or are not showing any of the forbidden
419  * labels.
420  *
421  * NOTE: if there is NO EDGE between the node, the constraint fails!
422  *
423  * @param pattern the pattern graph that was matched
424  * @param target the target graph the pattern was matched on
425  * @param match the match information for the left side pattern of the
426  * pattern on the target graph
427  * @return true if the match is valid; false if the constraint is
428  * violated
429  */
430  virtual
431  bool
432  isValidMatch( const Pattern_Interface & pattern,
433  const Graph_Interface & target,
434  const Match & match ) const
435  {
436  // get edge iterator for the edges between source and target
438  match.at(this->constrainedFromID)
439  , match.at(this->constrainedToID) );
441  match.at(this->constrainedFromID)
442  , match.at(this->constrainedToID) );
443 
444  // ensure that there is an edge to constrain ...
445  if (curEdge == edgeEnd) {
446  return false;
447  }
448 
449  // handle comparison according to given comparison type
450  switch (compareType) {
451 
452  case ALLOWED : { // check if all edge labels are found
453  // empty set of allowed labels -> no label allowed
454  if (edgeLabels.empty()) {
455  return false;
456  }
457  // if wildcard is among the allowed labels -> return true
458  if (pattern.getUsedWildcard() != NULL
459  && edgeLabels.find(*(pattern.getUsedWildcard())) != edgeLabels.end() )
460  {
461  return true;
462  }
463  // check if all mapped edges shows an allowed label
464  bool allFound = true;
465  for( ; allFound && curEdge != edgeEnd; ++curEdge ) {
466  allFound = edgeLabels.find( curEdge->getEdgeLabel() )
467  != edgeLabels.end();
468  }
469  return allFound;
470  }
471  case FORBIDDEN : { // check that all edge labels are NOT found
472  // empty set of forbidden labels -> all label allowed
473  if (edgeLabels.empty()) {
474  return true;
475  }
476  // if wildcard is among the forbidden pattern -> return false
477  if (pattern.getUsedWildcard() != NULL
478  && edgeLabels.find(*(pattern.getUsedWildcard())) != edgeLabels.end() )
479  {
480  return false;
481  }
482  // check if all mapped edges shows no forbidden label
483  bool allNotFound = true;
484  for( ; allNotFound && curEdge != edgeEnd; ++curEdge ) {
485  allNotFound = edgeLabels.find( curEdge->getEdgeLabel() )
486  == edgeLabels.end();
487  }
488  return allNotFound;
489  }
490  default :
491  assert(false); /*should never happen*/
492  }
493 
494  // if not satisfied so far, wont be satisfied anymore.. ;)
495  return false;
496  }
497 
498 
499  virtual
500  bool
501  isConstrainedLabel( const std::string & label ) const
502  {
503  // check if among the edge labels
504  for (LabelSet::const_iterator l=edgeLabels.begin(); l!=edgeLabels.end(); ++l)
505  if (l->compare(label)==0)
506  return true;
507  // not found
508  return false;
509  }
510 
511  /*!
512  * Creates a new MC_EdgeLabel heap object that equals the current
513  * object.
514  * NOTE: YOU have to delete it later on! There is no garbage
515  * collection!
516  * @return a new allocated MC_EdgeLabel object that equals *this
517  */
518  virtual
519  MC_EdgeLabel*
520  clone( void ) const
521  {
522  return new MC_EdgeLabel(*this);
523  }
524 
525 
526  /*!
527  * Creates a new MC_EdgeLabel heap object that equals the current
528  * object but uses the new indices given by old2newIndexMapping.
529  * NOTE: YOU have to delete it later on! There is no garbage
530  * collection!
531  * @param old2newIndexMapping the index mapping to be used for the
532  * remapping
533  * @param unmatchedIndex an optional specific index that marks
534  * unmatched nodes within old2newIndexMapping. if this
535  * constrains one of these nodes, no remapping is done and
536  * NULL is returned
537  * @return a new allocated MC_EdgeLabel object
538  */
539  virtual
540  MC_EdgeLabel*
541  remap( const Match & old2newIndexMapping, const size_t unmatchedIndex = UINT_MAX )
542  {
543  assert(this->constrainedFromID < old2newIndexMapping.size());
544  assert(this->constrainedToID < old2newIndexMapping.size());
545 
546  // check if this edge constrains an unmatched node
547  if (old2newIndexMapping.at(this->constrainedFromID) == unmatchedIndex
548  || old2newIndexMapping.at(this->constrainedToID) == unmatchedIndex)
549  {
550  return NULL;
551  }
552 
553  // create copy
554  MC_EdgeLabel* copy = new MC_EdgeLabel(*this);
555  // do remapping
556  copy->constrainedFromID = old2newIndexMapping.at(copy->constrainedFromID);
557  copy->constrainedToID = old2newIndexMapping.at(copy->constrainedToID);
558  // return remapped copy
559  return copy;
560  }
561 
562 
563  /*!
564  * Equality comparison to another match constraint.
565  * @param toCompare the constraint to compare to
566  * @return true if the constraints are equal; false otherwise
567  */
568  virtual
569  bool
570  operator==( const Match_Constraint& toCompare ) const
571  {
572  const MC_EdgeLabel* pc = dynamic_cast< const MC_EdgeLabel* >(&toCompare);
573  if (pc != NULL) {
574  bool isEqual =
575  MC_Edge::operator==( toCompare )
576  && this->edgeLabels.size() == pc->edgeLabels.size()
577  && this->compareType == pc->compareType
578  ;
579  // check if all edge labels present
580  for (LabelSet::const_iterator l=this->edgeLabels.begin();
581  isEqual && l!=this->edgeLabels.end(); ++l)
582  {
583  isEqual = pc->edgeLabels.find(*l)!=pc->edgeLabels.end();
584  }
585  // return final comparison result
586  return isEqual;
587  } else {
588  return false;
589  }
590  }
591 
592 
593  };
594 
595 //=========================================================================
596 
597 } // namespace sgm
598 
599 
600 #endif /* SGM_MC_EDGE_HH_ */
601