Scaffolding  0.1
This program can assemble genome scaffolds using the pairing information in paired-end reads.
permissive_matching.hpp
Go to the documentation of this file.
1 
2 
11 #ifndef PERMISSIVE_MATCHING_HPP
12 #define PERMISSIVE_MATCHING_HPP
13 
14 #include <boost/unordered_map.hpp>
15 
16 #include "utils/utils.hpp"
17 
18 #define ARRAY_LENGTH MAX_TW
19 
20 namespace scaffold{
21 
22  class PermissiveMatching;
23  typedef PermissiveMatching BytePermutation;
24 
26  private:
27  byte* matched;
28  public:
29 
30  // ======== Constructors & Destructor ================
32 
35  PermissiveMatching(const unordered_map<byte, byte>* edges = NULL): matched(new byte[ARRAY_LENGTH])
36  {
37  if(edges){
38  for(byte i = 0; i < ARRAY_LENGTH; ++i){
39  const auto edge_iter = edges->find(i);
40  if(edge_iter != edges->end()){
41  const byte edge_target = edge_iter->second;
42  matched[i] = edge_target;
43  assert((edge_target > i) || (matched[edge_target] == i));
44  } else matched[i] = i;
45  }// for
46  } else for(byte i = 0; i < ARRAY_LENGTH; ++i) matched[i] = i;
47  }// constructor
48 
50  PermissiveMatching(const PermissiveMatching& P): matched(new byte[ARRAY_LENGTH])
51  {
52  memcpy(matched, P.matched, ARRAY_LENGTH);
53  }
54 
57  {
58  delete[] matched;
59  }// destructor
60 
61 
62  // =========== methods ==================
63 
65  operator size_t() const
66  {
67  size_t result = 0;
68  for(byte i = 0; i < ARRAY_LENGTH; ++i)
69  result = boost::hash_combine(result, matched[i]);
70  return result;
71  }// function
72 
73 
75  const byte& operator[](const byte i) const
76  {
77  return matched[i];
78  }
79 
81  byte& operator[](const byte i)
82  {
83  return matched[i];
84  }
85 
87  bool introduce_edge(const byte u, const byte v)
88  {
89  assert(u < ARRAY_LENGTH);
90  assert(v < ARRAY_LENGTH);
91 
92  if((matched[u] != u) || (matched[v] != v)) return false;
93  matched[u] = v;
94  matched[v] = u;
95  }
96 
98  bool is_identity() const
99  {
100  for(byte i = 0; i < ARRAY_LENGTH; ++i)
101  if(matched[i] != i) return false;
102  return true;
103  }
104 
106 
111  void permute(const BytePermutation& perm)
112  {
113  byte* old_matched = matched;
114  DEBUG5(std::cout << "permuting "<<*this<<" with permutation "<<perm<<std::endl);
115  matched = new byte[ARRAY_LENGTH];
116  for(byte i = 0; i < ARRAY_LENGTH; ++i) matched[i] = i;
117  for(byte i = 0; i < ARRAY_LENGTH; ++i)
118  matched[perm[i]] = perm[old_matched[i]];
119  delete[] old_matched;
120  DEBUG5(std::cout<<"-->"<<*this<<std::endl);
121  }
122 
124 
127  PathsAndCycles merge_with(const PermissiveMatching& P, const std::bitset<ARRAY_LENGTH>& deg1_in_both)
128  {
129  PathsAndCycles result;
130  byte* old_matched = matched;
131  matched = new byte[ARRAY_LENGTH];
132 
133  for(byte u = 0; u < ARRAY_LENGTH; ++u){
134  byte v = u;
135  byte w = u;
136 
137  if(P[u] != u){
138  // propagate v
139  do{
140  v = P[v];
141  v = old_matched[v];
142  } while((v != u) && (v != P[v]) && (v != old_matched[v]));
143  if(u == v){
144  // if we arrived at u again, we walked in a cirlce, so register the circle
145  if(u > v) result.c++;
146  matched[u] = u;
147  continue;
148  }
149  }
150  if(old_matched[u] != u){
151  // propagate w
152  do{
153  w = old_matched[w];
154  w = P[w];
155  } while((w != old_matched[w]) && (w != P[w]));
156  // note that we cannot have arrived at u since otherwise we'd have 'continue'ed earlier
157  }
158  // note that, at this point, we have exactly one of P & old_matched assigning v to itself, and the same for w
159  if(P[u] == u){
160  if(old_matched[u] == u){
161  if(deg1_in_both[u]) result.p++;
162  matched[u] = u;
163  } else {
164  // we have a u-w path in the merge
165  if(deg1_in_both[u]){
166  // since P[u] == u we have a u-w path with a dangling path at u
167  matched[u] = u;
168  // if we also have a dangling path at w, then increase the number of paths
169  if(deg1_in_both[w] && (u > w)) result.p++;
170  } else {
171  if(deg1_in_both[w]){
172  matched[u] = u;
173  } else {
174  matched[u] = w;
175  }
176  }// if
177  }// if
178  } else {
179  // P[u] != u, so we have a v-u path
180  if(old_matched[u] == u){
181  if(deg1_in_both[u]){
182  // since old_matched[u] == u, we have a v-u path with a dangling path at u
183  matched[u] = u;
184  // if v also has a dangling path, increase the number of paths
185  if(deg1_in_both[v] && (u > v)) result.p++;
186  } else {
187  // we have a v-u path in the merge, but v could have a dangling path
188  if(deg1_in_both[v]){
189  matched[u] = u;
190  } else {
191  matched[u] = v;
192  }
193  }
194  } else {
195  // P[u] != u and old_matched[u] != u, implying deg1_in_both[u]
196  // so u is an inner vertex on some v-w path
197  matched[u] = u;
198  }// if
199  }// if
200  }// for
201  delete[] old_matched;
202 
203  return result;
204  }
205 
206  friend std::ostream& operator<<(std::ostream& os, const PermissiveMatching& P)
207  {
208  os << "(";
209  for(byte i = 0; i < ARRAY_LENGTH; ++i) os << (unsigned)P.matched[i] << " ";
210  return os << ")";
211  }
212 
213  };
214 
215 
216 
217  size_t hash_value(const PermissiveMatching& P)
218  {
219  return (size_t)P;
220  }
221 };
222 
223 
224 #endif
225 
bool is_identity() const
return whether everyone matches to itself
Definition: permissive_matching.hpp:98
PermissiveMatching(const PermissiveMatching &P)
copy constructor
Definition: permissive_matching.hpp:50
PathsAndCycles merge_with(const PermissiveMatching &P, const std::bitset< ARRAY_LENGTH > &deg1_in_both)
TODO: move this out of the permissive matching class as it's unique to the DP code & this should be a...
Definition: permissive_matching.hpp:127
Definition: read_adj_list.hpp:22
size_t hash_value(const boost::unordered_set< T > &S)
a hash computation for an unordered set, XORing its members
Definition: utils.hpp:178
~PermissiveMatching()
destructor
Definition: permissive_matching.hpp:56
bool introduce_edge(const byte u, const byte v)
introduce an edge uv, unless uv is already present OR the insertion would violate the matching constr...
Definition: permissive_matching.hpp:87
byte & operator[](const byte i)
access to the array
Definition: permissive_matching.hpp:81
const byte & operator[](const byte i) const
access to the array
Definition: permissive_matching.hpp:75
PermissiveMatching(const unordered_map< byte, byte > *edges=NULL)
construct from an unordered_map
Definition: permissive_matching.hpp:35
Definition: permissive_matching.hpp:25
void permute(const BytePermutation &perm)
rename the indices according to the given BytePermutation
Definition: permissive_matching.hpp:111
Definition: graph_typedefs.hpp:26