/** \param N1 = number of nodes of type 1
 *  \param d1 = size of neighborhoods of nodes of type 1
 *  \param N2 = number of nodes of type 2
 *  \param d2 = size of neighborhoods of nodes of type 2
 *  \note asserts that N1 * d1 == N2 * d2
 */
BipartiteGraph createRandomBipartiteGraph( size_t N1, size_t N2, size_t d1, size_t d2 ) {
    BipartiteGraph G;

    DAI_ASSERT( N1 * d1 == N2 * d2 );

    // build lists of degree-repeated vertex numbers
    std::vector<size_t> stubs1( N1*d1, 0 );
    for( size_t n1 = 0; n1 < N1; n1++ )
        for( size_t t = 0; t < d1; t++ )
            stubs1[n1*d1 + t] = n1;

    // build lists of degree-repeated vertex numbers
    std::vector<size_t> stubs2( N2*d2, 0 );
    for( size_t n2 = 0; n2 < N2; n2++ )
        for( size_t t = 0; t < d2; t++ )
            stubs2[n2*d2 + t] = n2;

    // shuffle lists
    random_shuffle( stubs1.begin(), stubs1.end() );
    random_shuffle( stubs2.begin(), stubs2.end() );

    // add edges
    vector<BipartiteGraph::Edge> edges;
    edges.reserve( N1*d1 );
    for( size_t e = 0; e < N1*d1; e++ )
        edges.push_back( BipartiteGraph::Edge(stubs1[e], stubs2[e]) );

    // finish construction
    G.construct( N1, N2, edges.begin(), edges.end() );

    return G;
}
Example #2
0
// N = number of variables
// n = size of variable neighborhoods
// K = number of factors
// k = size of factor neighborhoods
// asserts: N * n == K * k
BipartiteGraph CreateRandomBipartiteGraph( size_t N, size_t K, size_t n, size_t k ) {
    BipartiteGraph G;

    DAI_ASSERT( N * n == K * k );

    // build lists of degree-repeated vertex numbers
    std::vector<size_t> stubs1(N*n,0);
    for( size_t i = 0; i < N; i++ )
        for( size_t t = 0; t < n; t++ )
            stubs1[i*n + t] = i;

    // build lists of degree-repeated vertex numbers
    std::vector<size_t> stubs2(K*k,0);
    for( size_t I = 0; I < K; I++ )
        for( size_t t = 0; t < k; t++ )
            stubs2[I*k + t] = I;

    // shuffle lists
    random_shuffle( stubs1.begin(), stubs1.end() );
    random_shuffle( stubs2.begin(), stubs2.end() );

    // add edges
    vector<BipartiteGraph::Edge> edges;
    edges.reserve( N*n );
    for( size_t e = 0; e < N*n; e++ )
        edges.push_back( BipartiteGraph::Edge(stubs1[e], stubs2[e]) );

    // finish construction
    G.construct( N, K, edges.begin(), edges.end() );

    return G;
}
Example #3
0
    void checkAddEdge(unsigned numOfVertices, Edge toBeAdded, Edges existing, Edges missing)
    {
        g.addEdge(toBeAdded);

        ASSERT_EQ(existing.size(), g.numOfEdges());
        ASSERT_EQ(numOfVertices, g.numOfVertices());
        for (auto elem : existing) ASSERT_TRUE(g.edgeExists(elem));
        for (auto elem : missing) ASSERT_FALSE(g.edgeExists(elem));
    }
