mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-31 13:10:19 -04:00 
			
		
		
		
	
		
			
	
	
		
			201 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			201 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | /************************************************************************/ | ||
|  | /*                                                                      */ | ||
|  | /*        Free software: Progressive edge-growth (PEG) algorithm        */ | ||
|  | /*        Created by Xiaoyu Hu                                          */ | ||
|  | /*                   Evangelos Eletheriou                               */ | ||
|  | /*                   Dieter Arnold                                      */ | ||
|  | /*        IBM Research, Zurich Research Lab., Switzerland               */ | ||
|  | /*                                                                      */ | ||
|  | /*        The C++ sources files have been compiled using xlC compiler   */ | ||
|  | /*        at IBM RS/6000 running AIX. For other compilers and platforms,*/ | ||
|  | /*        minor changes might be needed.                                */ | ||
|  | /*                                                                      */ | ||
|  | /*        Bug reporting to: xhu@zurich.ibm.com                          */ | ||
|  | /**********************************************************************/ | ||
|  | 
 | ||
|  | ////
 | ||
|  | // Modified by F. P. Beekhof; 2008 / 08 / 19
 | ||
|  | ////
 | ||
|  | 
 | ||
|  | #include <cstdlib>
 | ||
|  | #include <cstring>
 | ||
|  | #include <string>
 | ||
|  | #include <iostream>
 | ||
|  | #include <iomanip>
 | ||
|  | #include <fstream>
 | ||
|  | #include <cmath>
 | ||
|  | #include <vector>
 | ||
|  | #include "BigGirth.h"
 | ||
|  | #include "Random.h"
 | ||
|  | #include "CyclesOfGraph.h"
 | ||
|  | 
 | ||
|  | const double EPS = 1e-6; | ||
|  | 
 | ||
|  | using namespace std; | ||
|  | 
 | ||
|  | void usage() | ||
|  | { | ||
|  |     cout<<"*******************************************************************************************"<<endl; | ||
|  |     cout<<" Usage Reminder: MainPEG -numM M -numN N -codeName CodeName -degFileName DegFileName " <<endl; | ||
|  |     cout<<"         option:         -sglConcent SglConcent                                     " <<endl;  | ||
|  |     cout<<"                         sglConcent==0 ----- strictly concentrated parity-check      " <<endl; | ||
|  |     cout<<"                                       degree distribution (including regular graphs)" <<endl; | ||
|  |     cout<<"                         sglConcent==1 ----- Best-effort concentrated (DEFAULT)      " <<endl; | ||
|  |     cout<<"         option:         -tgtGirth TgtGirth                                          " <<endl;  | ||
|  |     cout<<"                  TgtGirth==4, 6 ...; if very large, then greedy PEG (DEFAULT)       " <<endl; | ||
|  |     cout<<"                  IF sglConcent==0, TgtGirth is recommended to be set relatively small" <<endl; | ||
|  |     cout<<"         option:         -q                                          " <<endl;  | ||
|  |     cout<<"                  Quiet mode. Produces less output to the screen.       " <<endl; | ||
|  |     cout<<"         option:         -outputMode <0,1,2>                                    " <<endl; | ||
|  |     cout<<"                  Specifies output format.      " <<endl; | ||
|  |     cout<<"                  '0': H in compressed format (default)       " <<endl; | ||
|  |     cout<<"                  '1': H in un-compressed format       " <<endl; | ||
|  |     cout<<"                  '2': G and H in compressed format       " <<endl; | ||
|  |     cout<<"                                                                                       " <<endl; | ||
|  |     cout<<" Remarks: File CodeName stores the generated PEG Tanner graph. The first line contains"<<endl; | ||
|  |     cout<<"          the block length, N. The second line defines the number of parity-checks, M."<<endl; | ||
|  |     cout<<"          The third line defines the number of columns of the compressed parity-check "<<endl; | ||
|  |     cout<<"          matrix. The following M lines are then the compressed parity-check matrix.  "<<endl; | ||
|  |     cout<<"          Each of the M rows contains the indices (1 ... N) of 1's in the compressed  "<<endl; | ||
|  |     cout<<"          row of parity-check matrix. If not all column entries are used, the column  "<<endl; | ||
|  |     cout<<"          is filled up with 0's.                                                      "<<endl; | ||
|  |     cout<<"                                                                                      "<<endl; | ||
|  |     cout<<"          If both G and H are in the output, (outMode 2), the first line contains"<<endl; | ||
|  |     cout<<"          N, the 2nd line K, the number of message bits, the 3rd line M, the 4th line"<<endl; | ||
|  |     cout<<"          contains the number of rows of the compressed generator matrix; the 5th"<<endl; | ||
|  |     cout<<"          defines the number of columns of the compressed parity-check matrix. The"<<endl; | ||
|  |     cout<<"          format of G is almost like that of H, but vertical -- i.e. the padding"<<endl; | ||
|  |     cout<<"          zeroes are on the bottom.   "<<endl; | ||
|  | 
 | ||
|  |     cout<<"                                                                                      "<<endl; | ||
|  |     cout<<"          File DegFileName is the input file to specify the degree distribution (node "<<endl; | ||
|  |     cout<<"          perspective). The first line contains the number of various degrees. The second"<<endl; | ||
|  |     cout<<"          defines the row vector of degree sequence in the increasing order. The vector"<<endl; | ||
|  |     cout<<"          of fractions of the corresponding degree is defined in the last line.         "<<endl; | ||
|  |     cout<<"                                                                                       "<<endl; | ||
|  |     cout<<"          A log file called 'leftHandGirth.dat' will also be generated and stored in the"<<endl; | ||
|  |     cout<<"          current directory, which gives the girth of the left-hand subgraph of j, where"<<endl; | ||
|  |     cout<<"          1<=j<=N. The left-hand subgraph of j is defined as all the edges emanating from"<<endl; | ||
|  |     cout<<"          bit nodes {1 ... j} and their associated nodes.                                "<<endl;  | ||
|  |     cout<<"                                                                                         "<<endl; | ||
|  |     cout<<"          The last point is, when strictly concentrated parity-check degree distribution"<<endl; | ||
|  |     cout<<"          is invoked, i.e. sglConcent==0, the girth might be weaken to some extent as    "<<endl; | ||
|  |     cout<<"          compared to the generic PEG algorithm.                                         "<<endl; | ||
|  |     cout<<"**********************************************************************************************"<<endl; | ||
|  |     exit(-1); | ||
|  | } | ||
|  | 
 | ||
