Files
@ 0f3a4ccb62ea
Branch filter:
Location: AENC/switchchain/cpp/switchchain.cpp
0f3a4ccb62ea
3.6 KiB
text/x-c++src
Add generation of random degree distribution and split cpp file
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 118 119 120 121 122 123 124 | #include <algorithm>
#include <fstream>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>
#include "graph.hpp"
#include "exports.hpp"
// Its assumed that u,v are distinct.
// Check if all four vertices are distinct
bool edgeConflicts(const Edge &e1, const Edge &e2) {
return (e1.u == e2.u || e1.u == e2.v || e1.v == e2.u || e1.v == e2.v);
}
class SwitchChain {
public:
SwitchChain() : mt(std::random_device{}()), permutationDistribution(0, 2) {
// random_device uses hardware entropy if available
// std::random_device rd;
// mt.seed(rd());
}
~SwitchChain() {}
bool initialize(const Graph &gstart) {
if (gstart.edgeCount() == 0)
return false;
g = gstart;
edgeDistribution.param(
std::uniform_int_distribution<>::param_type(0, g.edgeCount() - 1));
return true;
}
bool doMove() {
Edge e1 = g.getEdge(edgeDistribution(mt));
Edge e2 = g.getEdge(edgeDistribution(mt));
// Keep regenerating while conflicting edges
int timeout = 0;
while (edgeConflicts(e1, e2)) {
e1 = g.getEdge(edgeDistribution(mt));
e2 = g.getEdge(edgeDistribution(mt));
++timeout;
if (timeout % 100 == 0) {
std::cerr << "Warning: sampled " << timeout
<< " random edges but they keep conflicting.\n";
}
}
// Consider one of the three possible permutations
// 1) e1.u - e1.v and e2.u - e2.v (original)
// 2) e1.u - e2.u and e1.v - e2.v
// 3) e1.u - e2.v and e1.v - e2.u
// Note that it might be that these new edges already exist
// in which case we also reject the move
// This is checked in exchangeEdges
int perm = permutationDistribution(mt);
if (perm == 0) // Original permutation
return false;
return g.exchangeEdges(e1, e2, perm == 1);
}
Graph g;
std::mt19937 mt;
std::uniform_int_distribution<> edgeDistribution;
std::uniform_int_distribution<> permutationDistribution;
};
int main() {
Graph g;
// Generate a random degree sequence
std::mt19937 gen(std::random_device{}());
// 50 nodes with average degree 12
DegreeSequence ds(50);
std::poisson_distribution<> degDist(7);
// Try at most 10 times to generate a valid sequence
bool validGraph = false;
for (int i = 0; i < 10; ++i) {
std::generate(ds.begin(), ds.end(),
[°Dist, &gen] { return degDist(gen); });
if (g.createFromDegreeSequence(ds)) {
validGraph = true;
break;
}
}
if (!validGraph) {
std::cerr << "Could not create graph from degree sequence.\n";
return 1;
}
std::sort(ds.begin(), ds.end());
std::cout << "Degree sequence:";
for (auto i : ds)
std::cout << ' ' << i;
std::cout << std::endl;
SwitchChain chain;
if (!chain.initialize(g)) {
std::cerr << "Could not initialize Markov chain.\n";
return 1;
}
std::ofstream outfile("graphdata.m");
outfile << '{' << g;
std::cout << "Starting switch Markov chain" << std::endl;
int movesDone = 0;
int movesTotal = 100000;
for (int i = 0; i < movesTotal; ++i) {
if (chain.doMove())
++movesDone;
if (i % (movesTotal / 50) == (movesTotal / 50 - 1))
outfile << ',' << chain.g;
}
outfile << '}';
std::cout << movesDone << '/' << movesTotal << " moves succeeded."
<< std::endl;
return 0;
}
|