/*
 * RandMeasure.cpp
 *
 *  Created on: 19.01.2013
 *      Author: Christian Staudt (christian.staudt@kit.edu)
 */

#include <networkit/community/NodeStructuralRandMeasure.hpp>
#include <networkit/community/PartitionIntersection.hpp>

namespace NetworKit {


double NodeStructuralRandMeasure::getDissimilarity(const Graph& G, const Partition& zeta, const Partition& eta) {
    Partition intersection = PartitionIntersection().calculate(zeta, eta);

    std::vector<count> size_zeta(zeta.upperBound(), 0);
    std::vector<count> size_eta(eta.upperBound(), 0);
    std::vector<count> size_intersection(intersection.upperBound(), 0);

    // precompute sizes for each cluster
    G.forNodes([&](node u){
        index C = zeta[u];
        index D = eta[u];
        index I = intersection[u];
        assert (C != none);
        assert (D != none);
        assert (I != none);
        size_zeta[C] += 1;
        size_eta[D] += 1;
        size_intersection[I] += 1;
    });


    count sumIntersection = 0;
    for (count s : size_intersection) {
        sumIntersection += s * (s - 1) / 2;
    }

    count sumZeta = 0;
    for (count s : size_zeta) {
        sumZeta += s * (s - 1) / 2;
    }

    count sumEta = 0;
    for (count s : size_eta) {
        sumEta += s * (s - 1) / 2;
    }

    count n = G.numberOfNodes();

    count A = n * (n-1) / 2 + 2 * sumIntersection - (sumZeta + sumEta);

    double rand = 1 - ((2 * A) * 1.0 / (n * (n-1)));

    // assert range [0, 1]
    assert (rand <= 1.0);
    assert (rand >= 0.0);
    return rand;
}

} /* namespace NetworKit */