/// Constructs a regular LDPC graph with N=6, j=2, K=4, k=3
BipartiteGraph createSmallLDPCGraph() {
    BipartiteGraph G;
    size_t N=4, j=3, K=4; // k=3;

    typedef BipartiteGraph::Edge Edge;
    vector<Edge> edges;
    edges.reserve( N*j );
    edges.push_back( Edge(0,0) ); edges.push_back( Edge(1,0) ); edges.push_back( Edge(2,0) );
    edges.push_back( Edge(0,1) ); edges.push_back( Edge(1,1) ); edges.push_back( Edge(3,1) );
    edges.push_back( Edge(0,2) ); edges.push_back( Edge(2,2) ); edges.push_back( Edge(3,2) );
    edges.push_back( Edge(1,3) ); edges.push_back( Edge(2,3) ); edges.push_back( Edge(3,3) );

    // finish construction
    G.construct( N, K, edges.begin(), edges.end() );

    return G;
}
void
PlotGraph::PlotAugmentingPath(BipartiteGraph& _bg, vector<EID>& _path){

    //get assignment size, assume the sizes of agents and tasks are identical
    size_t as_size = _bg.GetNumAgents();
    double plx[as_size];
    double ply[as_size];
/*
    //gnuplot_resetplot(g);
    gnuplot_cmd(g, (char*)"unset label");
    gnuplot_cmd(g, (char*)"set xrange [-0.25:1.25]");
    gnuplot_cmd(g, (char*)"set yrange [-0.25:%f]", as_size-1+.25);
    gnuplot_cmd(g, (char*)"set xtics 0");
    gnuplot_cmd(g, (char*)"set ytics 0");
    gnuplot_cmd(g, (char*)"set nokey");
*/
    //gnuplot_cmd(g, (char*)"set style line 2 lt 2 lc rgb \"blue\" lw 3");
    // Plot matching
    //cout<<endl<<"Set M: "<<endl;
    //DisplayData(_M);    
    bool alter = true;
    for (unsigned int i = 0; i < _path.size(); i++){
        plx[0] = _path[i].first;
        ply[0] = 0.0;
        plx[1] = _path[i].second;
        ply[1] = 1.0;

        //gnuplot_setstyle(g, (char*)"linespoints lc rgb \"#55DD99\" lw 3");
        if(alter)
          gnuplot_setstyle(g, (char*)"lines lc rgb \"#458B74\" lw 3");
        else
          gnuplot_setstyle(g, (char*)"lines lc rgb \"#7CCD7C\" lw 3");

        alter = !alter;
        gnuplot_plot_xy(g, plx, ply, 2, NULL);
    }

#ifdef SAVE_PLOTS
    stringstream ss;
    ss << setw(3) << setfill('0') << Cnt++;
    string postfix = ss.str();

    string name="save/plot"+postfix+".jpeg";
    gnuplot_cmd(g, (char*)"set terminal jpeg");
    //gnuplot_cmd(g, (char*)"set terminal jpeg small size 320,240");//bad
    gnuplot_cmd(g, (char*)"set output \"%s\"", name.c_str());
    printf("saved jpeg: \"%s\"\n", name.c_str());
#endif

    gnuplot_cmd(g, (char*)"replot");

   sleep(period);
}
Example #6
0
 void verifyMatching(BipartiteGraph g, unsigned expectedSize)
 {
     Matching matching = findMaximumMatching(g);
     typedef boost::unordered_set<unsigned> VertexSet;
     VertexSet first;
     VertexSet second;
     for (auto elem : matching)
     {
         ASSERT_TRUE(first.insert(elem.first).second);
         ASSERT_TRUE(second.insert(elem.second).second);
         ASSERT_TRUE(g.edgeExists(elem));
     }
     ASSERT_EQ(expectedSize, matching.size());
 }
/** Use construction described in "A Class of Group-Structured LDPC Codes"
 *  by R. M. Tanner, D. Sridhara and T. Fuja
 *  Proceedings of ICSTA, 2001
 *
 *  Example parameters: (p,j,k) = (31,3,5)
 *                      (p,j,k) = (37,3,4)
 *                      (p,j,k) = (7,2,4)
 *                      (p,j,k) = (29,2,4)
 *
 *  j and k must be divisors of p-1
 */