|  | int main(int argc, char * argv[]){ | ||
|  |   int sglConcent=1;  // default to non-strictly concentrated parity-check distribution
 | ||
|  |   int targetGirth=100000; // default to greedy PEG version 
 | ||
|  |   std::string codeName, degFileName; | ||
|  |   int M = -1, N = -1; | ||
|  |   bool verbose = true; | ||
|  | 
 | ||
|  |   const int OUTPUT_MODE_H_COMPRESSED = 0; | ||
|  |   const int OUTPUT_MODE_H = 1; | ||
|  |   const int OUTPUT_MODE_G_H_COMPRESSED = 2; | ||
|  |   int output_mode = OUTPUT_MODE_H_COMPRESSED; // default
 | ||
|  | 
 | ||
|  |   if (argc<9) { | ||
|  |     usage(); | ||
|  |   }else { | ||
|  |     for(int i=1;i<argc;++i){ | ||
|  |       if (strcmp(argv[i], "-numM")==0) { | ||
|  | 	if (++i >= argc) usage(); | ||
|  | 	M=atoi(argv[i]); | ||
|  |       } else if(strcmp(argv[i], "-numN")==0) { | ||
|  | 	if (++i >= argc) usage(); | ||
|  | 	N=atoi(argv[i]); | ||
|  |       } else if(strcmp(argv[i], "-codeName")==0) { | ||
|  | 	if (++i >= argc) usage(); | ||
|  | 	codeName = argv[i];  | ||
|  |       } else if(strcmp(argv[i], "-degFileName")==0) { | ||
|  | 	if (++i >= argc) usage(); | ||
|  | 	degFileName = argv[i];  | ||
|  |       } else if(strcmp(argv[i], "-sglConcent")==0) { | ||
|  | 	if (++i >= argc) usage(); | ||
|  | 	sglConcent=atoi(argv[i]); | ||
|  |       } else if(strcmp(argv[i], "-tgtGirth")==0) { | ||
|  | 	if (++i >= argc) usage(); | ||
|  | 	targetGirth=atoi(argv[i]); | ||
|  |       } else if(strcmp(argv[i], "-outputMode")==0) { | ||
|  | 	if (++i >= argc) usage(); | ||
|  | 	output_mode=atoi(argv[i]); | ||
|  |       } else if(strcmp(argv[i], "-q")==0) { | ||
|  | 	verbose=false; | ||
|  |       } else{ | ||
|  | 	usage(); | ||
|  |       } | ||
|  |     } | ||
|  |     if (M == -1 || N == -1) { | ||
|  |       cout<<"Error: M or N not specified!"<<endl; | ||
|  |       exit(-1); | ||
|  |     } | ||
|  |     if (M>N) { | ||
|  |       cout<<"Error: M must be smaller than N!"<<endl; | ||
|  |       exit(-1); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   std::vector<int> degSeq(N); | ||
|  | 
 | ||
|  |   ifstream infn(degFileName.c_str()); | ||
|  |   if (!infn) {cout << "\nCannot open file " << degFileName << endl; exit(-1); }  | ||
|  |   int m; | ||
|  |   infn >>m; | ||
|  |   std::vector<int> deg(m); | ||
|  |   std::vector<double> degFrac(m); | ||
|  |   for(int i=0;i<m;i++) infn>>deg[i]; | ||
|  |   for(int i=0;i<m;i++) infn>>degFrac[i]; | ||
|  |   infn.close(); | ||
|  |   double dtmp=0.0; | ||
|  |   for(int i=0;i<m;i++) dtmp+=degFrac[i]; | ||
|  |   cout.setf(ios::fixed, ios::floatfield); | ||
|  |   if(abs(dtmp-1.0)>EPS) { | ||
|  |     cout.setf(ios::fixed, ios::floatfield); | ||
|  |     cout <<"\n Invalid degree distribution (node perspective): sum != 1.0 but "<<setprecision(10)<<dtmp<<endl; exit(-1);  | ||
|  |   }  | ||
|  |   for(int i=1;i<m;++i) degFrac[i]+=degFrac[i-1]; | ||
|  |   for(int i=0;i<N;++i) { | ||
|  |     dtmp=double(i)/double(N); | ||
|  |     int j; | ||
|  |     for(j=m-1;j>=0;--j) { | ||
|  |       if(dtmp>degFrac[j]) break; | ||
|  |     } | ||
|  |     if(dtmp<degFrac[0]) degSeq[i]=deg[0]; | ||
|  |     else degSeq[i]=deg[j+1]; | ||
|  |   } | ||
|  | 
 | ||
|  |   BigGirth bigGirth(M, N, °Seq[0], codeName.c_str(), | ||
|  | 		    sglConcent, targetGirth, verbose); | ||
|  | 
 | ||
|  |   switch(output_mode) | ||
|  |   { | ||
|  | 	case OUTPUT_MODE_H_COMPRESSED: bigGirth.writeToFile_Hcompressed(); break; | ||
|  |   	case OUTPUT_MODE_H:   //  different output format
 | ||
|  | 		bigGirth.writeToFile_Hmatrix(); break; | ||
|  | 	case OUTPUT_MODE_G_H_COMPRESSED: | ||
|  | 	//  different output format: including generator matrix (compressed)
 | ||
|  | 		bigGirth.writeToFile(); break; | ||
|  | 	default: | ||
|  | 		cout << "Error: invalid output mode specified." << endl << endl; | ||
|  | 		usage(); | ||
|  |   } | ||
|  |    | ||
|  |   //computing local girth distribution  
 | ||
|  | 
 | ||
|  |   if (verbose && N<10000) { | ||
|  |     cout<<" Now computing the local girth on the global Tanner graph setting. "<<endl; | ||
|  |     cout<<"     might take a bit long time. Please wait ...                   "<<endl; | ||
|  |     bigGirth.loadH(); | ||
|  |     CyclesOfGraph cog(M, N, bigGirth.H); | ||
|  |     cog.getCyclesTable(); | ||
|  |     cog.printCyclesTable(); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 |