mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-01 08:07:10 -04:00
acd269fc97
git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6561 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
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();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|