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 <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)),
size(size)
size(size), generator(rng)
{
adjacency = new vector<int>[size];
for(int i=0; i<size; i++)
{
set<int> alreadyConnected;
unordered_set<int> alreadyConnected;
alreadyConnected.insert(i);
for(int j=0; j<k; j++)
......@@ -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 @@
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);
mt19937 rng(seed);
for(int r=0; r<runs; r++)
{
Graph graph(n, k, maxPeer, rng);
graph.KillMachines(alivePercent);
int minCut = graph.GetMinCut();
if(results.minKConnexity == -1 || results.minKConnexity > minCut)
results.minKConnexity = minCut;
results.UpdateArity(graph);
// 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];
graph.GetDistancesFrom(i, distance);
results.UpdateDistance(distance, graph.size);
}
}*/
}
results.Finalise();
......@@ -34,24 +38,25 @@ int main(int argc, char** argv)
FILE* output = fopen(outName, "wt");
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;
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(float a=0.05; a<1; a+=0.05)
{
outputStrings.push_back(async(launch::async, [rng, n, k, a]()
{
Results results = Simulate(rng, n, k, 3*k, 10000, a, 100);
ostringstream out;
out << n << "," << k << "," << 3*k << "," << results.avgDistance << ","
<< results.disconnected << "," << results.disconnectionProba << ","
<< results.maxDistanceReached << "," << results.arityDistrib[3*k]
<< endl;
return out.str();
}));
}
for(float a=1; a<=1; a+=0.05)
{
int seed = rng();
outputStrings.push_back(async(launch::async, [seed, n, k, a]()
{
Results results = Simulate(seed, n, k, 3*k, 10000, a, 1);
ostringstream out;
out << n << "," << k << "," << a << "," << 3*k << "," << results.avgDistance << ","
<< results.disconnected << "," << results.disconnectionProba << ","
<< results.maxDistanceReached << "," << results.arityDistrib[3*k] << "," << results.minKConnexity
<< endl;
return out.str();
}));
}
cout << "Launching finished" << endl;
......
......@@ -3,22 +3,52 @@
#include <random>
#include <queue>
#include <set>
#include <unordered_set>
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
{
public:
Graph(int size, int k, int maxPeers, mt19937 rng);
Graph(int size, int k, int maxPeers, mt19937& rng);
~Graph() { delete[] adjacency; };
void GetDistancesFrom(int node, int* distance);
void KillMachines(float proportion);
int GetMinCut();
//void SplitAS(float proportionAS1, float proportionAS2);
vector<int>* adjacency;
int size;
private:
int GetMinCut(MinCutGraph& graph);
uniform_int_distribution<int> distrib;
mt19937& generator;
};
class Results
......@@ -35,6 +65,7 @@ public:
double* distanceDistrib;
double avgDistance;
int maxDistanceReached;
int minKConnexity;
double disconnectionProba;
double arityTooBig;
......@@ -47,6 +78,7 @@ public:
private:
void AddAritySample(int arity);
void AddDistanceSample(int distance);
int64_t nAritySample;
int64_t nDistanceSample;
};
......@@ -17,6 +17,7 @@ Results::Results(int maxArity, int maxDistance) :
distanceTooBig = 0;
disconnected = 0;
avgDistance = 0;
minKConnexity = -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