Files @ 56cc6fa35193
Branch filter:

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

Tom Bannink
Add initial spectrum computation file
32c10aa21482
c039c549918d
c039c549918d
32c10aa21482
b8a998539881
32c10aa21482
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
bfca8e3039c5
2c2c8fc81176
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
9df034849ada
9df034849ada
257995a65b71
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
6218fdc51593
6218fdc51593
6218fdc51593
6218fdc51593
6218fdc51593
6218fdc51593
6218fdc51593
6218fdc51593
5da240b7cac5
bfca8e3039c5
6218fdc51593
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
bfca8e3039c5
c039c549918d
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_spectrum.hpp"
#include "powerlaw.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) {

            DegreeSequence ds(numVertices);
            powerlaw_distribution degDist(tau, 1, numVertices);
            //std::poisson_distribution<> degDist(12);

            // For a single n,tau take samples over several instances of
            // the degree distribution.
            // 500 samples seems to give reasonable results
            for (int degreeSample = 0; degreeSample < 5; ++degreeSample) {
                // Generate a graph
                // might require multiple tries
                for (int i = 1; ; ++i) {
                    std::generate(ds.begin(), ds.end(),
                                  [&degDist, &rng] { return degDist(rng); });
                    // First make the sum even
                    unsigned int sum = std::accumulate(ds.begin(), ds.end(), 0);
                    if (sum % 2) {
                        continue;
                        // Can we do this: ??
                        ds.back()++;
                    }

                    if (g.createFromDegreeSequence(ds))
                        break;

                    // When 10 tries have not worked, output a warning
                    if (i % 10 == 0) {
                        std::cerr << "Warning: could not create graph from "
                                     "degree sequence. Trying again...\n";
                    }
                }

#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;
}