Commit ed814636 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

* much improved directed correlation generation

* fixed bug related to negative sampled degrees


git-svn-id: https://svn.forked.de/graph-tool/trunk@14 d4600afd-f417-0410-95de-beed9576f240
parent 017675f0
...@@ -187,12 +187,12 @@ public: ...@@ -187,12 +187,12 @@ public:
pair<size_t,size_t> operator()(double r1, double r2) pair<size_t,size_t> operator()(double r1, double r2)
{ {
object retval = _o(r1,r2); object retval = _o(r1,r2);
return make_pair(size_t(extract<size_t>(retval[0])), size_t(extract<size_t>(retval[1]))); return make_pair(size_t(max(int(extract<int>(retval[0])),0)), size_t(max(int(extract<int>(retval[1])),0)));
} }
pair<size_t,size_t> operator()(double r1, double r2, size_t j, size_t k) pair<size_t,size_t> operator()(double r1, double r2, size_t j, size_t k)
{ {
object retval = _o(r1,r2,j,k); object retval = _o(r1,r2,j,k);
return make_pair(size_t(extract<size_t>(retval[0])), size_t(extract<size_t>(retval[1]))); return make_pair(size_t(max(int(extract<int>(retval[0])),0)), size_t(max(int(extract<int>(retval[1])),0)));
} }
object _o; object _o;
}; };
......
...@@ -111,73 +111,53 @@ struct total_deg_comp ...@@ -111,73 +111,53 @@ struct total_deg_comp
// so that the nearest (j,k) to a given target can be found easily. // so that the nearest (j,k) to a given target can be found easily.
//============================================================================== //==============================================================================
class degree_matrix_t: public vector<vector<vector<pair<size_t,size_t> > > > class degree_matrix_t
{ {
public: public:
typedef vector<vector<vector<pair<size_t,size_t> > > > base_t; degree_matrix_t(size_t N, size_t minj, size_t mink, size_t maxj, size_t maxk)
degree_matrix_t(size_t N, size_t max_j, size_t max_k, size_t avg_deg)
{ {
_L = size_t(sqrt(N)); _L = max(size_t(pow(2,ceil(log2(sqrt(N))))),size_t(2));
base_t &base = *this; _minj = minj;
base = base_t(_L, vector<vector<pair<size_t,size_t> > >(_L)); _mink = mink;
_cj = pow(max_j+1,1.0/(_L-1)) - 1.0; _maxj = max(maxj,_L);
_ck = pow(max_k+1,1.0/(_L-1)) - 1.0; _maxk = max(maxk,_L);
_avg_deg = avg_deg; _bins.resize(_L, vector<vector<pair<size_t,size_t> > >(_L));
_nearest_bins = base_t(_L, vector<vector<pair<size_t,size_t> > >(_L)); _high_bins.resize(size_t(log2(_L)));
_size = 0; for(size_t i = 0; i < _high_bins.size(); ++i)
_high_bins[i].resize(_L/(1<<(i+1)), vector<size_t>(_L/(1<<(i+1))));
} }
void insert(const pair<size_t, size_t>& v) void insert(const pair<size_t, size_t>& v)
{ {
size_t j_bin, k_bin; size_t j_bin, k_bin;
tie(j_bin, k_bin) = get_bin(v.first, v.second); tie(j_bin, k_bin) = get_bin(v.first, v.second, 0);
if ((*this)[j_bin][k_bin].empty()) _bins[j_bin][k_bin].push_back(v);
_size++; for (size_t i = 0; i < _high_bins.size(); ++i)
(*this)[j_bin][k_bin].push_back(v); {
size_t hj,hk;
} tie(hj,hk) = get_bin(j_bin,k_bin, i+1);
_high_bins[i][hj][hk]++;
void arrange_proximity() }
{
for(size_t j = 0; j < _L; ++j)
for(size_t k = 0; k < _L; ++k)
{
_nearest_bins[j][k].clear();
if ((*this)[j][k].empty())
{
for(size_t w = 1; w < _L; ++w)
{
for (size_t i = ((j>w)?j-w:0); i < ((j+w<=_L)?j+w:_L); ++i)
for (size_t l = ((k>w)?k-w:0); l < ((k+w<=_L)?k+w:_L); ++l)
{
if (!(*this)[i][l].empty())
_nearest_bins[j][k].push_back(make_pair(i,l));
}
if (!_nearest_bins[j][k].empty())
break;
}
}
}
} }
void erase(const pair<size_t,size_t>& v) void erase(const pair<size_t,size_t>& v)
{ {
size_t j_bin, k_bin; size_t j_bin, k_bin;
tie(j_bin, k_bin) = get_bin(v.first, v.second); tie(j_bin, k_bin) = get_bin(v.first, v.second, 0);
for(size_t i = 0; i < (*this)[j_bin][k_bin].size(); ++i) for(size_t i = 0; i < _bins[j_bin][k_bin].size(); ++i)
{ {
if ((*this)[j_bin][k_bin][i] == v) if (_bins[j_bin][k_bin][i] == v)
{ {
(*this)[j_bin][k_bin].erase((*this)[j_bin][k_bin].begin()+i); _bins[j_bin][k_bin].erase(_bins[j_bin][k_bin].begin()+i);
break; break;
} }
} }
if ((*this)[j_bin][k_bin].empty())
for (size_t i = 0; i < _high_bins.size(); ++i)
{ {
_size--; size_t hj,hk;
if (_size > _L) tie(hj,hk) = get_bin(j_bin,k_bin, i+1);
arrange_proximity(); _high_bins[i][hj][hk]--;
} }
} }
...@@ -185,94 +165,88 @@ public: ...@@ -185,94 +165,88 @@ public:
pair<size_t,size_t> find_closest(size_t j, size_t k, rng_t& rng) pair<size_t,size_t> find_closest(size_t j, size_t k, rng_t& rng)
{ {
vector<pair<size_t,size_t> > candidates; vector<pair<size_t,size_t> > candidates;
size_t j_bin, k_bin;
tie(j_bin, k_bin) = get_bin(j, k);
if ((*this)[j_bin][k_bin].empty()) size_t level;
// find the appropriate level on which to operate
for (level = _high_bins.size(); level <= 0; --level)
{ {
if (_size > _L) size_t hj, hk;
{ tie(hj,hk) = get_bin(j,k,level);
if (_nearest_bins[j_bin][k_bin].empty()) if (get_bin_count(hj,hk,level) == 0)
arrange_proximity();
for(size_t i = 0; i < _nearest_bins[j_bin][k_bin].size(); ++i)
{
size_t jb,kb;
tie(jb,kb) = _nearest_bins[j_bin][k_bin][i];
search_bin(jb, kb, j, k, candidates);
}
}
else
{ {
for(size_t jb = 0; jb < _L; ++jb) if (level < _high_bins.size())
for(size_t kb = 0; kb < _L; ++kb) level++;
search_bin(jb, kb, j, k, candidates); break;
} }
} }
else
{
search_bin(j_bin, k_bin, j, k, candidates);
size_t distance = size_t(sqrt(dist(candidates.front(), vertex_t(j,k)))); size_t j_bin, k_bin;
tie(j_bin, k_bin) = get_bin(j, k, level);
for (int x = -1; x < 2; ++x)
for (int y = -1; y < 2; ++y) for (size_t hj = ((j_bin>0)?j_bin-1:j_bin); hj < j_bin + 1 && hj <= get_bin(_maxj, _maxk, level).first; ++hj)
{ for (size_t hk = ((k_bin>0)?k_bin-1:k_bin); hk < k_bin + 1 && hk <= get_bin(_maxj, _maxk, level).second; ++hk)
size_t jb,kb; search_bin(hj,hk,j,k,level,candidates);
tie(jb,kb) = get_bin(max(int(j+x*distance),0), max(int(k+y*distance),0));
if (tie(jb,kb) == tie(j_bin,k_bin))
continue;
search_bin(jb, kb, j, k, candidates);
}
}
uniform_int<size_t> sample(0, candidates.size() - 1); uniform_int<size_t> sample(0, candidates.size() - 1);
return candidates[sample(rng)]; return candidates[sample(rng)];
} }
private: private:
pair<size_t,size_t> get_bin(size_t j, size_t k)
pair<size_t,size_t> get_bin(size_t j, size_t k, size_t level)
{ {
// uses logarithmic binning... if (level == 0)
size_t j_bin, k_bin, lim; return make_pair(((j-_minj)*(_L-1))/_maxj, ((k-_mink)*(_L-1))/_maxk);
lim = size_t(1.5*_avg_deg);
if (j < lim) pair<size_t, size_t> bin = get_bin(j,k,0);
j_bin = j; bin.first /= 1 << level;
else bin.second /= 1 << level;
j_bin = size_t(log(j)/log(_cj+1)) - size_t(log(lim)/log(_cj+1)) + lim; return bin;
if (k < lim) }
k_bin = k;
size_t get_bin_count(size_t bin_j, size_t bin_k, size_t level)
{
if (level == 0)
return _bins[bin_j][bin_k].size();
else else
k_bin = size_t(log(k)/log(_ck+1)) - size_t(log(lim)/log(_cj+1)) + lim; return _high_bins[level-1][bin_j][bin_k];
return make_pair(min(j_bin, _L-1), min(k_bin,_L-1));
} }
void search_bin(size_t j_bin, size_t k_bin, size_t j, size_t k, vector<pair<size_t,size_t> >& candidates) void search_bin(size_t hj, size_t hk, size_t j, size_t k, size_t level, vector<pair<size_t,size_t> >& candidates)
{ {
for (typeof((*this)[j_bin][k_bin].begin()) iter = (*this)[j_bin][k_bin].begin(); iter != (*this)[j_bin][k_bin].end(); ++iter) size_t w = 1 << level;
{ for (size_t j_bin = hj*w; j_bin < (hj+1)*w; ++j_bin)
if (candidates.empty()) for (size_t k_bin = hk*w; k_bin < (hk+1)*w; ++k_bin)
{ {
candidates.push_back(*iter); for (size_t i = 0; i < _bins[j_bin][k_bin].size(); ++i)
continue; {
} pair<size_t, size_t>& v = _bins[j_bin][k_bin][i];
if (dist(vertex_t(*iter), vertex_t(j,k)) < dist(vertex_t(candidates.front()),vertex_t(j,k))) if (candidates.empty())
{ {
candidates.clear(); candidates.push_back(v);
candidates.push_back(*iter); continue;
} }
else if (dist(vertex_t(*iter), vertex_t(j,k)) == dist(vertex_t(candidates.front()),vertex_t(j,k))) if (dist(vertex_t(v), vertex_t(j,k)) < dist(vertex_t(candidates.front()),vertex_t(j,k)))
{ {
candidates.push_back(*iter); candidates.clear();
candidates.push_back(v);
}
else if (dist(vertex_t(v), vertex_t(j,k)) == dist(vertex_t(candidates.front()),vertex_t(j,k)))
{
candidates.push_back(v);
}
}
} }
}
} }
size_t _L; size_t _L;
double _cj; vector<vector<vector<pair<size_t,size_t> > > > _bins;
double _ck; vector<vector<vector<size_t> > > _high_bins;
size_t _avg_deg; size_t _minj;
base_t _nearest_bins; size_t _mink;
size_t _size; size_t _maxj;
size_t _maxk;
}; };
//============================================================================== //==============================================================================
...@@ -291,7 +265,7 @@ void GraphInterface::GenerateCorrelatedConfigurationalModel(size_t N, pjk_t pjk, ...@@ -291,7 +265,7 @@ void GraphInterface::GenerateCorrelatedConfigurationalModel(size_t N, pjk_t pjk,
sample_from_distribution<pjk_t, pjk_t, inv_ceil_t> pjk_sample(pjk, ceil_pjk, inv_ceil_pjk, ceil_pjk_bound, rng); sample_from_distribution<pjk_t, pjk_t, inv_ceil_t> pjk_sample(pjk, ceil_pjk, inv_ceil_pjk, ceil_pjk_bound, rng);
vector<vertex_t> vertices(N); vector<vertex_t> vertices(N);
size_t sum_j=0, sum_k=0, max_j=0, max_k=0; size_t sum_j=0, sum_k=0, min_j=0, min_k=0, max_j=0, max_k=0;
if (verbose) if (verbose)
{ {
cout << "adding vertices: " << flush; cout << "adding vertices: " << flush;
...@@ -312,6 +286,8 @@ void GraphInterface::GenerateCorrelatedConfigurationalModel(size_t N, pjk_t pjk, ...@@ -312,6 +286,8 @@ void GraphInterface::GenerateCorrelatedConfigurationalModel(size_t N, pjk_t pjk,
tie(v.in_degree, v.out_degree) = pjk_sample(); tie(v.in_degree, v.out_degree) = pjk_sample();
sum_j += v.in_degree; sum_j += v.in_degree;
sum_k += v.out_degree; sum_k += v.out_degree;
min_j = min(v.in_degree,min_j);
min_k = min(v.out_degree,min_k);
max_j = max(v.in_degree,max_j); max_j = max(v.in_degree,max_j);
max_k = max(v.out_degree,max_k); max_k = max(v.out_degree,max_k);
} }
...@@ -369,7 +345,7 @@ void GraphInterface::GenerateCorrelatedConfigurationalModel(size_t N, pjk_t pjk, ...@@ -369,7 +345,7 @@ void GraphInterface::GenerateCorrelatedConfigurationalModel(size_t N, pjk_t pjk,
typedef multiset<pair<size_t,size_t>, total_deg_comp> ordered_degrees_t; typedef multiset<pair<size_t,size_t>, total_deg_comp> ordered_degrees_t;
ordered_degrees_t ordered_degrees; // (j,k) pairs ordered by (j+k), i.e, total degree ordered_degrees_t ordered_degrees; // (j,k) pairs ordered by (j+k), i.e, total degree
degree_matrix_t degree_matrix(target_degrees.size(), max_j, max_k, E/N); // (j,k) pairs layed out in a 2 dimensional matrix degree_matrix_t degree_matrix(target_degrees.size(), min_j, min_k, max_j, max_k); // (j,k) pairs layed out in a 2 dimensional matrix
for(typeof(target_degrees.begin()) iter = target_degrees.begin(); iter != target_degrees.end(); ++iter) for(typeof(target_degrees.begin()) iter = target_degrees.begin(); iter != target_degrees.end(); ++iter)
if (undirected_corr) if (undirected_corr)
ordered_degrees.insert(*iter); ordered_degrees.insert(*iter);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment