Files
@ 73c8d2811bea
Branch filter:
Location: AENC/switchchain/cpp/graph_gcm.hpp
73c8d2811bea
4.1 KiB
text/x-c++hdr
Add some correlation plots
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | #include "graph.hpp"
#include <algorithm>
#include <iostream>
#include <random>
#include <vector>
//
// Assumes degree sequence does NOT contain any zeroes!
//
// method2 = true -> take highest degree and finish its pairing completely
// method2 = false -> take new highest degree after every pairing
template <typename RNG>
bool greedyConfigurationModel(DegreeSequence& ds, Graph& g, RNG& rng, bool method2) {
// Similar to Havel-Hakimi but instead of pairing up with the highest ones
// that remain, simply pair up with random ones
unsigned int n = ds.size();
// degree, vertex index
std::vector<std::pair<unsigned int, unsigned int>> degrees(n);
for (unsigned int i = 0; i < n; ++i) {
degrees[i].first = ds[i];
degrees[i].second = i;
}
std::vector<decltype(degrees.begin())> available;
available.reserve(n);
// Clear the graph
g.reset(n);
while (!degrees.empty()) {
std::shuffle(degrees.begin(), degrees.end(), rng);
// Get the highest degree:
// If there are multiple highest ones, we pick a random one,
// ensured by the shuffle.
// The shuffle is needed anyway for the remaining part
unsigned int dmax = 0;
auto uIter = degrees.begin();
for (auto iter = degrees.begin(); iter != degrees.end(); ++iter) {
if (iter->first >= dmax) {
dmax = iter->first;
uIter = iter;
}
}
if (dmax > degrees.size() - 1)
return false;
if (dmax == 0) {
std::cerr << "ERROR 1 in GCM.\n";
}
unsigned int u = uIter->second;
if (method2) {
// Take the highest degree out of the vector
degrees.erase(uIter);
// Now assign randomly to the remaining vertices
// Since its shuffled, we can pick the first 'dmax' ones
auto vIter = degrees.begin();
while (dmax--) {
if (vIter->first == 0)
std::cerr << "ERROR in GCM2.\n";
if (!g.addEdge({u, vIter->second}))
std::cerr << "ERROR. Could not add edge in GCM2.\n";
vIter->first--;
if (vIter->first == 0)
vIter = degrees.erase(vIter);
else
vIter++;
}
} else {
// Pair with a random vertex that is not u itself and to which
// u has not paired yet!
available.clear();
for (auto iter = degrees.begin(); iter != degrees.end(); ++iter) {
if (iter->second != u && !g.hasEdge({u, iter->second}))
available.push_back(iter);
}
if (available.empty())
return false;
std::uniform_int_distribution<> distr(0, available.size() - 1);
auto vIter = available[distr(rng)];
// pair u to v
if (vIter->first == 0)
std::cerr << "ERROR 2 in GCM1.\n";
if (!g.addEdge({u, vIter->second}))
std::cerr << "ERROR. Could not add edge in GCM1.\n";
// Purge anything with degree zero
// Be careful with invalidating the other iterator!
// Degree of u is always greater or equal to the degree of v
if (dmax == 1) {
// Remove both
// Erasure invalidates all iterators AFTER the erased one
if (vIter > uIter) {
degrees.erase(vIter);
degrees.erase(uIter);
} else {
degrees.erase(uIter);
degrees.erase(vIter);
}
} else {
// Remove only v if it reaches zero
uIter->first--;
vIter->first--;
if (vIter->first == 0)
degrees.erase(vIter);
}
//degrees.erase(std::remove_if(degrees.begin(), degrees.end(),
// [](auto x) { return x.first == 0; }));
}
}
return true;
}
|