#include "switchchain.hpp" #include "exports.hpp" #include "graph.hpp" #include "graph_ccm.hpp" #include "graph_powerlaw.hpp" #include "graph_spectrum.hpp" #include #include #include #include #include #include #include void getTriangleDegrees(const Graph& g) { std::vector> trids; const auto& adj = g.getAdj(); int triangles = 0; for (auto& v : adj) { for (unsigned int i = 0; i < v.size(); ++i) { for (unsigned int j = i + 1; j < v.size(); ++j) { if (g.hasEdge({v[i], v[j]})) { ++triangles; std::array ds = {{v.size(), adj[v[i]].size(), adj[v[j]].size()}}; std::sort(ds.begin(), ds.end()); trids.push_back(ds); } } } } assert(triangles % 3 == 0); return; } int main(int argc, char* argv[]) { // Generate a random degree sequence std::mt19937 rng(std::random_device{}()); // Goal: // Degrees follow a power-law distribution with some parameter tau // Expect: #tri = const * n^{ something } // The goal is to find the 'something' by finding the number of triangles // for different values of n and tau float tauValues[] = {2.1f, 2.2f, 2.3f, 2.4f, 2.5f, 2.6f, 2.7f, 2.8f, 2.9f}; Graph g; Graph g1; Graph g2; std::ofstream outfile; if (argc >= 2) outfile.open(argv[1]); else outfile.open("graphdata.m"); if (!outfile.is_open()) { std::cout << "ERROR: Could not open output file.\n"; return 1; } outfile << '{'; bool outputComma = false; for (int numVertices = 500; numVertices <= 500; numVertices += 1000) { for (float tau : tauValues) { // For a single n,tau take samples over several instances of // the degree distribution. for (int degreeSample = 0; degreeSample < 5; ++degreeSample) { DegreeSequence ds; generatePowerlawGraph(numVertices, tau, g, ds, rng); #if 0 // // Test the GCM1 and GCM2 success rate // std::vector greedyTriangles1; std::vector greedyTriangles2; int successrate1 = 0; int successrate2 = 0; for (int i = 0; i < 100; ++i) { Graph gtemp; // Take new highest degree every time if (greedyConfigurationModel(ds, gtemp, rng, false)) { ++successrate1; greedyTriangles1.push_back(gtemp.countTriangles()); g1 = gtemp; } // Finish all pairings of highest degree first if (greedyConfigurationModel(ds, gtemp, rng, true)) { ++successrate2; greedyTriangles2.push_back(gtemp.countTriangles()); g2 = gtemp; } } #endif for (int i = 1; i < 5; ++i) { SwitchChain chain; if (!chain.initialize(g)) { std::cerr << "Could not initialize Markov chain.\n"; return 1; } std::cout << "Running n = " << numVertices << ", tau = " << tau << ". \t" << std::flush; //int mixingTime = (32.0f - 26.0f*(tau - 2.0f)) * numVertices; //40000; //constexpr int measurements = 50; //constexpr int measureSkip = // 200; // Take a sample every ... steps int mixingTime = 0; constexpr int measurements = 50000; constexpr int measureSkip = 1; int movesTotal = 0; int movesSuccess = 0; int triangles[measurements]; for (int i = 0; i < mixingTime; ++i) { ++movesTotal; if (chain.doMove()) { ++movesSuccess; } } std::vector successRates; successRates.reserve(measurements * measureSkip); int successrate = 0; for (int i = 0; i < measurements; ++i) { for (int j = 0; j < measureSkip; ++j) { ++movesTotal; if (chain.doMove()) { ++movesSuccess; ++successrate; } } triangles[i] = chain.g.countTriangles(); if ((i+1) % 100 == 0) { successRates.push_back(successrate); successrate = 0; } } std::cout << '(' << 100.0f * float(movesSuccess) / float(movesTotal) << "% successrate). " << std::flush; // std::cout << std::endl; if (outputComma) outfile << ',' << '\n'; outputComma = true; std::sort(ds.begin(), ds.end()); outfile << '{' << '{' << numVertices << ',' << tau << '}'; outfile << ',' << triangles; outfile << ',' << ds; #if 0 outfile << ',' << greedyTriangles1; outfile << ',' << greedyTriangles2; SwitchChain chain1, chain2; if (chain1.initialize(g1)) { movesDone = 0; SwitchChain& c = chain1; for (int i = 0; i < mixingTime; ++i) { if (c.doMove()) ++movesDone; } for (int i = 0; i < measurements; ++i) { for (int j = 0; j < measureSkip; ++j) if (c.doMove()) ++movesDone; triangles[i] = c.g.countTriangles(); } std::cout << movesDone << '/' << mixingTime + measurements * measureSkip << " moves succeeded (" << 100.0f * float(movesDone) / float(mixingTime + measurements * measureSkip) << "%)."; outfile << ',' << triangles; } if (chain2.initialize(g2)) { movesDone = 0; SwitchChain& c = chain2; for (int i = 0; i < mixingTime; ++i) { if (c.doMove()) ++movesDone; } for (int i = 0; i < measurements; ++i) { for (int j = 0; j < measureSkip; ++j) if (c.doMove()) ++movesDone; triangles[i] = c.g.countTriangles(); } std::cout << movesDone << '/' << mixingTime + measurements * measureSkip << " moves succeeded (" << 100.0f * float(movesDone) / float(mixingTime + measurements * measureSkip) << "%)."; outfile << ',' << triangles; } #endif outfile << ',' << successRates; outfile << '}' << std::flush; std::cout << std::endl; } } } } outfile << '}'; return 0; }