Files @ 32a7f1c13790
Branch filter:

Location: AENC/switchchain/cpp/switchchain.cpp - annotation

Tom Bannink
Add cannonical powerlaw ds
32c10aa21482
c039c549918d
c039c549918d
32c10aa21482
c9c22e41130d
b8a998539881
7bef7b203f4e
28b33414825e
a79267af1717
446bcd991614
446bcd991614
446bcd991614
446bcd991614
446bcd991614
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
257995a65b71
257995a65b71
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
28b33414825e
257995a65b71
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
c039c549918d
c039c549918d
c039c549918d
c039c549918d
c039c549918d
9905828198ec
c039c549918d
a79267af1717
9df034849ada
5da240b7cac5
0f3a4ccb62ea
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
c039c549918d
c039c549918d
c039c549918d
257995a65b71
bfca8e3039c5
bfca8e3039c5
9df034849ada
257995a65b71
c9c22e41130d
c9c22e41130d
0f3a4ccb62ea
257995a65b71
5da240b7cac5
9df034849ada
5da240b7cac5
9df034849ada
9df034849ada
9df034849ada
9df034849ada
5da240b7cac5
9df034849ada
fda8425fac05
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
fda8425fac05
9df034849ada
9df034849ada
9df034849ada
9df034849ada
5da240b7cac5
5da240b7cac5
257995a65b71
257995a65b71
257995a65b71
5da240b7cac5
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
7bef7b203f4e
0290e63ba024
0290e63ba024
446bcd991614
5da240b7cac5
5da240b7cac5
5da240b7cac5
5da240b7cac5
5da240b7cac5
fda8425fac05
5da240b7cac5
5da240b7cac5
5da240b7cac5
257995a65b71
257995a65b71
c039c549918d
bfca8e3039c5
446bcd991614
bfca8e3039c5
257995a65b71
257995a65b71
257995a65b71
257995a65b71
bfca8e3039c5
257995a65b71
257995a65b71
257995a65b71
257995a65b71
efc6996e97a2
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
efc6996e97a2
257995a65b71
257995a65b71
257995a65b71
257995a65b71
257995a65b71
bfca8e3039c5
c039c549918d
257995a65b71
257995a65b71
257995a65b71
257995a65b71
446bcd991614
bfca8e3039c5
59e3e241c8ea
bfca8e3039c5
c039c549918d
bfca8e3039c5
bfca8e3039c5
9df034849ada
9df034849ada
257995a65b71
9df034849ada
9df034849ada
9df034849ada
257995a65b71
257995a65b71
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
257995a65b71
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
9df034849ada
257995a65b71
257995a65b71
257995a65b71
9df034849ada
9df034849ada
9df034849ada
9df034849ada
257995a65b71
bfca8e3039c5
c039c549918d
c039c549918d
c039c549918d
446bcd991614
446bcd991614
#include "switchchain.hpp"
#include "exports.hpp"
#include "graph.hpp"
#include "graph_gcm.hpp"
#include "graph_powerlaw.hpp"
#include "graph_spectrum.hpp"
#include <algorithm>
#include <array>
#include <fstream>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>

void getTriangleDegrees(const Graph& g) {
    std::vector<std::array<std::size_t,3>> 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<std::size_t, 3> 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<int> greedyTriangles1;
                std::vector<int> 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<int> 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;
}