BipartiteGraph createGroupStructuredLDPCGraph( size_t p, size_t j, size_t k ) {
    BipartiteGraph G;

    size_t n = j;
    size_t N = p * k;
    size_t K = p * j;

    size_t a, b;
    for( a = 2; a < p; a++ )
        if( order(a,p) == k )
            break;
    DAI_ASSERT( a != p );
    for( b = 2; b < p; b++ )
        if( order(b,p) == j )
            break;
    DAI_ASSERT( b != p );
    // cout << "# order(a=" << a << ") = " << order(a,p) << endl;
    // cout << "# order(b=" << b << ") = " << order(b,p) << endl;

    DAI_ASSERT( N * n == K * k );

    typedef BipartiteGraph::Edge Edge;
    vector<Edge> edges;
    edges.reserve( N * n );

    for( size_t s = 0; s < j; s++ )
        for( size_t t = 0; t < k; t++ ) {
            size_t P = (powmod(b,s,p) * powmod(a,t,p)) % p;
            for( size_t m = 0; m < p; m++ )
                edges.push_back( Edge(t*p + m, s*p + ((m + P) % p)) );
        }

    // finish construction
    G.construct( N, K, edges.begin(), edges.end() );

    return G;
}
void 
PlotGraph::PlotBipartiteGraph(BipartiteGraph& _bg,
			      vector<VID>& _S, 
			      vector<VID>& _T,
			      vector<VID>& _N,
			      vector<EID>& _EG,
			      vector<EID>& _M, 
			      int target_task){

    //get assignment size, assume the sizes of agents and tasks are identical
    size_t as_size = _bg.GetNumAgents();
    double plx[as_size];
    double ply[as_size];

    //g=gnuplot_init();
    gnuplot_resetplot(g);
    gnuplot_cmd(g, (char*)"unset label");
    gnuplot_cmd(g, (char*)"set xrange [-0.25:%f]", as_size-1+.25);
    gnuplot_cmd(g, (char*)"set yrange [-0.25:1.25]");
    gnuplot_cmd(g, (char*)"set xtics 0");
    gnuplot_cmd(g, (char*)"set ytics 0");
    gnuplot_cmd(g, (char*)"set nokey");

    // Plot matching
    //cout<<endl<<"Set M: "<<endl;
    //DisplayData(_M);    
    for (unsigned int i = 0; i < _M.size(); i++){
        plx[0] = _M[i].first;
        ply[0] = 0.0;
        plx[1] = _M[i].second;
        ply[1] = 1.0;

        gnuplot_setstyle(g, (char*)"lines lc rgb \"red\" lw 3");
        gnuplot_plot_xy(g, plx, ply, 2, NULL);
    }

    // Plot admissible edges (EG)
    //cout<<"EG: "<<endl;
    //DisplayData(_EG);
    for(unsigned int i=0; i<_EG.size(); i++){
        plx[0] = _EG[i].first;
        ply[0] = 0.0;
        plx[1] = _EG[i].second;
        ply[1] = 1.0;

        gnuplot_setstyle(g, (char*)"lines lc rgb \"gray\"");
        gnuplot_plot_xy(g, plx, ply, 2, NULL);
                
        plx[0] = (0.9*plx[0] + 0.1*plx[1]);
        ply[0] = 0.11;
        gnuplot_setstyle(g, (char*)"points pointsize 2 lc rgb \"#FFFFFF\" pt 7");
        gnuplot_plot_xy(g, plx, ply, 1, NULL);

        //cout<<"EG "<<i<<": "<<_bg.GetMatrix(_EG[i])->GetWeight()<<endl;
        gnuplot_cmd(g, (char*)"set label \"%d\" at %f-0.04,0.1 front tc rgb \"#4682B4\" font \",8\"", int(_bg.GetMatrix(_EG[i])->GetWeight()), plx[0]);
    }


    // Plot membership of set S
    //cout<<"S: "<<endl;
    //DisplayData(_S);
    for(unsigned int i=0; i<_S.size(); i++){
        plx[0] = _S[i];
        ply[0] = 0.0;
        gnuplot_setstyle(g, (char*)"points pointsize 3 lc rgb \"green\" pt 7");
        gnuplot_plot_xy(g, plx, ply, 1, NULL);
    }

    // Plot membership of the set T
    //cout<<"T: "<<endl;
    //DisplayData(_T);
    for(unsigned int i=0; i<_T.size(); i++){
        plx[0] = _T[i];
        ply[0] = 1.0;
        gnuplot_setstyle(g, (char*)"points pointsize 3 lc rgb \"#00BFFF\" pt 7");
        gnuplot_plot_xy(g, plx, ply, 1, NULL);
    }

        if (target_task != -1) // not yet unioned, but the reversal point for the 
        {                         // alternating path
            plx[0] = target_task;
            ply[0] = 1.0;
            gnuplot_setstyle(g, (char*)"points pointsize 3 lc rgb \"grey\" pt 7");
            gnuplot_plot_xy(g, plx, ply, 1, NULL);
        }


    // Plot nodes
    for(unsigned int i = 0; i < as_size; i++)
    {
        plx[i] = i;
        ply[i] = 0.0;
    }

    gnuplot_setstyle(g, (char*)"points pointsize 2 lc rgb \"#102063\" pt 7");
    gnuplot_plot_xy(g, plx, ply, as_size, NULL);

    for(unsigned int i = 0; i < as_size; i++)
    {
        plx[i] = i;
        ply[i] = 1.0;
    }

    gnuplot_setstyle(g, (char*)"points pointsize 2 lc rgb \"#102063\" pt 7");
    gnuplot_plot_xy(g, plx, ply, as_size, NULL);

    for (unsigned int i = 0; i < as_size; i++)
    {
        gnuplot_cmd(g, (char*)"set label \"x%d\" at %d-0.025,-0.08 tc rgb \"black\"", i, i);
        gnuplot_cmd(g, (char*)"set label \"y%d\" at %d-0.025,1.08 tc rgb \"black\"", i, i);
	//cout<<"Label "<<i<<": "<<_bg.GetAgent(i)->GetLabel()<<endl;
	//cout<<"Label "<<i<<": "<<_bg.GetTask(i)->GetLabel()<<endl;
        gnuplot_cmd(g, (char*)"set label \"%d\" at %d-0.025,-0.15 tc rgb \"#112244\"", int(_bg.GetAgent(i)->GetLabel()), i);
        gnuplot_cmd(g, (char*)"set label \"%d\" at %d-0.025,1.15 tc rgb \"#112244\"", int(_bg.GetTask(i)->GetLabel()), i);
    }

/*    //image setting
       set terminal png 
              {{no}transparent} {{no}interlace}
              {tiny | small | medium | large | giant}
              {font <face> {<pointsize>}}
              {size <x>,<y>} {{no}crop}
              {{no}enhanced}
              {<color0> <color1> <color2> ...}
*/

#ifdef SAVE_PLOTS
    stringstream ss;
    ss << setw(3) << setfill('0') << Cnt++;
    string postfix = ss.str();

    string name="save/plot"+postfix+".jpeg";
    gnuplot_cmd(g, (char*)"set terminal jpeg");
    //gnuplot_cmd(g, (char*)"set terminal jpeg small size 320,240");//bad
    gnuplot_cmd(g, (char*)"set output \"%s\"", name.c_str());
    printf("saved jpeg: \"%s\"\n", name.c_str());
#endif

    gnuplot_cmd(g, (char*)"replot");

    sleep(period);
    //gnuplot_close(g);
}
/// 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;
}
Example #10
0
 void checkMatching(unsigned matchingSize, Edges edgesToAdd)
 {
     for (auto edge : edgesToAdd) g.addEdge(edge);
     verifyMatching(g, matchingSize);
 }
