1 #include "EVENT/LCIO.h"
2 #include "EVENT/LCRunHeader.h"
3 #include "EVENT/LCCollection.h"
4 #include "EVENT/LCParameters.h"
5 #include "EVENT/ReconstructedParticle.h"
6 #include "IMPL/ReconstructedParticleImpl.h"
8 #include "CLHEP/Vector/LorentzVector.h"
9 #include "CLHEP/Vector/ThreeVector.h"
15 #include <marlin/Global.h>
30 registerProcessorParameter(
"Printing" ,
31 "Print certain messages" ,
35 std::vector<std::string> gammagammaCandidateCollections;
36 gammagammaCandidateCollections.push_back(std::string(
"GammaGammaCandidatePi0s"));
37 gammagammaCandidateCollections.push_back(std::string(
"GammaGammaCandidateEtas"));
38 gammagammaCandidateCollections.push_back(std::string(
"GammaGammaCandidateEtaPrimes"));
39 registerInputCollections( LCIO::RECONSTRUCTEDPARTICLE,
40 "GammaGammaCandidateCollections" ,
41 "Gamma-Gamma Candidate Collection Names" ,
43 gammagammaCandidateCollections);
45 std::string outputParticleCollectionName =
"GammaGammaSolutions";
46 registerOutputCollection( LCIO::RECONSTRUCTEDPARTICLE,
47 "OutputParticleCollectionName" ,
48 "Output Particle Collection Name " ,
50 outputParticleCollectionName);
52 registerProcessorParameter(
"MaxCombinationsCut" ,
53 "Maximum Number of Explorable Combinations" ,
55 (
double)100000000.0) ;
57 registerProcessorParameter(
"LessThanMaximalCut" ,
58 "Maximum Number of Fewer GammaGammaParticles" ,
62 registerProcessorParameter(
"SolutionFindingAlgorithm" ,
63 "Solution Finding Algorithm" ,
90 recparcol->setSubset(
true);
95 if(
_printing>1)std::cout <<
"Find GammaGamma Solution: " << std::endl;
97 unsigned int nedges=
_pfovec.size();
99 if(
_printing>1)std::cout <<
"nphotons = " << nphotons <<
" nedges = " << nedges << std::endl;
101 if(
_printing>1)std::cout <<
"Naive combinatorial factor of " << std::setw(22) << nCr << std::endl;
109 if(
_printing>1)std::cout <<
" Pursuing full combinatoric exploration " << std::endl;
113 if(
_printing>1)std::cout <<
" Too many combinations - assigning quick greedy solution " << std::endl;
118 std::cout <<
"Unsupported solution finding algorithm " <<
_algorithm << std::endl;
138 if (k * 2 > n) k = n-
k;
139 if (k == 0)
return 1;
141 unsigned long int result = n;
142 for(
int i = 2; i <=
k; ++i ) {
153 if (i == array.size())
155 comb.push_back(accum);
159 std::vector<int> row = array[i];
160 for(
unsigned int j = 0; j < row.size(); ++j)
162 std::vector<int> tmp(accum);
163 tmp.push_back(row[j]);
178 typedef const std::vector<std::string>
StringVec ;
179 StringVec* strVec = evt->getCollectionNames() ;
183 for(StringVec::const_iterator name=strVec->begin(); name!=strVec->end(); name++){
186 LCCollection* col = evt->getCollection(*name);
187 unsigned int nelem = col->getNumberOfElements();
189 for(
unsigned int i=0;i<nelem;i++){
190 ReconstructedParticle* recoPart =
dynamic_cast<ReconstructedParticle*
>(col->getElementAt(i));
197 if(
_printing>1)std::cout <<
"FindPFOs : (nPFOs = " <<
_pfovec.size() <<
" )" << std::endl;
199 if(
_printing>1)std::cout <<
"Find PFOs : " << tf << std::endl;
209 if(
_printing>1)std::cout <<
"FindGammaGammaSolutionZero : (nPFOs = " <<
_pfovec.size() <<
" )" << std::endl;
211 typedef std::set<const ReconstructedParticle*> PfoSet;
212 PfoSet particles_assigned;
220 for(
unsigned int i = 0; i <
_pfovec.size(); i++){
221 const ReconstructedParticleVec particles =
_pfovec[i]->getParticles();
222 if(
_printing>3)std::cout <<
"FindGammaGammaSolutionZero: (nparticles = " << particles.size() <<
" )" << std::endl;
223 bool assignable =
true;
224 for(
unsigned int j = 0; j < particles.size(); j++){
225 const ReconstructedParticle *particle = particles[j];
226 if( particles_assigned.find(particle) != particles_assigned.end() )assignable =
false;
229 recparcol->addElement(
_pfovec[i]);
230 for(
unsigned int j = 0; j < particles.size(); j++){
231 const ReconstructedParticle *particle = particles[j];
232 particles_assigned.insert(particle);
243 if(
_printing>1)std::cout <<
"Count Independent Photons : (nPFOs = " <<
_pfovec.size() <<
" )" << std::endl;
245 typedef std::set<const ReconstructedParticle*> PfoSet;
246 PfoSet daughter_particles;
253 for(
unsigned int i = 0; i <
_pfovec.size(); i++){
254 const ReconstructedParticleVec particles =
_pfovec[i]->getParticles();
256 for(
unsigned int j = 0; j < particles.size(); j++){
257 const ReconstructedParticle *particle = particles[j];
260 if( daughter_particles.find(particle) == daughter_particles.end() ){
261 daughter_particles.insert(particle);
268 if(
_printing>1)std::cout <<
"Number of independent photons available = " << daughter_particles.size() << std::endl;
270 unsigned int nphotons = daughter_particles.size();
280 gettimeofday(&tv,NULL);
281 double t0 = tv.tv_sec+(tv.tv_usec/1000000.0);
283 std::vector<MyEdge> evec;
284 evec.reserve(
NEMAX*25);
285 std::vector<CandidateSolution> svec;
287 std::vector<FirstVertex> fvec;
288 fvec.reserve(
NVMAX*25);
293 std::bitset<NVMAX> vbits;
294 std::bitset<NVMAX> ored_vbits;
295 std::bitset<NEMAX> ebits;
296 std::bitset<NEMAX> febits;
297 unsigned long int nCr;
298 unsigned long int nCr2;
300 if(
_printing>1)std::cout <<
"FindGammaGammaSolutions : (nPFOs = " <<
_pfovec.size() <<
" )" << std::endl;
302 typedef std::set<const ReconstructedParticle*> PfoSet;
303 PfoSet daughter_particles;
304 PfoSet particles_assigned;
312 for(
unsigned int i = 0; i <
_pfovec.size(); i++){
313 const ReconstructedParticleVec particles =
_pfovec[i]->getParticles();
314 if(
_printing>3)std::cout <<
"FindGammaGammaSolutions: (nparticles = " << particles.size() <<
" )" << std::endl;
315 for(
unsigned int j = 0; j < particles.size(); j++){
316 const ReconstructedParticle *particle = particles[j];
318 if(
_printing>7)std::cout <<
"GWWWW " << i <<
" " << j <<
" " << particle << std::endl;
319 if( daughter_particles.find(particle) == daughter_particles.end() ){
320 daughter_particles.insert(particle);
322 if(
_printing>3)std::cout <<
"New photon " << particle <<
" " << k << std::endl;
329 if(
_printing>3)std::cout <<
"Set size " << daughter_particles.size() << std::endl;
330 for(std::set<const ReconstructedParticle*>::iterator it=daughter_particles.begin(); it!=daughter_particles.end(); ++it){
331 if(
_printing>3)std::cout << *it << std::endl;
336 if(
_printing>5)std::cout <<
"Graph definition file information Dry-Run" << std::endl;
337 if(
_printing>5)std::cout << std::setw(4) << daughter_particles.size() << std::setw(4) <<
_pfovec.size() << std::endl;
338 std::set<const ReconstructedParticle*>::iterator it;
339 std::pair<std::set<const ReconstructedParticle*>::iterator,
bool> retcode;
342 for(
unsigned int i = 0; i <
_pfovec.size(); i++){
343 const ReconstructedParticleVec particles =
_pfovec[i]->getParticles();
344 if(
_printing>5)std::cout <<
"GammaGammaCandidate " << std::setw(4) << i << std::endl;
345 for(
unsigned int j = 0; j < particles.size(); j++){
346 const ReconstructedParticle *particle = particles[j];
348 retcode = daughter_particles.insert(particle);
349 if (retcode.second) {
350 if(
_printing>5)std::cout << particle <<
" inserted as element ";
353 if(
_printing>5)std::cout << particle <<
" already exists as element ";
355 if(
_printing>5)std::cout << std::distance(daughter_particles.begin(),retcode.first) << std::endl;
361 if(
_printing>6)std::cout <<
"GRAPH definition file information" << std::endl;
362 int nvertices = daughter_particles.size();
364 typedef adjacency_list<vecS, vecS, undirectedS> my_graph;
365 my_graph g(nvertices);
366 int vertex_degree[
NVMAX];
367 for (
int i = 0; i <
NVMAX; ++i) {
368 vertex_degree[i] = 0;
370 if(
_printing>6)std::cout << std::setw(4) << daughter_particles.size() << std::setw(4) <<
_pfovec.size() << std::endl;
372 for(
unsigned int i = 0; i <
_pfovec.size(); i++){
373 const ReconstructedParticleVec particles =
_pfovec[i]->getParticles();
374 if(
_printing>6)std::cout << std::setw(4) << i;
375 for(
unsigned int j = 0; j < particles.size(); j++){
376 const ReconstructedParticle *particle = particles[j];
377 retcode = daughter_particles.insert(particle);
378 if(
_printing>6)std::cout <<
" " << std::setw(4) << std::distance(daughter_particles.begin(),retcode.first) ;
379 if(j==0)u = std::distance(daughter_particles.begin(),retcode.first);
380 if(j!=0)v = std::distance(daughter_particles.begin(),retcode.first);
385 const float GoodnessOfPID =
_pfovec[i]->getGoodnessOfPID();
386 if(
_printing>6)std::cout <<
" " << std::setw(4) << particleType <<
" " <<
387 std::fixed << std::setw(10) << std::setprecision(6) << GoodnessOfPID << std::endl;
390 evec[i].u = std::min(u,v);
391 evec[i].v = std::max(u,v);
393 evec[i].edge_pvalue = double(GoodnessOfPID);
394 edge_chisq = gsl_cdf_chisq_Qinv(
double(GoodnessOfPID), 1.0);
395 evec[i].edge_chisq = edge_chisq;
396 evec[i].w = edge_chisq;
400 evec[i].vbits = vbits;
401 vertex_degree[u] = vertex_degree[u]+1;
402 vertex_degree[v] = vertex_degree[v]+1;
404 add_edge(std::min(u,v),std::max(u,v),g);
409 if(
_printing>6)std::cout <<
" " << std::endl;
410 if(
_printing>6)std::cout <<
"Edge summary " << std::endl;
411 for (
int i = 0; i < nedges; ++i) {
412 if(
_printing>6)std::cout << std::setw(3) << i <<
" " << evec[i].vbits <<
" "
413 << std::setw(2) << evec[i].u <<
" " << std::setw(2) << evec[i].v << std::endl;
415 if(
_printing>6)std::cout <<
" " << std::endl;
416 if(
_printing>6)std::cout <<
"Vertex degrees " << std::endl;
418 for (
int i = 0; i < nvertices; ++i){
419 if(
_printing>6)std::cout << std::setw(3) << i <<
" " << std::setw(3) << vertex_degree[i] << std::endl;
420 vdsum += vertex_degree[i];
422 if(
_printing>6)std::cout <<
"vdsum = " << vdsum << std::endl;
424 if(
_printing>6)std::cout <<
"Vertex - Vertex partnerships" << std::endl;
425 for(
int iv =0; iv < nvertices; ++iv){
426 if(
_printing>6)std::cout <<
"Vertex " << std::setw(2) << iv <<
": " ;
427 for (
int je = 0; je < nedges; ++je) {
428 if(evec[je].u == iv){
429 if(
_printing>6)std::cout << std::setw(2) << evec[je].v <<
" ";
435 if(
_printing>6)std::cout <<
"Vertex - Edge partnerships" << std::endl;
436 for(
int iv =0; iv < nvertices; ++iv){
437 if(
_printing>6)std::cout <<
"Vertex " << std::setw(2) << iv <<
": " ;
440 for (
int je = 0; je < nedges; ++je) {
441 if(evec[je].u == iv){
442 if(
_printing>6)std::cout << std::setw(2) << je <<
" ";
449 fvec.back().ivertex = iv;
450 fvec.back().nedges = nfvedges;
451 fvec.back().febits = febits;
452 std::list<int> fvelist;
453 for (
int je = 0; je < nedges; ++je) {
456 fvelist.push_back(je);
458 if(nfound==1)fvec.back().fedge = je;
461 fvec.back().fvelist = fvelist;
465 if(
_printing>6)std::cout <<
" " << std::endl;
466 if(
_printing>6)std::cout <<
"Check FirstVertex structure" << std::endl;
467 if(
_printing>6)std::cout << std::setw(2) << fvec.size() <<
" FirstVertices out of "
468 << std::setw(2) << nvertices <<
" vertices in total" << std::endl;
469 if(
_printing>6)std::cout <<
" i iv ne febits Edges" << std::endl;
471 int nfirst_vertices = 0;
472 for(
unsigned int i = 0; i < fvec.size(); ++i) {
474 if(
_printing>6)std::cout << std::setw(2) << i <<
" " << std::setw(2) << fvec[i].ivertex <<
" "
475 << std::setw(2) << fvec[i].nedges <<
" " << fvec[i].febits <<
" { ";
476 for (std::list<int>::iterator it=fvec[i].fvelist.begin(); it!=fvec[i].fvelist.end(); ++it){
477 if(
_printing>6)std::cout << std::setw(2) << *it <<
" ";
479 if(
_printing>6)std::cout <<
"}" << std::endl;
481 if(
_printing>6)std::cout <<
"nfirst_vertices = "<<nfirst_vertices << std::endl;
484 std::vector<graph_traits<my_graph>::vertex_descriptor> mate(nvertices);
490 bool success = checked_edmonds_maximum_cardinality_matching(g, &mate[0]);
492 if(
_printing>6)std::cout << std::endl <<
"Found a matching of size " << matching_size(g, &mate[0]) << std::endl;
493 if(
_printing>6)std::cout <<
"The matching is:" << std::endl;
494 graph_traits<my_graph>::vertex_iterator vi, vi_end;
495 for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
496 if (mate[*vi] != graph_traits<my_graph>::null_vertex() && *vi < mate[*vi])
497 if(
_printing>6)std::cout <<
"{" << *vi <<
", " << mate[*vi] <<
"}" << std::endl;
501 int n = nfirst_vertices;
503 const unsigned int rmax = matching_size(g, &mate[0]);
504 if(
_printing>2)std::cout <<
"Setting rmax to " << rmax << std::endl;
510 if(rminB>rminA)rminC = rminB;
511 const unsigned int rmin = rminC;
514 if(
_printing>2)std::cout <<
"Setting rmin to " << rmin << std::endl;
516 gettimeofday(&tv,NULL);
517 double t1 = tv.tv_sec+(tv.tv_usec/1000000.0);
519 if(
_printing>3)std::cout <<
"Initialization took " << std::fixed << std::setw(12) << std::setprecision(6) << t1-t0 <<
" (s) " << std::endl;
522 for (
unsigned int r=rmax; r>=rmin; --r){
524 if(
_printing>2)std::cout <<
"subsidiary matching problem: find " << r <<
" edges from the set of size " << n <<
" with no overlaps " << std::endl;
527 if(
_printing>2)std::cout <<
"combination counting ... nfv = " << n <<
" r = " << std::setw(2) << r
528 <<
" nCr = " << std::setw(22) << nCr <<
" nCr (fv) = " << std::setw(22) << nCr2 << std::endl;
530 int nmatch_withr = 0;
532 unsigned long int icombi=0;
535 std::vector<bool> vb(n);
537 std::fill(vb.begin() + r, vb.end(),
true);
539 for (
int i = 0; i < n; ++i) {
552 std::vector< std::vector<int> > array;
554 for(
unsigned int i=0; i<r; ++i) {
556 std::vector<int> tmp;
557 if(fvec[d[i]].nedges>1){
559 for (std::list<int>::iterator it=fvec[d[i]].fvelist.begin(); it!=fvec[d[i]].fvelist.end(); ++it){
564 array.push_back(tmp);
567 c.push_back(fvec[d[i]].fedge);
573 std::vector<int> accum;
576 for ( std::vector<std::vector<int> >::size_type i = 0; i <
comb.size(); ++i )
580 if(c.size()==r &&
comb[i].size()>0){
581 c.erase(c.begin()+nfilled,c.end());
583 for ( std::vector<int>::size_type j = 0; j <
comb[i].size(); ++j )
585 c.push_back(
comb[i][j]);
589 ored_vbits = evec[c[0]].vbits;
590 for (
unsigned int i=1; i<r; ++i){
591 ored_vbits = (ored_vbits | evec[c[i]].vbits);
592 if(ored_vbits.count()!=2*(i+1))
break;
594 size_t nused = ored_vbits.count();
605 for (
unsigned int i=0; i<r; ++i){
612 wsum += evec[c[i]].w;
613 if(evec[c[i]].pdgid==111)npi0++;
614 if(evec[c[i]].pdgid==221)neta++;
615 if(evec[c[i]].pdgid==331)netap++;
620 svec.back().nv = nused;
621 svec.back().wsum = wsum;
622 svec.back().ebits = ebits;
623 svec.back().npi0 = npi0;
624 svec.back().neta = neta;
625 svec.back().netap = netap;
627 double dof = double(r);
628 double chisq_value = wsum;
629 double pvalue = gsl_cdf_chisq_Q(chisq_value,dof);
630 svec.back().pvalue = pvalue;
631 svec.back().icomb = icombi;
642 if(!d.empty())d.clear();
643 if(!array.empty())array.clear();
646 }
while ( std::next_permutation(vb.begin(), vb.end() ) );
648 if(
_printing>2)std::cout <<
"Found " << std::setw(7) << nmatch_withr <<
" matches with "
649 << std::setw(3) << r <<
" edges from " << std::setw(22) << nCr <<
" combinations " << std::endl;
651 gettimeofday(&tv,NULL);
652 t2 = tv.tv_sec+(tv.tv_usec/1000000.0);
653 if(
_printing>3)std::cout <<
"Match search for n = " << std::setw(2) << n <<
" r = " << std::setw(2) << r <<
" "
654 << std::fixed << std::setw(12) << std::setprecision(6) << t2-t1 <<
" (s) "
655 << std::fixed << std::setw(12) << std::setprecision(6) << 1.0e6*(t2-t1)/
double(nCr)
656 <<
" micro-seconds per combination " << std::endl;
661 if(
_printing>2)std::cout <<
"Found " << std::setw(7) << nmatch <<
" matches total " << std::endl;
663 if(
_printing>5)std::cout <<
"Two particle hypothesis results (pi0, eta) with rmax = " << rmax << std::endl;
668 for (
unsigned int r=rmax; r>0; --r){
669 double min_wsum = 999999.0;
670 double max_wsum = -999999.0;
674 for(
unsigned int i = 0; i < svec.size(); ++i) {
675 if(svec[i].ne ==
int(r) && svec[i].netap ==0){
677 if(svec[i].wsum > max_wsum){
678 max_wsum = svec[i].wsum;
682 if(svec[i].wsum < min_wsum){
683 min_wsum = svec[i].wsum;
690 if(r==rmax && imin >= 0)ibest = imin;
691 if(imin>=0 && imax >=0)
692 if(
_printing>5)std::cout <<
"wsum extrema for r = " << std::setw(2) << r <<
" " << std::setw(10) << min_wsum <<
" " << std::setw(10) << max_wsum
693 <<
" pvalues " << std::setw(12) << svec[imin].pvalue <<
" " << std::setw(12) << svec[imax].pvalue
694 <<
" ( " << imin <<
" " << imax <<
" ) " <<
" Combinations " << svec[imin].icomb <<
" " << svec[imax].icomb << std::endl;
698 double pvalue = gsl_cdf_chisq_Q(svec[ibest].wsum,svec[ibest].ne);
699 if(
_printing>4)std::cout <<
"Best candidate solution " << ibest << std::endl;
700 if(
_printing>4)std::cout <<
"npi0, neta, netap " << svec[ibest].npi0 <<
" " << svec[ibest].neta <<
" " << svec[ibest].netap << std::endl;
701 if(
_printing>4)std::cout << std::setw(4) << ibest <<
" " << std::setw(2) << svec[ibest].ne <<
" "
702 << std::setw(2) << svec[ibest].nv <<
" " << svec[ibest].ebits <<
" "
703 << std::fixed << std::setw(10) << std::setprecision(5) << svec[ibest].wsum <<
" "
704 << std::fixed << std::setw(10) << std::setprecision(6) << pvalue << std::endl;
706 for (
unsigned int i=0; i<
NEMAX; ++i){
707 if( (svec[ibest].ebits).test(i) ){
708 if(
_printing>4)std:: cout <<
"Edge " << std::setw(2) << i <<
" " << std::setw(2) << evec[i].u <<
" "
709 << std::setw(2) << evec[i].v <<
" " << evec[i].pdgid <<
" "
710 << std::fixed << std::setw(10) << std::setprecision(6) << evec[i].edge_pvalue << std::endl;
715 gettimeofday(&tv,NULL);
716 double t3 = tv.tv_sec+(tv.tv_usec/1000000.0);
717 if(
_printing>2)std::cout <<
"Solution analysis time = " << std::fixed << std::setw(12) << std::setprecision(6) << t3-t2 <<
" (s) " << std::endl;
718 if(
_printing>2)std::cout <<
"Total elapsed time = " << std::fixed << std::setw(12) << std::setprecision(6) << t3-t0 <<
" (s) " << std::endl;
727 if(
_printing>3)std::cout <<
"ALGORITHM2 RESULTS" << std::endl;
728 for(
unsigned int i = 0; i <
_pfovec.size(); ++i){
729 if( (svec[ibest].ebits).test(i) ){
730 const ReconstructedParticleVec particles =
_pfovec[i]->getParticles();
731 bool assignable =
true;
732 for(
unsigned int j = 0; j < particles.size(); ++j){
733 const ReconstructedParticle *particle = particles[j];
734 if( particles_assigned.find(particle) != particles_assigned.end() )assignable =
false;
737 recparcol->addElement(
_pfovec[i]);
738 if(
_printing>3)std::cout << std::setw(4) << i;
739 for(
unsigned int j = 0; j < particles.size(); ++j){
740 const ReconstructedParticle *particle = particles[j];
741 particles_assigned.insert(particle);
743 retcode = daughter_particles.insert(particle);
744 if(
_printing>3)std::cout <<
" " << std::setw(4) << std::distance(daughter_particles.begin(),retcode.first) ;
748 const float GoodnessOfPID =
_pfovec[i]->getGoodnessOfPID();
749 if(
_printing>3)std::cout <<
" " << std::setw(4) << particleType <<
" "
750 << std::fixed << std::setw( 10 ) << std::setprecision( 6 ) << GoodnessOfPID << std::endl;
767 const int lhs_particleType = lhs->getType();
768 const int rhs_particleType = rhs->getType();
771 const float lhs_GoodnessOfPID = lhs->getGoodnessOfPID();
772 const float rhs_GoodnessOfPID = rhs->getGoodnessOfPID();
774 if(lhs_particleType==rhs_particleType)
return (lhs_GoodnessOfPID>rhs_GoodnessOfPID);
775 return (lhs_particleType<rhs_particleType);
void FindGammaGammaSolutions(LCCollectionVec *)
GammaGammaSolutionFinder()
std::string _outputParticleCollectionName
virtual void processEvent(LCEvent *evt)
Called for every event - the working horse.
unsigned long int CombinatorialFactor(int n, int k)
CLHEP::Hep3Vector Vector3D
virtual void init()
Called at the beginning of the job before anything is read.
double _maxCombinationsCut
GammaGammaSolutionFinder:
bool FindPFOs(LCEvent *evt)
GammaGammaSolutionFinder aGammaGammaSolutionFinder
static bool PfoProbabilitySortFunction(ReconstructedParticle *lhs, ReconstructedParticle *rhs)
std::vector< std::string > _gammagammaCandidateCollections
CLHEP::HepLorentzVector LorentzVector
std::vector< ReconstructedParticle * > _pfovec
unsigned int CountIndependentPhotons()
virtual void processRunHeader(LCRunHeader *run)
Called for every run.
std::vector< LCCollection * > LCCollectionVec
virtual void end()
Called after data processing for clean up.
void FindCombinations(std::vector< std::vector< int > > array, unsigned int i, std::vector< int > accum)
void FindGammaGammaSolutionZero(LCCollectionVec *)
std::vector< std::vector< int > > comb
std::vector< std::string > StringVec