TreeEP::TreeEP( const FactorGraph &fg, const PropertySet &opts ) : JTree(fg, opts("updates",string("HUGIN")), false), _maxdiff(0.0), _iters(0), props(), _Q() { setProperties( opts ); if( opts.hasKey("tree") ) { construct( fg, opts.getAs<RootedTree>("tree") ); } else { if( props.type == Properties::TypeType::ORG || props.type == Properties::TypeType::ALT ) { // ORG: construct weighted graph with as weights a crude estimate of the // mutual information between the nodes // ALT: construct weighted graph with as weights an upper bound on the // effective interaction strength between pairs of nodes WeightedGraph<Real> wg; // in order to get a connected weighted graph, we start // by connecting every variable to the zero'th variable with weight 0 for( size_t i = 1; i < fg.nrVars(); i++ ) wg[UEdge(i,0)] = 0.0; for( size_t i = 0; i < fg.nrVars(); i++ ) { SmallSet<size_t> delta_i = fg.bipGraph().delta1( i, false ); const Var& v_i = fg.var(i); foreach( size_t j, delta_i ) if( i < j ) { const Var& v_j = fg.var(j); VarSet v_ij( v_i, v_j ); SmallSet<size_t> nb_ij = fg.bipGraph().nb1Set( i ) | fg.bipGraph().nb1Set( j ); Factor piet; foreach( size_t I, nb_ij ) { const VarSet& Ivars = fg.factor(I).vars(); if( props.type == Properties::TypeType::ORG ) { if( (Ivars == v_i) || (Ivars == v_j) ) piet *= fg.factor(I); else if( Ivars >> v_ij ) piet *= fg.factor(I).marginal( v_ij ); } else { if( Ivars >> v_ij ) piet *= fg.factor(I); } } if( props.type == Properties::TypeType::ORG ) { if( piet.vars() >> v_ij ) { piet = piet.marginal( v_ij ); Factor pietf = piet.marginal(v_i) * piet.marginal(v_j); wg[UEdge(i,j)] = dist( piet, pietf, DISTKL ); } else { // this should never happen... DAI_ASSERT( 0 == 1 ); wg[UEdge(i,j)] = 0; } } else wg[UEdge(i,j)] = piet.strength(v_i, v_j); }
TestDAI( const FactorGraph &fg, const string &_name, const PropertySet &opts ) : obj(NULL), name(_name), err(), q(), logZ(0.0), maxdiff(0.0), time(0), iters(0U), has_logZ(false), has_maxdiff(false), has_iters(false) { double tic = toc(); if( name == "LDPC" ) { double zero[2] = {1.0, 0.0}; q.clear(); for( size_t i = 0; i < fg.nrVars(); i++ ) q.push_back( Factor(Var(i,2), zero) ); logZ = 0.0; maxdiff = 0.0; iters = 1; has_logZ = false; has_maxdiff = false; has_iters = false; } else obj = newInfAlg( name, fg, opts ); time += toc() - tic; }
/// Construct from factor graph \a fg, name \a _name, and set of properties \a opts TestDAI( const FactorGraph &fg, const string &_name, const PropertySet &opts ) : obj(NULL), name(_name), varErr(), facErr(), varMarginals(), facMarginals(), allMarginals(), logZ(0.0), maxdiff(0.0), time(0), iters(0U), has_logZ(false), has_maxdiff(false), has_iters(false) { double tic = toc(); if( name == "LDPC" ) { // special case: simulating a Low Density Parity Check code Real zero[2] = {1.0, 0.0}; for( size_t i = 0; i < fg.nrVars(); i++ ) varMarginals.push_back( Factor(fg.var(i), zero) ); allMarginals = varMarginals; logZ = 0.0; maxdiff = 0.0; iters = 1; has_logZ = false; has_maxdiff = false; has_iters = false; } else // create a corresponding InfAlg object obj = newInfAlg( name, fg, opts ); // Add the time needed to create the object time += toc() - tic; }
int main( int argc, char *argv[] ) { if ( argc != 2 ) { cout << "Usage: " << argv[0] << " <filename.fg>" << endl << endl; cout << "Reads factor graph <filename.fg> and verifies" << endl; cout << "whether BBP works correctly on it." << endl << endl; return 1; } else { // Read FactorGraph from the file specified by the first command line argument FactorGraph fg; fg.ReadFromFile(argv[1]); // Set some constants size_t verbose = 0; Real tol = 1.0e-9; size_t maxiter = 10000; Real damping = 0.0; // Store the constants in a PropertySet object PropertySet opts; opts.set("verbose",verbose); // Verbosity (amount of output generated) opts.set("tol",tol); // Tolerance for convergence opts.set("maxiter",maxiter); // Maximum number of iterations opts.set("damping",damping); // Amount of damping applied // Construct a BP (belief propagation) object from the FactorGraph fg BP bp(fg, opts("updates",string("SEQFIX"))("logdomain",false)); bp.recordSentMessages = true; bp.init(); bp.run(); vector<size_t> state( fg.nrVars(), 0 ); for( size_t t = 0; t < 45; t++ ) { BBP::Properties::UpdateType updates; switch( t % 5 ) { case BBP::Properties::UpdateType::SEQ_FIX: updates = BBP::Properties::UpdateType::SEQ_FIX; break; case BBP::Properties::UpdateType::SEQ_MAX: updates = BBP::Properties::UpdateType::SEQ_MAX; break; case BBP::Properties::UpdateType::SEQ_BP_REV: updates = BBP::Properties::UpdateType::SEQ_BP_REV; break; case BBP::Properties::UpdateType::SEQ_BP_FWD: updates = BBP::Properties::UpdateType::SEQ_BP_FWD; break; case BBP::Properties::UpdateType::PAR: updates = BBP::Properties::UpdateType::PAR; break; } BBPCostFunction cfn; switch( (t / 5) % 9 ) { case 0: cfn = BBPCostFunction::CFN_GIBBS_B; break; case 1: cfn = BBPCostFunction::CFN_GIBBS_B2; break; case 2: cfn = BBPCostFunction::CFN_GIBBS_EXP; break; case 3: cfn = BBPCostFunction::CFN_GIBBS_B_FACTOR; break; case 4: cfn = BBPCostFunction::CFN_GIBBS_B2_FACTOR; break; case 5: cfn = BBPCostFunction::CFN_GIBBS_EXP_FACTOR; break; case 6: cfn = BBPCostFunction::CFN_VAR_ENT; break; case 7: cfn = BBPCostFunction::CFN_FACTOR_ENT; break; case 8: cfn = BBPCostFunction::CFN_BETHE_ENT; break; } Real h = 1e-4; Real result = numericBBPTest( bp, &state, opts("updates",updates), cfn, h ); cout << "result: " << result << ",\tupdates=" << updates << ", cfn=" << cfn << endl; } } return 0; }
int main( int argc, char *argv[] ) { int i; char* myString = (char*) malloc (50); if ( argc < 3 ) { cout << "Usage: Filename and then Number of Nodes in the One Loop Graph. " << endl; cout << "Reads filename, it creates the fg file and then runs inference algorithms" << endl; return 1; } else { strcpy(myString,"Results"); strcat(myString,argv[1]); ofstream file( myString,ios::out); FactorGraph fg; vector<Var> vars; vector<Factor> factors; //Number of variables. size_t dimx=atoi(argv[2]); double J=0.5; size_t N=dimx; vars.reserve( N ); for( size_t i = 0; i < N; i++ ) vars.push_back( Var( i, 2 ) ); factors.reserve( N ); for( size_t i = 0; i < dimx; i++ ){ // Add a pairwise interaction with the next neighboring pixel if (i!=dimx-1) factors.push_back( createFactorIsing( vars[i], vars[i+1], J ) ); else if (i==dimx-1) factors.push_back( createFactorIsing( vars[i], vars[0], J ) ); // Add a single-variable interaction with strength th. double th=0.1; factors.push_back( createFactorIsing( vars[i], th) ); } fg=FactorGraph( factors.begin(), factors.end(), vars.begin(), vars.end(), factors.size(), vars.size() ); fg.WriteToFile( strcat(myString,".fg") ); cout << "1" << endl; // Set some constants size_t maxiter = 10000; Real tol = 1e-9; size_t verb = 1; // Store the constants in a PropertySet object PropertySet opts,cavaiopts; opts.set("maxiter",maxiter); // Maximum number of iterations opts.set("tol",tol); // Tolerance for convergence opts.set("verbose",verb); // Verbosity (amount of output generated) cavaiopts.set("maxiter",maxiter); // Maximum number of iterations cavaiopts.set("tol",tol); // Tolerance for convergence cavaiopts.set("verbose",verb); // Verbosity (amount of output generated) cavaiopts.set("updates",string("HUGIN")); printf("Doing Juction Tree\n"); JTree jt( fg, opts("updates",string("HUGIN")) ); jt.init(); jt.run(); printf("Doing BP\n"); BP bp(fg, opts("updates",string("SEQRND"))("logdomain",false)); bp.init(); bp.run(); printf("Doing LC\n"); LC lc(fg, opts("updates",string("SEQRND"))("logdomain",false)("cavity",string("PAIR"))("cavainame",string("BP"))("cavaiopts",string("[updates=SEQMAX,tol=1e-9,maxiter=10000,logdomain=0]"))); //LC lc(fg, opts("updates",string("SEQRND"))("logdomain",false)("cavity",string("UNIFORM"))); //LC lc(fg, opts("updates",string("SEQRND"))("logdomain",false)("cavity",string("FULL"))); lc.init(); lc.run(); printf("Doing MR\n"); MR mr(fg, opts("updates",string("LINEAR"))("logdomain",false)("inits",string("CLAMPING"))); mr.init(); mr.run(); // Report variable marginals for fg, calculated by the junction tree algorithm file << "Exact variable marginals:" << endl; for( size_t i = 0; i < fg.nrVars(); i++ ) // iterate over all variables in fg file << jt.belief(fg.var(i)) << endl; // display the "belief" of jt for that variable file << "\n" << endl; // Report variable marginals for fg, calculated by the belief propagation algorithm file << "Approximate (LBF) variable marginals:" << endl; for( size_t i = 0; i < fg.nrVars(); i++ ) // iterate over all variables in fg file << bp.belief(fg.var(i)) << endl; // display the belief of bp for that variable file << "\n" << endl; // Report variable marginals for fg, calculated by the MoK07 file << "Approximate (Loop Corrected MoK07) variable marginals:" << endl; for( size_t i = 0; i < fg.nrVars(); i++ ) // iterate over all variables in fg file << lc.belief(fg.var(i)) << endl; // display the belief of bp for that variable file << "\n" << endl; // Report variable marginals for fg, calculated by the MR05 file << "Approximate (Loop Corrected MR05) variable marginals:" << endl; for( size_t i = 0; i < fg.nrVars(); i++ ) // iterate over all variables in fg file << mr.belief(fg.var(i)) << endl; // display the belief of bp for that variable file << "\n" << endl; file.close(); } return 0; }
int main( int argc, char *argv[] ) { if ( argc != 3 ) { cout << "Usage: " << argv[0] << " <filename.fg> [map|pd]" << endl << endl; cout << "Reads factor graph <filename.fg> and runs" << endl; cout << "map: Junction tree MAP" << endl; cout << "pd : LBP and posterior decoding" << endl << endl; return 1; } else { // Redirect cerr to inf.log ofstream errlog("inf.log"); //streambuf* orig_cerr = cerr.rdbuf(); cerr.rdbuf(errlog.rdbuf()); // Read FactorGraph from the file specified by the first command line argument FactorGraph fg; fg.ReadFromFile(argv[1]); // Set some constants size_t maxiter = 10000; Real tol = 1e-9; size_t verb = 1; // Store the constants in a PropertySet object PropertySet opts; opts.set("maxiter",maxiter); // Maximum number of iterations opts.set("tol",tol); // Tolerance for convergence opts.set("verbose",verb); // Verbosity (amount of output generated) if (strcmp(argv[2], "map") == 0) { // Construct another JTree (junction tree) object that is used to calculate // the joint configuration of variables that has maximum probability (MAP state) JTree jtmap( fg, opts("updates",string("HUGIN"))("inference",string("MAXPROD")) ); // Initialize junction tree algorithm jtmap.init(); // Run junction tree algorithm jtmap.run(); // Calculate joint state of all variables that has maximum probability vector<size_t> jtmapstate = jtmap.findMaximum(); /* // Report exact MAP variable marginals cout << "Exact MAP variable marginals:" << endl; for( size_t i = 0; i < fg.nrVars(); i++ ) cout << jtmap.belief(fg.var(i)) << endl; */ // Report exact MAP joint state cerr << "Exact MAP state (log score = " << fg.logScore( jtmapstate ) << "):" << endl; cout << fg.nrVars() << endl; for( size_t i = 0; i < jtmapstate.size(); i++ ) cout << fg.var(i).label() << " " << jtmapstate[i] + 1 << endl; // +1 because in MATLAB assignments start at 1 } else if (strcmp(argv[2], "pd") == 0) { // Construct a BP (belief propagation) object from the FactorGraph fg // using the parameters specified by opts and two additional properties, // specifying the type of updates the BP algorithm should perform and // whether they should be done in the real or in the logdomain BP bp(fg, opts("updates",string("SEQMAX"))("logdomain",true)); // Initialize belief propagation algorithm bp.init(); // Run belief propagation algorithm bp.run(); // Report variable marginals for fg, calculated by the belief propagation algorithm cerr << "LBP posterior decoding (highest prob assignment in marginal):" << endl; cout << fg.nrVars() << endl; for( size_t i = 0; i < fg.nrVars(); i++ ) {// iterate over all variables in fg //cout << bp.belief(fg.var(i)) << endl; // display the belief of bp for that variable Factor marginal = bp.belief(fg.var(i)); Real maxprob = marginal.max(); for (size_t j = 0; j < marginal.nrStates(); j++) { if (marginal[j] == maxprob) { cout << fg.var(i).label() << " " << j + 1 << endl; // +1 because in MATLAB assignments start at 1 } } } } else { cerr << "Invalid inference algorithm specified." << endl; return 1; } } return 0; }
/// Main function int main( int argc, char *argv[] ) { try { // Variables for storing command line arguments size_t seed; size_t states = 2; string type; size_t d, N, K, k, j, n1, n2, n3, prime; bool periodic = false; FactorType ft; LDPCType ldpc; Real beta, sigma_w, sigma_th, mean_w, mean_th, noise; // Declare the supported options. po::options_description opts("General command line options"); opts.add_options() ("help", "produce help message") ("seed", po::value<size_t>(&seed), "random number seed (tries to read from /dev/urandom if not specified)") ("states", po::value<size_t>(&states), "number of states of each variable (default=2 for binary variables)") ; // Graph structure options po::options_description opts_graph("Options for specifying graph structure"); opts_graph.add_options() ("type", po::value<string>(&type), "factor graph type (one of 'FULL', 'DREG', 'LOOP', 'TREE', 'GRID', 'GRID3D', 'HOI', 'LDPC')") ("d", po::value<size_t>(&d), "variable connectivity (only for type=='DREG');\n\t<d><N> should be even") ("N", po::value<size_t>(&N), "number of variables (not for type=='GRID','GRID3D')") ("n1", po::value<size_t>(&n1), "width of grid (only for type=='GRID','GRID3D')") ("n2", po::value<size_t>(&n2), "height of grid (only for type=='GRID','GRID3D')") ("n3", po::value<size_t>(&n3), "length of grid (only for type=='GRID3D')") ("periodic", po::value<bool>(&periodic), "periodic grid? (only for type=='GRID','GRID3D'; default=0)") ("K", po::value<size_t>(&K), "number of factors (only for type=='HOI','LDPC')") ("k", po::value<size_t>(&k), "number of variables per factor (only for type=='HOI','LDPC')") ; // Factor options po::options_description opts_factors("Options for specifying factors"); opts_factors.add_options() ("factors", po::value<FactorType>(&ft), "factor type (one of 'EXPGAUSS','POTTS','ISING')") ("beta", po::value<Real>(&beta), "inverse temperature (ignored for factors=='ISING')") ("mean_w", po::value<Real>(&mean_w), "mean of pairwise interactions w_{ij} (only for factors=='ISING')") ("mean_th", po::value<Real>(&mean_th), "mean of unary interactions th_i (only for factors=='ISING')") ("sigma_w", po::value<Real>(&sigma_w), "stddev of pairwise interactions w_{ij} (only for factors=='ISING')") ("sigma_th", po::value<Real>(&sigma_th), "stddev of unary interactions th_i (only for factors=='ISING'") ; // LDPC options po::options_description opts_ldpc("Options for specifying LDPC code factor graphs"); opts_ldpc.add_options() ("ldpc", po::value<LDPCType>(&ldpc), "type of LDPC code (one of 'SMALL','GROUP','RANDOM')") ("j", po::value<size_t>(&j), "number of parity checks per bit (only for type=='LDPC')") ("noise", po::value<Real>(&noise), "bitflip probability for binary symmetric channel (only for type=='LDPC')") ("prime", po::value<size_t>(&prime), "prime number for construction of LDPC code (only for type=='LDPC' with ldpc='GROUP'))") ; // All options opts.add(opts_graph).add(opts_factors).add(opts_ldpc); // Parse command line arguments po::variables_map vm; po::store(po::parse_command_line(argc, argv, opts), vm); po::notify(vm); // Display help message if necessary if( vm.count("help") || !vm.count("type") ) { cout << "This program is part of libDAI - http://www.libdai.org/" << endl << endl; cout << "Usage: ./createfg [options]" << endl << endl; cout << "Creates a factor graph according to the specified options." << endl << endl; cout << endl << opts << endl; cout << "The following factor graph types with pairwise interactions can be created:" << endl; cout << "\t'FULL': fully connected graph of <N> variables" << endl; cout << "\t'DREG': random regular graph of <N> variables where each variable is connected with <d> others" << endl; cout << "\t'LOOP': a single loop of <N> variables" << endl; cout << "\t'TREE': random tree-structured (acyclic, connected) graph of <N> variables" << endl; cout << "\t'GRID': 2D grid of <n1>x<n2> variables" << endl; cout << "\t'GRID3D': 3D grid of <n1>x<n2>x<n3> variables" << endl; cout << "The following higher-order interactions factor graphs can be created:" << endl; cout << "\t'HOI': random factor graph consisting of <N> variables and <K> factors," << endl; cout << "\t each factor being an interaction of <k> variables." << endl; cout << "The following LDPC code factor graphs can be created:" << endl; cout << "\t'LDPC': simulates LDPC decoding problem, using an LDPC code of <N> bits and <K>" << endl; cout << "\t parity checks, with <k> bits per check and <j> checks per bit, transmitted" << endl; cout << "\t on a binary symmetric channel with probability <noise> of flipping a bit." << endl; cout << "\t The transmitted codeword has all bits set to zero. The argument 'ldpc'" << endl; cout << "\t determines how the LDPC code is constructed: either using a group structure," << endl; cout << "\t or randomly, or a fixed small code with (N,K,k,j) = (4,4,3,3)." << endl << endl; cout << "For all types except type=='LDPC', the factors have to be specified as well." << endl << endl; cout << "EXPGAUSS factors (the default) are created by drawing all log-factor entries" << endl; cout << "independently from a Gaussian with mean 0 and standard deviation <beta>." << endl << endl; cout << "In case of pairwise interactions, one can also choose POTTS factors, for which" << endl; cout << "the log-factors are simply delta functions multiplied by the strength <beta>." << endl << endl; cout << "For pairwise interactions and binary variables, one can also use ISING factors." << endl; cout << "Here variables x1...xN are assumed to be +1/-1--valued, and unary interactions" << endl; cout << "are of the form exp(th*xi) with th drawn from a Gaussian distribution with mean" << endl; cout << "<mean_th> and standard deviation <sigma_th>, and pairwise interactions are of the" << endl; cout << "form exp(w*xi*xj) with w drawn from a Gaussian distribution with mean <mean_w>" << endl; cout << "and standard deviation <sigma_w>." << endl; return 1; } // Set default number of states if( !vm.count("states") ) states = 2; // Set default factor type if( !vm.count("factors") ) ft = FactorType::EXPGAUSS; // Check validness of factor type if( ft == FactorType::POTTS ) if( type == HOI_TYPE ) throw "For factors=='POTTS', interactions should be pairwise (type!='HOI')"; if( ft == FactorType::ISING ) if( ((states != 2) || (type == HOI_TYPE)) ) throw "For factors=='ISING', variables should be binary (states==2) and interactions should be pairwise (type!='HOI')"; // Read random seed if( !vm.count("seed") ) { ifstream infile; bool success; infile.open( "/dev/urandom" ); success = infile.is_open(); if( success ) { infile.read( (char *)&seed, sizeof(size_t) / sizeof(char) ); success = infile.good(); infile.close(); } if( !success ) throw "Please specify random number seed."; } rnd_seed( seed ); // Set default periodicity if( !vm.count("periodic") ) periodic = false; // Store some options in a PropertySet object PropertySet options; if( vm.count("mean_th") ) options.Set("mean_th", mean_th); if( vm.count("sigma_th") ) options.Set("sigma_th", sigma_th); if( vm.count("mean_w") ) options.Set("mean_w", mean_w); if( vm.count("sigma_w") ) options.Set("sigma_w", sigma_w); if( vm.count("beta") ) options.Set("beta", beta); // Output some comments cout << "# Factor graph made by " << argv[0] << endl; cout << "# type = " << type << endl; cout << "# states = " << states << endl; // The factor graph to be constructed FactorGraph fg; #define NEED_ARG(name, desc) do { if(!vm.count(name)) throw "Please specify " desc " with --" name; } while(0); if( type == FULL_TYPE || type == DREG_TYPE || type == LOOP_TYPE || type == TREE_TYPE || type == GRID_TYPE || type == GRID3D_TYPE ) { // Pairwise interactions // Check command line options if( type == GRID_TYPE ) { NEED_ARG("n1", "width of grid"); NEED_ARG("n2", "height of grid"); N = n1 * n2; } else if( type == GRID3D_TYPE ) { NEED_ARG("n1", "width of grid"); NEED_ARG("n2", "height of grid"); NEED_ARG("n3", "depth of grid"); N = n1 * n2 * n3; } else NEED_ARG("N", "number of variables"); if( states > 2 || ft == FactorType::POTTS ) { NEED_ARG("beta", "stddev of log-factor entries"); } else { NEED_ARG("mean_w", "mean of pairwise interactions"); NEED_ARG("mean_th", "mean of unary interactions"); NEED_ARG("sigma_w", "stddev of pairwise interactions"); NEED_ARG("sigma_th", "stddev of unary interactions"); } if( type == DREG_TYPE ) NEED_ARG("d", "connectivity (number of neighboring variables of each variable)"); // Build pairwise interaction graph GraphAL G; if( type == FULL_TYPE ) G = createGraphFull( N ); else if( type == DREG_TYPE ) G = createGraphRegular( N, d ); else if( type == LOOP_TYPE ) G = createGraphLoop( N ); else if( type == TREE_TYPE ) G = createGraphTree( N ); else if( type == GRID_TYPE ) G = createGraphGrid( n1, n2, periodic ); else if( type == GRID3D_TYPE ) G = createGraphGrid3D( n1, n2, n3, periodic ); // Construct factor graph from pairwise interaction graph fg = createFG( G, ft, states, options ); // Output some additional comments if( type == GRID_TYPE || type == GRID3D_TYPE ) { cout << "# n1 = " << n1 << endl; cout << "# n2 = " << n2 << endl; if( type == GRID3D_TYPE ) cout << "# n3 = " << n3 << endl; } if( type == DREG_TYPE ) cout << "# d = " << d << endl; cout << "# options = " << options << endl; } else if( type == HOI_TYPE ) { // Higher order interactions // Check command line arguments NEED_ARG("N", "number of variables"); NEED_ARG("K", "number of factors"); NEED_ARG("k", "number of variables per factor"); NEED_ARG("beta", "stddev of log-factor entries"); // Create higher-order interactions factor graph do { fg = createHOIFG( N, K, k, beta ); } while( !fg.isConnected() ); // Output some additional comments cout << "# K = " << K << endl; cout << "# k = " << k << endl; cout << "# beta = " << beta << endl; } else if( type == LDPC_TYPE ) { // LDPC codes // Check command line arguments NEED_ARG("ldpc", "type of LDPC code"); NEED_ARG("noise", "bitflip probability for binary symmetric channel"); // Check more command line arguments (seperately for each LDPC type) if( ldpc == LDPCType::RANDOM ) { NEED_ARG("N", "number of variables"); NEED_ARG("K", "number of factors"); NEED_ARG("k", "number of variables per factor"); NEED_ARG("j", "number of parity checks per bit"); if( N * j != K * k ) throw "Parameters should satisfy N * j == K * k"; } else if( ldpc == LDPCType::GROUP ) { NEED_ARG("prime", "prime number"); NEED_ARG("k", "number of variables per factor"); NEED_ARG("j", "number of parity checks per bit"); if( !isPrime(prime) ) throw "Parameter <prime> should be prime"; if( !((prime-1) % j == 0 ) ) throw "Parameters should satisfy (prime-1) % j == 0"; if( !((prime-1) % k == 0 ) ) throw "Parameters should satisfy (prime-1) % k == 0"; N = prime * k; K = prime * j; } else if( ldpc == LDPCType::SMALL ) { N = 4; K = 4; j = 3; k = 3; } // Output some additional comments cout << "# N = " << N << endl; cout << "# K = " << K << endl; cout << "# j = " << j << endl; cout << "# k = " << k << endl; if( ldpc == LDPCType::GROUP ) cout << "# prime = " << prime << endl; cout << "# noise = " << noise << endl; // Construct likelihood and paritycheck factors Real likelihood[4] = {1.0 - noise, noise, noise, 1.0 - noise}; Real *paritycheck = new Real[1 << k]; createParityCheck(paritycheck, k, 0.0); // Create LDPC structure BipartiteGraph ldpcG; bool regular; do { if( ldpc == LDPCType::GROUP ) ldpcG = createGroupStructuredLDPCGraph( prime, j, k ); else if( ldpc == LDPCType::RANDOM ) ldpcG = createRandomBipartiteGraph( N, K, j, k ); else if( ldpc == LDPCType::SMALL ) ldpcG = createSmallLDPCGraph(); regular = true; for( size_t i = 0; i < N; i++ ) if( ldpcG.nb1(i).size() != j ) regular = false; for( size_t I = 0; I < K; I++ ) if( ldpcG.nb2(I).size() != k ) regular = false; } while( !regular && !ldpcG.isConnected() ); // Convert to FactorGraph vector<Factor> factors; for( size_t I = 0; I < K; I++ ) { VarSet vs; for( size_t _i = 0; _i < k; _i++ ) { size_t i = ldpcG.nb2(I)[_i]; vs |= Var( i, 2 ); } factors.push_back( Factor( vs, paritycheck ) ); } delete paritycheck; // Generate noise vector vector<char> noisebits(N,0); size_t bitflips = 0; for( size_t i = 0; i < N; i++ ) { if( rnd_uniform() < noise ) { noisebits[i] = 1; bitflips++; } } cout << "# bitflips = " << bitflips << endl; // Simulate transmission of all-zero codeword vector<char> input(N,0); vector<char> output(N,0); for( size_t i = 0; i < N; i++ ) output[i] = (input[i] + noisebits[i]) & 1; // Add likelihoods for( size_t i = 0; i < N; i++ ) factors.push_back( Factor(Var(i,2), likelihood + output[i]*2) ); // Construct Factor Graph fg = FactorGraph( factors ); } else throw "Invalid type"; // Output additional comments cout << "# N = " << fg.nrVars() << endl; cout << "# seed = " << seed << endl; // Output factor graph cout << fg; } catch( const char *e ) { /// Display error message cerr << "Error: " << e << endl; return 1; } return 0; }
void RegionGraph::constructCVM( const FactorGraph &fg, const std::vector<VarSet> &cl, size_t verbose ) { if( verbose ) cerr << "constructCVM called (" << fg.nrVars() << " vars, " << fg.nrFactors() << " facs, " << cl.size() << " clusters)" << endl; // Retain only maximal clusters if( verbose ) cerr << " Constructing ClusterGraph" << endl; ClusterGraph cg( cl ); if( verbose ) cerr << " Erasing non-maximal clusters" << endl; cg.eraseNonMaximal(); // Create inner regions - first pass if( verbose ) cerr << " Creating inner regions (first pass)" << endl; set<VarSet> betas; for( size_t alpha = 0; alpha < cg.nrClusters(); alpha++ ) for( size_t alpha2 = alpha; (++alpha2) != cg.nrClusters(); ) { VarSet intersection = cg.cluster(alpha) & cg.cluster(alpha2); if( intersection.size() > 0 ) betas.insert( intersection ); } // Create inner regions - subsequent passes if( verbose ) cerr << " Creating inner regions (next passes)" << endl; set<VarSet> new_betas; do { new_betas.clear(); for( set<VarSet>::const_iterator gamma = betas.begin(); gamma != betas.end(); gamma++ ) for( set<VarSet>::const_iterator gamma2 = gamma; (++gamma2) != betas.end(); ) { VarSet intersection = (*gamma) & (*gamma2); if( (intersection.size() > 0) && (betas.count(intersection) == 0) ) new_betas.insert( intersection ); } betas.insert(new_betas.begin(), new_betas.end()); } while( new_betas.size() ); // Create inner regions - final phase if( verbose ) cerr << " Creating inner regions (final phase)" << endl; vector<Region> irs; irs.reserve( betas.size() ); for( set<VarSet>::const_iterator beta = betas.begin(); beta != betas.end(); beta++ ) irs.push_back( Region(*beta,0.0) ); // Create edges if( verbose ) cerr << " Creating edges" << endl; vector<pair<size_t,size_t> > edges; for( size_t beta = 0; beta < irs.size(); beta++ ) for( size_t alpha = 0; alpha < cg.nrClusters(); alpha++ ) if( cg.cluster(alpha) >> irs[beta] ) edges.push_back( pair<size_t,size_t>(alpha,beta) ); // Construct region graph if( verbose ) cerr << " Constructing region graph" << endl; construct( fg, cg.clusters(), irs, edges ); // Calculate counting numbers if( verbose ) cerr << " Calculating counting numbers" << endl; calcCVMCountingNumbers(); if( verbose ) cerr << "Done." << endl; }
int main( int argc, char *argv[] ) { if( argc != 3 ) { cout << "Usage: " << argv[0] << " <in.fg> <tw>" << endl << endl; cout << "Reports some characteristics of the .fg network." << endl; cout << "Also calculates treewidth (which may take some time) unless <tw> == 0." << endl; return 1; } else { // Read factorgraph FactorGraph fg; char *infile = argv[1]; int calc_tw = atoi(argv[2]); fg.ReadFromFile( infile ); cout << "Number of variables: " << fg.nrVars() << endl; cout << "Number of factors: " << fg.nrFactors() << endl; cout << "Connected: " << fg.isConnected() << endl; cout << "Tree: " << fg.isTree() << endl; cout << "Has short loops: " << hasShortLoops(fg.factors()) << endl; cout << "Has negatives: " << hasNegatives(fg.factors()) << endl; cout << "Binary variables? " << fg.isBinary() << endl; cout << "Pairwise interactions? " << fg.isPairwise() << endl; if( calc_tw ) { std::pair<size_t,size_t> tw = treewidth(fg); cout << "Treewidth: " << tw.first << endl; cout << "Largest cluster for JTree has " << tw.second << " states " << endl; } double stsp = 1.0; for( size_t i = 0; i < fg.nrVars(); i++ ) stsp *= fg.var(i).states(); cout << "Total state space: " << stsp << endl; double cavsum_lcbp = 0.0; double cavsum_lcbp2 = 0.0; size_t max_Delta_size = 0; map<size_t,size_t> cavsizes; for( size_t i = 0; i < fg.nrVars(); i++ ) { VarSet di = fg.delta(i); if( cavsizes.count(di.size()) ) cavsizes[di.size()]++; else cavsizes[di.size()] = 1; size_t Ds = fg.Delta(i).nrStates(); if( Ds > max_Delta_size ) max_Delta_size = Ds; cavsum_lcbp += di.nrStates(); for( VarSet::const_iterator j = di.begin(); j != di.end(); j++ ) cavsum_lcbp2 += j->states(); } cout << "Maximum pancake has " << max_Delta_size << " states" << endl; cout << "LCBP with full cavities needs " << cavsum_lcbp << " BP runs" << endl; cout << "LCBP with only pairinteractions needs " << cavsum_lcbp2 << " BP runs" << endl; cout << "Cavity sizes: "; for( map<size_t,size_t>::const_iterator it = cavsizes.begin(); it != cavsizes.end(); it++ ) cout << it->first << "(" << it->second << ") "; cout << endl; cout << "Type: " << (fg.isPairwise() ? "pairwise" : "higher order") << " interactions, " << (fg.isBinary() ? "binary" : "nonbinary") << " variables" << endl; if( fg.isPairwise() ) { bool girth_reached = false; size_t loopdepth; for( loopdepth = 2; loopdepth <= fg.nrVars() && !girth_reached; loopdepth++ ) { size_t nr_loops = countLoops( fg, loopdepth ); cout << "Loops up to " << loopdepth << " variables: " << nr_loops << endl; if( nr_loops > 0 ) girth_reached = true; } if( girth_reached ) cout << "Girth: " << loopdepth-1 << endl; else cout << "Girth: infinity" << endl; } return 0; } }