Example #11
0
int main( int argc, char *argv[] ) {
    try {
        size_t N, K, k, d, j, n1, n2, n3;
        size_t prime;
        size_t seed;
        Real beta, sigma_w, sigma_th, noise, mean_w, mean_th;
        string type;
        size_t states = 2;

        // Declare the supported options.
        po::options_description desc("Allowed options");
        desc.add_options()
            ("help",     "produce help message")
            ("type",     po::value<string>(&type),     "factor graph type:\n\t'full', 'grid', 'grid_torus', 'dreg', 'loop', 'tree', 'hoi', 'ldpc_random', 'ldpc_group', 'ldpc_small', 'potts3d'")
            ("seed",     po::value<size_t>(&seed),     "random number seed (tries to read from /dev/urandom if not specified)")
            ("N",        po::value<size_t>(&N),        "number of variables (not for type=='ldpc_small')")
            ("n1",       po::value<size_t>(&n1),       "width of 3D grid (only for type=='potts3d')")
            ("n2",       po::value<size_t>(&n2),       "height of 3D grid (only for type=='potts3d')")
            ("n3",       po::value<size_t>(&n3),       "length of 3D grid (only for type=='potts3d')")
            ("K",        po::value<size_t>(&K),        "number of factors\n\t(only for type=='hoi' and 'type=='ldpc_{random,group}')")
            ("k",        po::value<size_t>(&k),        "number of variables per factor\n\t(only for type=='hoi' and type=='ldpc_{random,group}')")
            ("d",        po::value<size_t>(&d),        "variable connectivity\n\t(only for type=='dreg')")
            ("j",        po::value<size_t>(&j),        "number of parity checks per bit\n\t(only for type=='ldpc_{random,group}')")
            ("prime",    po::value<size_t>(&prime),    "prime number for construction of LDPC code\n\t(only for type=='ldpc_group')")
            ("beta",     po::value<Real>(&beta),       "stddev of log-factor entries\n\t(only for type=='hoi', 'potts3d', 'grid' if states>2)")
            ("mean_w",   po::value<Real>(&mean_w),     "mean of pairwise interactions w_{ij}\n\t(not for type=='hoi', 'ldpc_*', 'potts3d')")
            ("mean_th",  po::value<Real>(&mean_th),    "mean of singleton interactions th_i\n\t(not for type=='hoi', 'ldpc_*', 'potts3d')")
            ("sigma_w",  po::value<Real>(&sigma_w),    "stddev of pairwise interactions w_{ij}\n\t(not for type=='hoi', 'ldpc_*', 'potts3d')")
            ("sigma_th", po::value<Real>(&sigma_th),   "stddev of singleton interactions th_i\n\t(not for type=='hoi', 'ldpc_*', 'potts3d'")
            ("noise",    po::value<Real>(&noise),      "bitflip probability for binary symmetric channel (only for type=='ldpc')")
            ("states",   po::value<size_t>(&states),   "number of states of each variable (should be 2 for all but type=='grid', 'grid_torus', 'loop', 'potts3d')")
        ;

        po::variables_map vm;
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);

        if( vm.count("help") || !vm.count("type") ) {
            if( vm.count("type") ) {
                if( type == FULL_TYPE ) {
                    cout << "Creates fully connected pairwise graphical model of <N> binary variables;" << endl;
                } else if( type == GRID_TYPE ) {
                    cout << "Creates (non-periodic) 2D Ising grid of (approx.) <N> variables (which need not be binary);" << endl;
                } else if( type == GRID_TORUS_TYPE ) {
                    cout << "Creates periodic 2D Ising grid of (approx.) <N> variables (which need not be binary);" << endl;
                } else if( type == DREG_TYPE ) {
                    cout << "Creates random d-regular graph of <N> binary variables with uniform degree <d>" << endl;
                    cout << "(where <d><N> should be even);" << endl;
                } else if( type == LOOP_TYPE ) {
                    cout << "Creates a pairwise graphical model consisting of a single loop of" << endl;
                    cout << "<N> variables (which need not be binary);" << endl;
                } else if( type == TREE_TYPE ) {
                    cout << "Creates a pairwise, connected graphical model without cycles (i.e., a tree)" << endl;
                    cout << "of <N> binary variables;" << endl;
                } else if( type == HOI_TYPE ) {
                    cout << "Creates a random factor graph of <N> binary variables and" << endl;
                    cout << "<K> factors, each factor being an interaction of <k> variables." << endl;
                    cout << "The entries of the factors are exponentials of i.i.d. Gaussian" << endl;
                    cout << "variables with mean 0 and standard deviation <beta>." << endl;
                } else if( type == LDPC_RANDOM_TYPE ) {
                    cout << "Simulates LDPC decoding problem, using a LDPC code of <N> bits and <K> parity" << endl;
                    cout << "checks, with <k> bits per check and <j> checks per bit, transmitted on a binary" << endl;
                    cout << "symmetric channel with probability <noise> of flipping a bit. The transmitted" << endl;
                    cout << "codeword has all bits set to zero. The LDPC code is randomly generated." << endl;
                } else if( type == LDPC_GROUP_TYPE ) {
                    cout << "Simulates LDPC decoding problem, using a LDPC code of <N> bits and <K> parity" << endl;
                    cout << "checks, with <k> bits per check and <j> checks per bit, transmitted on a binary" << endl;
                    cout << "symmetric channel with probability <noise> of flipping a bit. The transmitted" << endl;
                    cout << "codeword has all bits set to zero. The LDPC code is constructed (using group" << endl;
                    cout << "theory) using a parameter <prime>; <j> and <k> should both be divisors of <prime>-1." << endl;
                } else if( type == LDPC_SMALL_TYPE ) {
                    cout << "Simulates LDPC decoding problem, using a LDPC code of 4 bits and 4 parity" << endl;
                    cout << "checks, with 3 bits per check and 3 checks per bit, transmitted on a binary" << endl;
                    cout << "symmetric channel with probability <noise> of flipping a bit. The transmitted" << endl;
                    cout << "codeword has all bits set to zero. The LDPC code is fixed." << endl;
                } else if( type == POTTS3D_TYPE ) {
                    cout << "Builds 3D Potts model of size <n1>x<n2>x<n3> with nearest-neighbour Potts" << endl;
                    cout << "interactions with <states> states and inverse temperature <beta>." << endl;
                } else
                    cerr << "Unknown type (should be one of 'full', 'grid', 'grid_torus', 'dreg', 'loop', 'tree', 'hoi', 'ldpc_random', 'ldpc_group', 'ldpc_small', 'potts3d')" << endl;

                if( type == FULL_TYPE || type == GRID_TYPE || type == GRID_TORUS_TYPE || type == DREG_TYPE || type == LOOP_TYPE || type == TREE_TYPE ) {
                    if( type == GRID_TYPE || type == GRID_TORUS_TYPE || type == LOOP_TYPE ) {
                        cout << "if <states> > 2: factor entries are exponents of Gaussians with mean 0 and standard deviation beta; otherwise," << endl;
                    }
                    cout << "singleton interactions are Gaussian with mean <mean_th> and standard" << endl;
                    cout << "deviation <sigma_th>; pairwise interactions are Gaussian with mean" << endl;
                    cout << "<mean_w> and standard deviation <sigma_w>." << endl;
                }
            }
            cout << endl << desc << endl;
            return 1;
        }

        if( !vm.count("states") )
            states = 2;

        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 );

        FactorGraph fg;

        cout << "# Factor graph made by " << argv[0] << endl;
        cout << "# type = " << type << endl;

        if( type == FULL_TYPE ) {
            if( !vm.count("N") || !vm.count("mean_w") || !vm.count("mean_th") || !vm.count("sigma_w") || !vm.count("sigma_th") )
                throw "Please specify all required arguments";
            MakeFullFG( N, mean_w, mean_th, sigma_w, sigma_th, fg );

            cout << "# N = " << N << endl;
            cout << "# mean_w = " << mean_w << endl;
            cout << "# mean_th = " << mean_th << endl;
            cout << "# sigma_w = " << sigma_w << endl;
            cout << "# sigma_th = " << sigma_th << endl;
        } else if( type == GRID_TYPE || type == GRID_TORUS_TYPE ) {
#define NEED_ARG(name, desc) do { if(!vm.count(name)) throw "Please specify " desc " with --" name; } while(0);
            if( states > 2 ) {
                NEED_ARG("N", "number of nodes");
                NEED_ARG("beta", "stddev of log-factor entries");
            } else {
                NEED_ARG("N", "number of nodes");
                NEED_ARG("mean_w", "mean of pairwise interactions");
                NEED_ARG("mean_th", "mean of singleton interactions");
                NEED_ARG("sigma_w", "stddev of pairwise interactions");
                NEED_ARG("sigma_th", "stddev of singleton interactions");
            }

            size_t n = (size_t)sqrt((long double)N);
            N = n * n;

            bool periodic = false;
            if( type == GRID_TYPE )
                periodic = false;
            else
                periodic = true;

            if( states > 2 )
                MakeGridNonbinaryFG( periodic, n, states, beta, fg );
            else
                MakeGridFG( periodic, n, mean_w, mean_th, sigma_w, sigma_th, fg );

            cout << "# n = " << n << endl;
            cout << "# N = " << N << endl;

            if( states > 2 )
                cout << "# beta = " << beta << endl;
            else {
                cout << "# mean_w = " << mean_w << endl;
                cout << "# mean_th = " << mean_th << endl;
                cout << "# sigma_w = " << sigma_w << endl;
                cout << "# sigma_th = " << sigma_th << endl;
            }
        } else if( type == DREG_TYPE ) {
            if( !vm.count("N") || !vm.count("mean_w") || !vm.count("mean_th") || !vm.count("sigma_w") || !vm.count("sigma_th") || !vm.count("d") )
                throw "Please specify all required arguments";

            MakeDRegFG( N, d, mean_w, mean_th, sigma_w, sigma_th, fg );

            cout << "# N = " << N << endl;
            cout << "# d = " << d << endl;
            cout << "# mean_w = " << mean_w << endl;
            cout << "# mean_th = " << mean_th << endl;
            cout << "# sigma_w = " << sigma_w << endl;
            cout << "# sigma_th = " << sigma_th << endl;
        } else if( type == LOOP_TYPE ) {
            if( states > 2 ) {
                if( !vm.count("N") || !vm.count("beta") )
                    throw "Please specify all required arguments";
            } else {
                if( !vm.count("N") || !vm.count("mean_w") || !vm.count("mean_th") || !vm.count("sigma_w") || !vm.count("sigma_th") )
                    throw "Please specify all required arguments";
            }
            if( states > 2 )
                MakeLoopNonbinaryFG( N, states, beta, fg );
            else
                MakeLoopFG( N, mean_w, mean_th, sigma_w, sigma_th, fg );

            cout << "# N = " << N << endl;

            if( states > 2 )
                cout << "# beta = " << beta << endl;
            else {
                cout << "# mean_w = " << mean_w << endl;
                cout << "# mean_th = " << mean_th << endl;
                cout << "# sigma_w = " << sigma_w << endl;
                cout << "# sigma_th = " << sigma_th << endl;
            }
        } else if( type == TREE_TYPE ) {
            if( !vm.count("N") || !vm.count("mean_w") || !vm.count("mean_th") || !vm.count("sigma_w") || !vm.count("sigma_th") )
                throw "Please specify all required arguments";
            MakeTreeFG( N, mean_w, mean_th, sigma_w, sigma_th, fg );

            cout << "# N = " << N << endl;
            cout << "# mean_w = " << mean_w << endl;
            cout << "# mean_th = " << mean_th << endl;
            cout << "# sigma_w = " << sigma_w << endl;
            cout << "# sigma_th = " << sigma_th << endl;
        } else if( type == HOI_TYPE ) {
            if( !vm.count("N") || !vm.count("K") || !vm.count("k") || !vm.count("beta") )
                throw "Please specify all required arguments";
            do {
                MakeHOIFG( N, K, k, beta, fg );
            } while( !fg.isConnected() );

            cout << "# N = " << N << endl;
            cout << "# K = " << K << endl;
            cout << "# k = " << k << endl;
            cout << "# beta = " << beta << endl;
        } else if( type == LDPC_RANDOM_TYPE || type == LDPC_GROUP_TYPE || type == LDPC_SMALL_TYPE ) {
            if( !vm.count("noise") )
                throw "Please specify all required arguments";

            if( type == LDPC_RANDOM_TYPE ) {
                if( !vm.count("N") || !vm.count("K") || !vm.count("j") || !vm.count("k") )
                    throw "Please specify all required arguments";

                if( N * j != K * k )
                    throw "Parameters should satisfy N * j == K * k";
            } else if( type == LDPC_GROUP_TYPE ) {
                if( !vm.count("prime") || !vm.count("j") || !vm.count("k") )
                    throw "Please specify all required arguments";

                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( type == LDPC_SMALL_TYPE ) {
                N = 4;
                K = 4;
                j = 3;
                k = 3;
            }

            cout << "# N = " << N << endl;
            cout << "# K = " << K << endl;
            cout << "# j = " << j << endl;
            cout << "# k = " << k << endl;
            if( type == LDPC_GROUP_TYPE )
                cout << "# prime = " << prime << endl;
            cout << "# noise = " << noise << endl;

            // p = 31, j = 3, k = 5
            // p = 37, j = 3, k = 4
            // p = 7 , j = 2, k = 3
            // p = 29, j = 2, k = 4

            // Construct likelihood and paritycheck factors
            Real likelihood[4] = {1.0 - noise, noise, noise, 1.0 - noise};
            Real *paritycheck = new Real[1 << k];
            MakeParityCheck(paritycheck, k, 0.0);

            // Create LDPC structure
            BipartiteGraph ldpcG;
            bool regular;
            do {
                if( type == LDPC_GROUP_TYPE )
                    ldpcG = CreateGroupStructuredLDPCGraph( prime, j, k );
                else if( type == LDPC_RANDOM_TYPE )
                    ldpcG = CreateRandomBipartiteGraph( N, K, j, k );
                else if( type == LDPC_SMALL_TYPE )
                    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 if( type == POTTS3D_TYPE ) {
            if( !vm.count("n1") || !vm.count("n2") || !vm.count("n3") || !vm.count("beta") || !vm.count("states") )
                throw "Please specify all required arguments";
            Make3DPotts( n1, n2, n3, states, beta, fg );

            cout << "# N = " << n1*n2*n3 << endl;
            cout << "# n1 = " << n1 << endl;
            cout << "# n2 = " << n2 << endl;
            cout << "# n3 = " << n3 << endl;
            cout << "# beta = " << beta << endl;
            cout << "# states = " << states << endl;
        } else {
            throw "Invalid type";
        }

        cout << "# seed = " << seed << endl;
        cout << fg;
    } catch( const char *e ) {
        cerr << "Error: " << e << endl;
        return 1;
    }

    return 0;
}