All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CMergeBookKeeper.cxx
Go to the documentation of this file.
1 #include <iostream>
2 
5 
6 #include "TString.h" // Form()
7 
8 namespace cmtool {
9 
10  CMergeBookKeeper::CMergeBookKeeper(unsigned short nclusters)
11  {
12  Reset(nclusters);
13  }
14 
15  void CMergeBookKeeper::Reset(unsigned short nclusters)
16  {
17  _prohibit_merge.clear();
18  _prohibit_merge.reserve(nclusters);
19  std::vector<unsigned short>::clear();
20  std::vector<unsigned short>::reserve(nclusters);
21 
22  for(size_t i=0; i<nclusters; ++i) {
23  this->push_back(i);
24  _prohibit_merge.push_back(std::vector<bool>(nclusters-i,false));
25  }
26  _out_cluster_count = nclusters;
27 
28  }
29 
30  void CMergeBookKeeper::ProhibitMerge(unsigned short index1, unsigned short index2)
31  {
32  if(index1 == index2)
33 
34  throw CMTException(Form("<<%s>> Two input clusters identical (%d)",__FUNCTION__,index1));
35 
36 
37  if( index1 >= this->size() || index2 >= this->size() )
38 
39  throw CMTException(Form("Input cluster index (%d and/or %d) out of range",index1,index2));
40 
41  auto out_index1 = this->at(index1);
42  auto out_index2 = this->at(index2);
43 
44  if(out_index1 == out_index2)
45  throw CMTException(Form("Cluster %d and %d already merged!",index1,index2));
46 
47  if(out_index2 < out_index1) std::swap(out_index1,out_index2);
48 
49  _prohibit_merge.at(out_index1).at(out_index2-out_index1) = true;
50 
51  }
52 
53  bool CMergeBookKeeper::MergeAllowed(unsigned short index1,
54  unsigned short index2)
55  {
56 
57  if(index1 == index2)
58 
59  throw CMTException(Form("<<%s>> Two input clusters identical (%d)",__FUNCTION__,index1));
60 
61 
62  if( index1 >= this->size() || index2 >= this->size() )
63 
64  throw CMTException(Form("Input cluster index (%d and/or %d) out of range",index1,index2));
65 
66  auto out_index1 = this->at(index1);
67  auto out_index2 = this->at(index2);
68 
69  if(out_index1 == out_index2) return true;
70 
71  if(out_index2 < out_index1) std::swap(out_index1,out_index2);
72 
73  return !(_prohibit_merge.at(out_index1).at(out_index2-out_index1));
74 
75  }
76 
77  void CMergeBookKeeper::Merge(unsigned short index1, unsigned short index2)
78  {
79 
80  if(index1 == index2)
81 
82  throw CMTException(Form("<<%s>> Two input clusters identical (%d)",__FUNCTION__,index1));
83 
84 
85  if( index1 >= this->size() || index2 >= this->size() )
86 
87  throw CMTException(Form("Input cluster index (%d and/or %d) out of range",index1,index2));
88 
89  auto out_index1 = this->at(index1);
90  auto out_index2 = this->at(index2);
91 
92  if(out_index1 == out_index2) return;
93 
94  if(out_index2 < out_index1) std::swap(out_index1,out_index2);
95 
96  if(_prohibit_merge.at(out_index1).at(out_index2-out_index1))
97 
98  throw CMTException(Form("Clusters (%d,%d) correspond to output (%d,%d) which is prohibited to merge",
99  index1,index2,
100  out_index1,out_index2));
101 
102  //
103  // Merge cluster indexes
104  //
105  for(auto &v : (*this)) {
106 
107  if( v == out_index1 || v == out_index2 )
108  v = out_index1;
109  else if( v > out_index2 )
110  v -= 1;
111  }
112 
113  //
114  // Merge prohibit rule
115  //
116  // (1) handle index < out_index1
117  for(size_t index=0; index < out_index1; ++index) {
118 
119  size_t tmp_out_index1 = out_index1 - index;
120  size_t tmp_out_index2 = out_index2 - index;
121 
122  _prohibit_merge.at(index).at(tmp_out_index1) = ( _prohibit_merge.at(index).at(tmp_out_index1)
123  ||
124  _prohibit_merge.at(index).at(tmp_out_index2)
125  );
126 
127  for(size_t in_index=tmp_out_index2;
128  //in_index < _prohibit_merge.at(index).size() - 1;
129  in_index < (_out_cluster_count - index - 1);
130  ++in_index) {
131 
132  /*
133  if(in_index >= (_out_cluster_count - 1 - index))
134 
135  _prohibit_merge.at(index).at(in_index) = false;
136 
137  else
138  */
139  _prohibit_merge.at(index).at(in_index) = _prohibit_merge.at(index).at(in_index+1);
140  }
141 
142  //(*_prohibit_merge.at(index).rbegin()) = false;
143  _prohibit_merge.at(index).at(_out_cluster_count - index - 1) = false;
144 
145  }
146 
147  // (2) handle index == out_index1
148  for(size_t in_index = 1;
149  //in_index < _prohibit_merge.at(out_index1).size() - 1;
150  in_index < (_out_cluster_count - out_index1 - 1);
151  ++in_index) {
152  if( (in_index + out_index1) < out_index2 ) {
153  /*
154  std::cout<<Form("Inspecting1 : (%d,%zu) to (%zu,%zu)",
155  out_index1,in_index,
156  (in_index + out_index1),(out_index2 - (in_index+out_index1)))
157  << std::endl;
158  */
159  _prohibit_merge.at(out_index1).at(in_index) = ( _prohibit_merge.at(out_index1).at(in_index)
160  ||
161  _prohibit_merge.at(in_index + out_index1).at(out_index2 - (in_index+out_index1))
162  );
163  }
164  else {
165  /*
166  std::cout<<Form("Inspecting2 : (%d,%zu) to (%d,%zu) ...",
167  out_index1,in_index+1,
168  out_index2,(in_index+out_index1-out_index2));
169  if(_prohibit_merge.at(out_index1).at(in_index+1)) std::cout<<"T";
170  else std::cout<<"F";
171  std::cout<<",";
172  if(_prohibit_merge.at(out_index2).at(in_index+out_index1-out_index2)) std::cout<<"T";
173  else std::cout<<"F";
174  std::cout<<std::endl;
175  */
176  _prohibit_merge.at(out_index1).at(in_index) = ( _prohibit_merge.at(out_index1).at(in_index+1)
177  ||
178  _prohibit_merge.at(out_index2).at(in_index+1+out_index1-out_index2)
179  );
180 
181  }
182  }
183  //(*_prohibit_merge.at(out_index1).rbegin()) = false;
184  _prohibit_merge.at(out_index1).at(_out_cluster_count - out_index1 - 1) = false;
185 
186  // (3) handle out_index1 < index < out_index2
187  for(size_t index = out_index1+1;
188  index < out_index2;
189  ++index){
190  for(size_t in_index = (out_index2 - index);
191  //in_index < (_prohibit_merge.at(index).size() - 1);
192  in_index < (_out_cluster_count - index - 1);
193  ++in_index)
194 
195  _prohibit_merge.at(index).at(in_index) = _prohibit_merge.at(index).at(in_index+1);
196 
197  //(*_prohibit_merge.at(index).rbegin()) = false;
198  _prohibit_merge.at(index).at(_out_cluster_count - index - 1) = false;
199  }
200  // (4) handle out_index2 <= index
201  for(size_t index = out_index2;
202  //index < (_prohibit_merge.size() - 1);
203  index < (_out_cluster_count - 1);
204  ++index) {
205 
206  for(size_t in_index = 0;
207  in_index < _prohibit_merge.at(index).size();
208  ++in_index)
209 
210  if(in_index < _prohibit_merge.at(index+1).size())
211  _prohibit_merge.at(index).at(in_index) = _prohibit_merge.at(index+1).at(in_index);
212 
213  else
214  _prohibit_merge.at(index).at(in_index) = false;
215 
216  }
217 
218  _out_cluster_count -=1;
219 
220  }
221 
223  {
224  std::cout<<"Merge Result:"<<std::endl;
225  for(auto const& v : *this)
226  std::cout<<v<< " ";
227  std::cout<<std::endl<<std::endl;
228 
229  std::cout<<"Prohibit Status:"<<std::endl;
230  for(auto const &bs : _prohibit_merge) {
231 
232  for(auto const &b : bs) {
233 
234  if(b) std::cout<<"\033[93mT\033[00m ";
235  else std::cout<<"\033[95mF\033[00m ";
236 
237  }
238  std::cout<<std::endl;
239  }
240  std::cout<<std::endl;
241 
242  }
243 
244  bool CMergeBookKeeper::IsMerged(unsigned short index1, unsigned short index2) const
245  {
246  if( index1 >= this->size() || index2 >= this->size() )
247  throw CMTException(Form("Invalid cluster index: %d or %d",index1,index2));
248 
249  return this->at(index1) == this->at(index2);
250  }
251 
252 
253  std::vector<unsigned short> CMergeBookKeeper::GetMergedSet(unsigned short index1) const
254  {
255 
256  if( index1 >= this->size() )
257  throw CMTException(Form("Invalid cluster index: %d ",index1));
258 
259  auto out_index = this->at(index1);
260  std::vector<unsigned short> result;
261 
262  for(size_t i=0; i<this->size(); ++i)
263  if( this->at(i) == out_index ) result.push_back(i);
264 
265  return result;
266  }
267 
268  void CMergeBookKeeper::PassResult(std::vector<std::vector<unsigned short> > &result) const
269  {
270 
271  result.clear();
272  result.resize(_out_cluster_count, std::vector<unsigned short>());
273 
274  for(size_t i=0; i<this->size(); ++i)
275  result.at(this->at(i)).push_back(i);
276  }
277 
279  {
280  // Check length compatibility between this instance's result and "another"
281  std::vector<std::vector<unsigned short> > my_result;
282  this->PassResult(my_result);
283  if(my_result.size() != another.size()) {
284  throw CMTException(Form("Input has an incompatible size (%zu != %zu)",
285  my_result.size(),
286  another.size())
287  );
288  return;
289  }
290 
291  // Check if "another" result is different from input
292  std::vector<std::vector<unsigned short> > another_result;
293  another.PassResult(another_result);
294  if(another_result.size() >= my_result.size())
295  throw CMTException(Form("The input has equal or more number of output clusters (%zu>=%zu)",
296  another_result.size(),
297  my_result.size())
298  );
299 
300  // Combine
301  for(auto const& ares : another_result) {
302 
303  if(ares.size()==1) continue;
304 
305  // Get one of cluster to be used for merging
306  unsigned short target = my_result.at(ares.at(0)).at(0);
307 
308  for(auto const &res_index : ares) {
309 
310  for(auto const &orig_index : my_result.at(res_index)) {
311 
312  if(target == orig_index) continue;
313 
314  else this->Merge(target,orig_index);
315 
316  }
317 
318  }
319 
320  }
321 
322  }
323 
324 }
void ProhibitMerge(unsigned short index1, unsigned short index2)
Method to set a pair of clusters to prohibit from merging.
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
Class def header for a class CMergeBookKeeper.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::vector< unsigned short > GetMergedSet(unsigned short index1) const
CMergeBookKeeper(unsigned short nclusters=0)
Default constructor.
size_t _out_cluster_count
Number of output clusters.
std::vector< std::vector< bool > > _prohibit_merge
Class def header for exception classes in CMTException.
void Combine(const CMergeBookKeeper &another)
createEngine this
void Merge(unsigned short index1, unsigned short index2)
Method to merge 2 clusters via index numbers.
bool MergeAllowed(unsigned short index1, unsigned short index2)
Method to inqury if a combination is prohibited to merge.
void PassResult(std::vector< std::vector< unsigned short > > &result) const
bool IsMerged(unsigned short index1, unsigned short index2) const
BEGIN_PROLOG could also be cout
void Reset(unsigned short nclusters=0)
Reset method.