graph_rewiring.cc 5.21 KB
Newer Older
Tiago Peixoto's avatar
 
Tiago Peixoto committed
1 2
// graph-tool -- a general graph modification and manipulation thingy
//
Tiago Peixoto's avatar
Tiago Peixoto committed
3
// Copyright (C) 2007-2012 Tiago de Paula Peixoto <tiago@skewed.de>
Tiago Peixoto's avatar
 
Tiago Peixoto committed
4 5 6 7 8 9 10 11 12 13 14 15
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
Tiago Peixoto's avatar
Tiago Peixoto committed
16
// along with this program. If not, see <http://www.gnu.org/licenses/>.
Tiago Peixoto's avatar
 
Tiago Peixoto committed
17 18 19

#include "graph.hh"
#include "graph_filtering.hh"
20

21 22 23 24 25
#if (GCC_VERSION >= 40400)
#   include <tr1/random>
#else
#   include <boost/tr1/random.hpp>
#endif
26

27
#include "graph_rewiring.hh"
Tiago Peixoto's avatar
 
Tiago Peixoto committed
28

29
#include <boost/bind.hpp>
30
#include <boost/python.hpp>
31

32
using namespace graph_tool;
Tiago Peixoto's avatar
 
Tiago Peixoto committed
33 34
using namespace boost;

35 36 37 38 39
class PythonFuncWrap
{
public:
    PythonFuncWrap(python::object o): _o(o) {}

40 41
    double operator()(pair<size_t, size_t> deg1, pair<size_t, size_t> deg2)
        const
42
    {
43 44
        python::object ret = _o(python::make_tuple(deg1.first, deg1.second),
                                python::make_tuple(deg2.first, deg2.second));
45 46 47
        return python::extract<double>(ret);
    }

48 49 50
    template <class Type>
    double operator()(const Type& deg1, const Type& deg2) const
    {
51
        python::object ret = _o(python::object(deg1), python::object(deg2));
52 53 54
        return python::extract<double>(ret);
    }

55 56 57 58
private:
    python::object _o;
};

59 60 61 62 63 64

struct graph_rewire_block
{
    template <class Graph, class EdgeIndexMap, class CorrProb, class BlockProp>
    void operator()(Graph& g, EdgeIndexMap edge_index, CorrProb corr_prob,
                    pair<bool, bool> rest, BlockProp block_prop,
65 66 67
                    pair<size_t, bool> iter_sweep,
                    pair<bool, bool> cache_verbose, size_t& pcount, rng_t& rng)
        const
68 69 70
    {
        graph_rewire<ProbabilisticRewireStrategy>()
            (g, edge_index, corr_prob, rest.first, rest.second, iter_sweep,
71
             cache_verbose, pcount, rng, PropertyBlock<BlockProp>(block_prop));
72 73 74 75
    }
};


76 77
size_t random_rewire(GraphInterface& gi, string strat, size_t niter,
                     bool no_sweep, bool self_loops, bool parallel_edges,
78
                     python::object corr_prob, boost::any block,
79
                     bool cache, size_t seed, bool verbose)
Tiago Peixoto's avatar
 
Tiago Peixoto committed
80
{
81
    rng_t rng(static_cast<rng_t::result_type>(seed));
82
    PythonFuncWrap corr(corr_prob);
83
    size_t pcount = 0;
Tiago Peixoto's avatar
 
Tiago Peixoto committed
84

85 86
    if (strat == "erdos")
        run_action<graph_tool::detail::never_reversed>()
87 88
            (gi, boost::bind<void>(graph_rewire<ErdosRewireStrategy>(),
                                   _1, gi.GetEdgeIndex(), boost::ref(corr),
89
                                   self_loops, parallel_edges,
90 91
                                   make_pair(niter, no_sweep),
                                   make_pair(cache, verbose),
92
                                   boost::ref(pcount), boost::ref(rng)))();
93
    else if (strat == "uncorrelated")
94
        run_action<graph_tool::detail::never_reversed>()
95 96
            (gi, boost::bind<void>(graph_rewire<RandomRewireStrategy>(),
                                   _1, gi.GetEdgeIndex(), boost::ref(corr),
97
                                   self_loops, parallel_edges,
98 99
                                   make_pair(niter, no_sweep),
                                   make_pair(cache, verbose),
100
                                   boost::ref(pcount), boost::ref(rng)))();
Tiago Peixoto's avatar
Tiago Peixoto committed
101
    else if (strat == "correlated")
102
        run_action<graph_tool::detail::never_reversed>()
103 104
            (gi, boost::bind<void>(graph_rewire<CorrelatedRewireStrategy>(),
                                   _1, gi.GetEdgeIndex(), boost::ref(corr),
105
                                   self_loops, parallel_edges,
106 107
                                   make_pair(niter, no_sweep),
                                   make_pair(cache, verbose),
108
                                   boost::ref(pcount), boost::ref(rng)))();
109 110
    else if (strat == "probabilistic")
        run_action<>()
111 112
            (gi, boost::bind<void>(graph_rewire<ProbabilisticRewireStrategy>(),
                                   _1, gi.GetEdgeIndex(), boost::ref(corr),
113
                                   self_loops, parallel_edges,
114 115
                                   make_pair(niter, no_sweep),
                                   make_pair(cache, verbose),
116
                                   boost::ref(pcount), boost::ref(rng)))();
117 118 119 120 121
    else if (strat == "blockmodel")
        run_action<>()
            (gi, boost::bind<void>(graph_rewire_block(),
                                   _1, gi.GetEdgeIndex(), boost::ref(corr),
                                   make_pair(self_loops, parallel_edges), _2,
122 123
                                   make_pair(niter, no_sweep),
                                   make_pair(cache, verbose),
124 125
                                   boost::ref(pcount), boost::ref(rng)),
             vertex_properties())(block);
Tiago Peixoto's avatar
Tiago Peixoto committed
126
    else
Tiago Peixoto's avatar
Tiago Peixoto committed
127
        throw ValueException("invalid random rewire strategy: " + strat);
128
    return pcount;
Tiago Peixoto's avatar
 
Tiago Peixoto committed
129
}