graph_absolute_trust.hh 7.15 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>
Tiago Peixoto's avatar
Tiago Peixoto committed
26
#include <boost/random/uniform_int.hpp>
Tiago Peixoto's avatar
Tiago Peixoto committed
27
#include <boost/functional/hash.hpp>
Tiago Peixoto's avatar
Tiago Peixoto committed
28
29
30
31
32
33

namespace graph_tool
{
using namespace std;
using namespace boost;

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

Tiago Peixoto's avatar
Tiago Peixoto committed
47
        unchecked_vector_property_map<vector<t_type>, VertexIndex>
Tiago Peixoto's avatar
Tiago Peixoto committed
48
49
50
51
52
53
54
            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);
        #pragma omp parallel for default(shared) private(i)     \
55
56
57
            schedule(dynamic)
        for (i = (source == -1) ? 0 : source;
             i < ((source == -1) ? N : source + 1); ++i)
Tiago Peixoto's avatar
Tiago Peixoto committed
58
        {
59
60
            typename graph_traits<Graph>::vertex_descriptor v =
                vertex(i, g);
Tiago Peixoto's avatar
Tiago Peixoto committed
61
62
63
64
65
66
67
            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
68
69
70
        #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
71
        {
Tiago Peixoto's avatar
Tiago Peixoto committed
72
73
74
75
76
77
78
79
            // walk hash set
            tr1::unordered_set<size_t> path_set;
            uniform_int<size_t> random_salt(0, numeric_limits<size_t>::max());
            size_t salt = random_salt(rng);

            t_type delta = 2*epslon;
            size_t iter = 0;
            while (delta >= epslon || iter < 10)
Tiago Peixoto's avatar
Tiago Peixoto committed
80
            {
Tiago Peixoto's avatar
Tiago Peixoto committed
81
                delta = 0;
Tiago Peixoto's avatar
Tiago Peixoto committed
82
83
84
85
86
87
88
                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;
89
                t_type pweight = 1.0;
Tiago Peixoto's avatar
Tiago Peixoto committed
90
91
                v_mark[v][vertex_index[v]] = iter+1;

Tiago Peixoto's avatar
Tiago Peixoto committed
92
93
94
                size_t path_hash = salt;
                hash_combine(path_hash, i);

Tiago Peixoto's avatar
Tiago Peixoto committed
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
                // 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)
                        {
111
                            if (c[*e] < 0)
112
                                continue;
Tiago Peixoto's avatar
Tiago Peixoto committed
113
114
                            out_es.push_back(*e);
                            if (out_prob.empty())
115
                                out_prob.push_back(c[*e]+0.1);
Tiago Peixoto's avatar
Tiago Peixoto committed
116
                            else
117
                                out_prob.push_back(out_prob.back()+c[*e]+0.1);
Tiago Peixoto's avatar
Tiago Peixoto committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
                        }
                    }
                    if (!out_es.empty())
                    {
                        // select edge according to its probability
                        typename graph_traits<Graph>::edge_descriptor e;
                        uniform_real<t_type> random(0,out_prob.back());

                        t_type u;
                        {
                            #pragma omp critical
                            u = random(rng);
                        }
                        e = out_es[lower_bound(out_prob.begin(),
                                               out_prob.end(), u) -
                                   out_prob.begin()];
134
135

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

139
140
141
142
143
144
                        //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
145
146
147
148
                        // get path hash
                        hash_combine(path_hash, posi);
                        if (path_set.find(path_hash) == path_set.end())
                        {
149
                            // if new path, modify vertex trust score
Tiago Peixoto's avatar
Tiago Peixoto committed
150
151
152
153
154
155
156
157
158
                            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]);
                        }
159
160
161
162

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

163
164
165
166
                        // stop if weight drops to zero
                        if (pweight == 0)
                            break;

Tiago Peixoto's avatar
Tiago Peixoto committed
167
168
169
170
                        v_mark[v][posi] = iter+1; // mark vertex
                    }
                }
                while (!out_es.empty());
Tiago Peixoto's avatar
Tiago Peixoto committed
171
172
173
174
                ++iter;
                if (max_iter > 0 && iter == max_iter)
                    break;
             }
Tiago Peixoto's avatar
Tiago Peixoto committed
175
176
        }

177
        #pragma omp parallel for default(shared) private(i) schedule(dynamic)
178
179
        for (i = (source == -1) ? 0 : source;
             i < ((source == -1) ? N : source + 1); ++i)
Tiago Peixoto's avatar
Tiago Peixoto committed
180
181
182
183
184
185
186
187
188
189
190
191
192
193
        {
            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