#include "exports.hpp" #include "graph.hpp" #include "graph_powerlaw.hpp" #include "graph_spectrum.hpp" #include "switchchain.hpp" #include #include #include #include #include #include int main(int argc, char* argv[]) { // Simulation parameters const int numVerticesMin = 10000; const int numVerticesMax = 10000; const int numVerticesStep = 1000; float tauValues[] = {2.1f, 2.5f, 2.9f}; auto getMixingTime = [](int n, float tau) { return int(100.0f * (50.0f - 5.0f * (tau - 2.0f)) * n); }; auto getMeasurements = [](int n, float tau) { (void)n; (void)tau; return 5000000; }; // Output file std::ofstream outfile; if (argc >= 2) outfile.open(argv[1]); else outfile.open("graphdata_canonical_creationfreqs.m"); if (!outfile.is_open()) { std::cout << "ERROR: Could not open output file.\n"; return 1; } // Output Mathematica-style comment to indicate file contents outfile << "(*\n"; outfile << "n from " << numVerticesMin << " to " << numVerticesMax << " step " << numVerticesStep << std::endl; outfile << "tauValues: " << tauValues << std::endl; outfile << "Canonical degree sequence.\n"; outfile << "mixingTime: 100 * (50 - 5 (tau - 2)) n\n"; outfile << "measurements: 5000000\n"; outfile << "measureSkip: 0\n"; outfile << "histogram is conditioned on successful switches\n"; outfile << "data:\n"; outfile << "1: {n,tau}\n"; outfile << "2: { {delta1, freq1} , {delta2, freq2} , ... }\n"; outfile << "3: {successful switches, total attempted switches}\n"; outfile << "*)" << std::endl; // Mathematica does not accept normal scientific notation outfile << std::fixed; outfile << '{' << '\n'; bool outputComma = false; Graph g; for (int numVertices = numVerticesMin; numVertices <= numVerticesMax; numVertices += numVerticesStep) { for (float tau : tauValues) { DegreeSequence ds; generateCanonicalPowerlawGraph(numVertices, tau, g, ds); SwitchChain chain; if (!chain.initialize(g)) { std::cerr << "Could not initialize Markov chain.\n"; return 1; } std::cout << "Running (n,tau) = (" << numVertices << ',' << tau << "). " << std::flush; // Mix int mixingTime = getMixingTime(numVertices, tau); for (int i = 0; i < mixingTime; ++i) { chain.doMove(); } std::cout << "Mixing done. " << std::flush; int range = 500; // Keep track of [-range, range] std::vector frequencies(2*range+1, 0); // frequencies[x+range] corresponds to frequency of x // clip anything outside of range to range! int prevTriangles = chain.g.countTriangles(); chain.g.getTrackedTriangles() = prevTriangles; int movesDone = 0; int measurements = getMeasurements(numVertices, tau); for (int i = 0; i < measurements; ++i) { if (chain.doMove(true)) { ++movesDone; int newTriangles = chain.g.getTrackedTriangles(); int diff = newTriangles - prevTriangles; prevTriangles = newTriangles; // Add 'diff' to histogram if (diff < -range) diff = -range; else if (diff > range) diff = range; frequencies[diff+range]++; } } std::cout << "Measuring done. " << std::flush; std::vector> histogram; for (int i = -range; i <= range; ++i) { histogram.push_back(std::make_pair(i, frequencies[i + range])); } if (outputComma) outfile << ',' << '\n'; outputComma = true; outfile << '{' << '{' << numVertices << ',' << tau << '}'; outfile << ',' << histogram; outfile << ',' << '{' << movesDone << ',' << measurements << '}'; outfile << '}' << std::flush; std::cout << "Output done." << std::endl; } } outfile << '\n' << '}'; return 0; }