Commit f6113c52 authored by Ulysse Beaugnon's avatar Ulysse Beaugnon

You can now mesure the connectivity of a graph.

It is still very slow, I will try to improve performance
parent b4c5fdd0
#include "main.h" #include "main.h"
#include <cmath>
#include <map>
Graph::Graph(int size, int k, int maxPeers, mt19937 rng) : Graph::Graph(int size, int k, int maxPeers, mt19937& rng) :
distrib(uniform_int_distribution<int>(0, size-1)), distrib(uniform_int_distribution<int>(0, size-1)),
size(size) size(size), generator(rng)
{ {
adjacency = new vector<int>[size]; adjacency = new vector<int>[size];
for(int i=0; i<size; i++) for(int i=0; i<size; i++)
{ {
set<int> alreadyConnected; unordered_set<int> alreadyConnected;
alreadyConnected.insert(i); alreadyConnected.insert(i);
for(int j=0; j<k; j++) for(int j=0; j<k; j++)
...@@ -63,3 +65,159 @@ void Graph::KillMachines(float proportion) ...@@ -63,3 +65,159 @@ void Graph::KillMachines(float proportion)
} }
} }
} }
int Graph::GetMinCut()
{
int nIter = log(size)*log(size);
int minCut = -1;
for(int i=0; i<nIter; i++)
{
MinCutGraph graph = MinCutGraph(adjacency, size);
int minCutCandidate = GetMinCut(graph);
if(minCut == -1 || minCut > minCutCandidate)
minCut = minCutCandidate;
}
return minCut;
}
int Graph::GetMinCut(MinCutGraph& copy1)
{
int n=copy1.nodes.size();
if(n==2)
return copy1.edges.size();
MinCutGraph copy2(copy1);
int nMerge = min(n-2.0, n/1.414);
copy1.Merge(nMerge, generator);
copy2.Merge(nMerge, generator);
return min(GetMinCut(copy1), GetMinCut(copy2));
}
MinCutGraph::MinCutGraph(vector<int>* adjacency, int n)
{
nodes.resize(n);
int nextEdgeId = 0;
for(int i=0; i<n; i++)
for(int j : adjacency[i])
if(j > i)
{
nodes[i].v.insert(nextEdgeId);
nodes[j].v.insert(nextEdgeId);
edges.push_back(nullable<pair<int, int>>(pair<int, int>(i, j)));
nextEdgeId++;
}
}
void MinCutGraph::Merge(int nMerge, mt19937& rng)
{
uniform_int_distribution<int> distrib(0, edges.size()-1);
while(nMerge > 0)
{
// Choose an edge
int eId = distrib(rng);
if(edges[eId].null)
continue;
int n1 = edges[eId].v.first;
int n2 = edges[eId].v.second;
// anilate n2
nodes[n2].null = true;
// redirect all edges from n2
for(int i : nodes[n2].v)
{
if(edges[i].v.first == n1 || edges[i].v.second == n1)
{
nodes[n1].v.erase(i);
edges[i].null = true;
}
else
{
nodes[n1].v.insert(i);
if(edges[i].v.first == n2)
edges[i].v.first = n1;
else
edges[i].v.second = n1;
}
}
nMerge--;
}
RenumNodes();
RenumEdges();
}
void MinCutGraph::Check()
{
cout << "CHECKING ... "; cout.flush();
for(int i=0; i<edges.size(); i++)
{
if(!edges[i].null)
{
auto e = edges[i].v;
if(e.first >= nodes.size())
cout << "Bad first" << endl; cout.flush();
if(e.second >= nodes.size())
cout << "Bad second" << endl; cout.flush();
if(nodes[e.first].v.count(i) == 0)
cout << "Bad first node" << endl; cout.flush();
if(nodes[e.second].v.count(i) == 0)
cout << "Bad second node" << endl; cout.flush();
}
}
for(int i=0; i<nodes.size(); i++)
if(!nodes[i].null)
for(int e : nodes[i].v)
if(edges[e].v.first != i && edges[e].v.second != i)
cout << "Bad edge" << endl; cout.flush();
cout << "DONE" << endl; cout.flush();
}
void MinCutGraph::RenumEdges()
{
int nextId = 0;
for(int i=0; i<edges.size(); i++)
if(!edges[i].null)
{
edges[nextId] = edges[i];
nodes[edges[nextId].v.first].v.erase(i);
nodes[edges[nextId].v.first].v.insert(nextId);
nodes[edges[nextId].v.second].v.erase(i);
nodes[edges[nextId].v.second].v.insert(nextId);
nextId++;
}
edges.resize(nextId);
}
void MinCutGraph::RenumNodes()
{
int nextId = 0;
for(int i=0; i<nodes.size(); i++)
if(!nodes[i].null)
{
nodes[nextId] = nodes[i];
for(int j : nodes[nextId].v)
{
if(edges[j].v.first == i)
edges[j].v.first = nextId;
else
edges[j].v.second = nextId;
}
nextId++;
}
nodes.resize(nextId);
}
...@@ -5,23 +5,27 @@ ...@@ -5,23 +5,27 @@
const char* outName = "out.csv"; const char* outName = "out.csv";
Results Simulate(mt19937 rng, int n, int k, int maxPeer, int maxDistanceFrom, float alivePercent, int runs) Results Simulate(int seed, int n, int k, int maxPeer, int maxDistanceFrom, float alivePercent, int runs)
{ {
Results results(maxPeer, 20); Results results(maxPeer, 20);
mt19937 rng(seed);
for(int r=0; r<runs; r++) for(int r=0; r<runs; r++)
{ {
Graph graph(n, k, maxPeer, rng); Graph graph(n, k, maxPeer, rng);
graph.KillMachines(alivePercent); graph.KillMachines(alivePercent);
int minCut = graph.GetMinCut();
if(results.minKConnexity == -1 || results.minKConnexity > minCut)
results.minKConnexity = minCut;
results.UpdateArity(graph); results.UpdateArity(graph);
// Compute the shortest path // Compute the shortest path
for(int i=0; i<min(graph.size, maxDistanceFrom); i++) /*for(int i=0; i<min(graph.size, maxDistanceFrom); i++)
{ {
int distance[graph.size]; int distance[graph.size];
graph.GetDistancesFrom(i, distance); graph.GetDistancesFrom(i, distance);
results.UpdateDistance(distance, graph.size); results.UpdateDistance(distance, graph.size);
} }*/
} }
results.Finalise(); results.Finalise();
...@@ -34,24 +38,25 @@ int main(int argc, char** argv) ...@@ -34,24 +38,25 @@ int main(int argc, char** argv)
FILE* output = fopen(outName, "wt"); FILE* output = fopen(outName, "wt");
int fno = fileno(output); int fno = fileno(output);
fprintf(output, "n,k,maxPeer,avgDistance,disconnected,disconnectionProba,maxDistance,maxArityDistrib\n"); fprintf(output, "n,k,a,maxPeer,avgDistance,disconnected,disconnectionProba,maxDistance,maxArityDistrib,minCut\n");
vector<future<string>> outputStrings; vector<future<string>> outputStrings;
for(int n=200; n<=20000; n*=2) for(int n=2000; n<=2000; n*=2)
for(int k=10; k<=10; k+=5) for(int k=10; k<=10; k+=5)
for(float a=0.05; a<1; a+=0.05) for(float a=1; a<=1; a+=0.05)
{ {
outputStrings.push_back(async(launch::async, [rng, n, k, a]() int seed = rng();
{ outputStrings.push_back(async(launch::async, [seed, n, k, a]()
Results results = Simulate(rng, n, k, 3*k, 10000, a, 100); {
ostringstream out; Results results = Simulate(seed, n, k, 3*k, 10000, a, 1);
out << n << "," << k << "," << 3*k << "," << results.avgDistance << "," ostringstream out;
<< results.disconnected << "," << results.disconnectionProba << "," out << n << "," << k << "," << a << "," << 3*k << "," << results.avgDistance << ","
<< results.maxDistanceReached << "," << results.arityDistrib[3*k] << results.disconnected << "," << results.disconnectionProba << ","
<< endl; << results.maxDistanceReached << "," << results.arityDistrib[3*k] << "," << results.minKConnexity
return out.str(); << endl;
})); return out.str();
} }));
}
cout << "Launching finished" << endl; cout << "Launching finished" << endl;
......
...@@ -3,22 +3,52 @@ ...@@ -3,22 +3,52 @@
#include <random> #include <random>
#include <queue> #include <queue>
#include <set> #include <set>
#include <unordered_set>
using namespace std; using namespace std;
template<class T>
struct nullable
{
T v;
bool null;
nullable() : null(false) { };
nullable(T t) : v(t), null(false) { };
};
class MinCutGraph
{
public:
vector<nullable<pair<int, int>>> edges;
vector<nullable<unordered_set<int>>> nodes;
MinCutGraph(vector<int>* adjacency, int n);
void Merge(int nMerge, mt19937& rng);
private:
void Check();
void RenumEdges();
void RenumNodes();
};
class Graph class Graph
{ {
public: public:
Graph(int size, int k, int maxPeers, mt19937 rng); Graph(int size, int k, int maxPeers, mt19937& rng);
~Graph() { delete[] adjacency; }; ~Graph() { delete[] adjacency; };
void GetDistancesFrom(int node, int* distance); void GetDistancesFrom(int node, int* distance);
void KillMachines(float proportion); void KillMachines(float proportion);
int GetMinCut();
//void SplitAS(float proportionAS1, float proportionAS2);
vector<int>* adjacency; vector<int>* adjacency;
int size; int size;
private: private:
int GetMinCut(MinCutGraph& graph);
uniform_int_distribution<int> distrib; uniform_int_distribution<int> distrib;
mt19937& generator;
}; };
class Results class Results
...@@ -35,6 +65,7 @@ public: ...@@ -35,6 +65,7 @@ public:
double* distanceDistrib; double* distanceDistrib;
double avgDistance; double avgDistance;
int maxDistanceReached; int maxDistanceReached;
int minKConnexity;
double disconnectionProba; double disconnectionProba;
double arityTooBig; double arityTooBig;
...@@ -47,6 +78,7 @@ public: ...@@ -47,6 +78,7 @@ public:
private: private:
void AddAritySample(int arity); void AddAritySample(int arity);
void AddDistanceSample(int distance); void AddDistanceSample(int distance);
int64_t nAritySample; int64_t nAritySample;
int64_t nDistanceSample; int64_t nDistanceSample;
}; };
...@@ -17,6 +17,7 @@ Results::Results(int maxArity, int maxDistance) : ...@@ -17,6 +17,7 @@ Results::Results(int maxArity, int maxDistance) :
distanceTooBig = 0; distanceTooBig = 0;
disconnected = 0; disconnected = 0;
avgDistance = 0; avgDistance = 0;
minKConnexity = -1;
maxDistanceReached = -1; maxDistanceReached = -1;
} }
......
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