graph_absolute_trust.hh 7.4 KB
Newer Older
Tiago Peixoto's avatar
Tiago Peixoto committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007  Tiago de Paula Peixoto <tiago@forked.de>
//
// 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
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#ifndef GRAPH_ABSOLUTE_TRUST_HH
#define GRAPH_ABSOLUTE_TRUST_HH

#include "graph.hh"
#include "graph_filtering.hh"
#include "graph_util.hh"

Tiago Peixoto's avatar
Tiago Peixoto committed
25
#include <tr1/unordered_set>
26
#include <tr1/random>
Tiago Peixoto's avatar
Tiago Peixoto committed
27
#include <boost/functional/hash.hpp>
Tiago Peixoto's avatar
Tiago Peixoto committed
28

29
30
#include <iostream>

Tiago Peixoto's avatar
Tiago Peixoto committed
31
32
33
34
35
namespace graph_tool
{
using namespace std;
using namespace boost;

36
struct get_absolute_trust
Tiago Peixoto's avatar
Tiago Peixoto committed
37
{
38
    template <class Graph, class VertexIndex, class TrustMap,
Tiago Peixoto's avatar
Tiago Peixoto committed
39
              class InferredTrustMap>
40
41
    void operator()(Graph& g, VertexIndex vertex_index, int64_t source,
                    TrustMap c, InferredTrustMap t, double epslon,
42
43
                    pair<size_t,size_t> iter_range, bool reversed,
                    rng_t& rng) const
Tiago Peixoto's avatar
Tiago Peixoto committed
44
45
46
47
48
    {
        typedef typename property_traits<TrustMap>::value_type c_type;
        typedef typename property_traits<InferredTrustMap>::value_type
            ::value_type t_type;

49
50
51
        size_t min_iter = iter_range.first;
        size_t max_iter = iter_range.second;

Tiago Peixoto's avatar
Tiago Peixoto committed
52
        unchecked_vector_property_map<vector<t_type>, VertexIndex>
Tiago Peixoto's avatar
Tiago Peixoto committed
53
54
55
56
57
58
            t_count(vertex_index, num_vertices(g));
        unchecked_vector_property_map<vector<size_t>, VertexIndex>
            v_mark(vertex_index, num_vertices(g));

        // init inferred trust t
        int i, N = num_vertices(g);
59
        #pragma omp parallel for default(shared) private(i) schedule(dynamic)
60
61
        for (i = (source == -1) ? 0 : source;
             i < ((source == -1) ? N : source + 1); ++i)
Tiago Peixoto's avatar
Tiago Peixoto committed
62
        {
63
64
            typename graph_traits<Graph>::vertex_descriptor v =
                vertex(i, g);
Tiago Peixoto's avatar
Tiago Peixoto committed
65
66
67
68
69
70
71
            if (v == graph_traits<Graph>::null_vertex())
                continue;
            t[v].resize(N);
            t_count[v].resize(N,0);
            v_mark[v].resize(N,0);
        }

Tiago Peixoto's avatar
Tiago Peixoto committed
72
73
74
        #pragma omp parallel for default(shared) private(i) schedule(dynamic)
        for (i = (source == -1) ? 0 : source;
             i < ((source == -1) ? N : source + 1); ++i)
Tiago Peixoto's avatar
Tiago Peixoto committed
75
        {
Tiago Peixoto's avatar
Tiago Peixoto committed
76
77
            // walk hash set
            tr1::unordered_set<size_t> path_set;
78
79
            tr1::uniform_int<size_t>
                random_salt(0, numeric_limits<size_t>::max());
Tiago Peixoto's avatar
Tiago Peixoto committed
80
81
            size_t salt = random_salt(rng);

82
            t_type delta = epslon + 1;
Tiago Peixoto's avatar
Tiago Peixoto committed
83
            size_t iter = 0;
84
            while (delta > epslon || iter < min_iter)
Tiago Peixoto's avatar
Tiago Peixoto committed
85
            {
Tiago Peixoto's avatar
Tiago Peixoto committed
86
                delta = 0;
Tiago Peixoto's avatar
Tiago Peixoto committed
87
88
89
90
91
92
93
                typename graph_traits<Graph>::vertex_descriptor v =
                    vertex(i, g);
                if (v == graph_traits<Graph>::null_vertex())
                    continue;

                typename graph_traits<Graph>::vertex_descriptor pos = v;
                t_type pos_t = 1.0;
94
                t_type pweight = 1.0;
Tiago Peixoto's avatar
Tiago Peixoto committed
95
96
                v_mark[v][vertex_index[v]] = iter+1;

Tiago Peixoto's avatar
Tiago Peixoto committed
97
98
99
                size_t path_hash = salt;
                hash_combine(path_hash, i);

Tiago Peixoto's avatar
Tiago Peixoto committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
                // start a self-avoiding walk from vertex v
                vector<typename graph_traits<Graph>::edge_descriptor> out_es;
                vector<t_type> out_prob;
                do
                {
                    out_es.clear();
                    out_prob.clear();

                    // obtain list of candidate edges to follow
                    typename graph_traits<Graph>::out_edge_iterator e, e_end;
                    for (tie(e, e_end) = out_edges(pos, g); e != e_end; ++e)
                    {
                        typename graph_traits<Graph>::vertex_descriptor t =
                            target(*e,g);
                        if (v_mark[v][vertex_index[t]] <= iter)
                        {
116
                            if (c[*e] < 0)
117
                                continue;
Tiago Peixoto's avatar
Tiago Peixoto committed
118
119
                            out_es.push_back(*e);
                            if (out_prob.empty())
120
                                out_prob.push_back(c[*e]+0.1);
Tiago Peixoto's avatar
Tiago Peixoto committed
121
                            else
122
                                out_prob.push_back(out_prob.back()+c[*e]+0.1);
Tiago Peixoto's avatar
Tiago Peixoto committed
123
124
125
126
127
128
                        }
                    }
                    if (!out_es.empty())
                    {
                        // select edge according to its probability
                        typename graph_traits<Graph>::edge_descriptor e;
129
                        typedef tr1::uniform_real<t_type> dist_t;
130
                        tr1::variate_generator<rng_t&, dist_t>
131
                            random(rng, dist_t(0, out_prob.back()));
Tiago Peixoto's avatar
Tiago Peixoto committed
132
133
134
135

                        t_type u;
                        {
                            #pragma omp critical
136
                            u = random();
Tiago Peixoto's avatar
Tiago Peixoto committed
137
138
139
140
                        }
                        e = out_es[lower_bound(out_prob.begin(),
                                               out_prob.end(), u) -
                                   out_prob.begin()];
141
142

                        // new position in random walk
Tiago Peixoto's avatar
Tiago Peixoto committed
143
144
145
                        pos = target(e,g);
                        size_t posi = vertex_index[pos];

146
147
148
149
150
151
                        //update current path trust
                        pos_t *= c[e];

                        if (reversed && boost::source(e, g) != v)
                            pweight *= c[e];

Tiago Peixoto's avatar
Tiago Peixoto committed
152
153
154
155
                        // get path hash
                        hash_combine(path_hash, posi);
                        if (path_set.find(path_hash) == path_set.end())
                        {
156
                            // if new path, modify vertex trust score
Tiago Peixoto's avatar
Tiago Peixoto committed
157
158
159
160
161
162
163
164
165
                            path_set.insert(path_hash);

                            t_type old = 0;
                            if (t_count[v][posi] > 0)
                                old = t[v][posi]/t_count[v][posi];
                            t[v][posi] += pos_t*pweight;
                            t_count[v][posi] += pweight;
                            delta += abs(old - t[v][posi]/t_count[v][posi]);
                        }
166
167
168
169

                        if (!reversed)
                            pweight *= c[e];

170
171
172
173
                        // stop if weight drops to zero
                        if (pweight == 0)
                            break;

Tiago Peixoto's avatar
Tiago Peixoto committed
174
175
176
177
                        v_mark[v][posi] = iter+1; // mark vertex
                    }
                }
                while (!out_es.empty());
Tiago Peixoto's avatar
Tiago Peixoto committed
178
179
180
181
                ++iter;
                if (max_iter > 0 && iter == max_iter)
                    break;
             }
Tiago Peixoto's avatar
Tiago Peixoto committed
182
183
        }

184
        #pragma omp parallel for default(shared) private(i) schedule(dynamic)
185
186
        for (i = (source == -1) ? 0 : source;
             i < ((source == -1) ? N : source + 1); ++i)
Tiago Peixoto's avatar
Tiago Peixoto committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
        {
            typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
            if (v == graph_traits<Graph>::null_vertex())
                continue;
            for (size_t j = 0; j < N; ++j)
                if (t_count[v][j] > 0)
                    t[v][j] /= t_count[v][j];
        }
    }
};

}

#endif