/*
 *
 */

#include <networkit/community/PartitionFragmentation.hpp>
#include <networkit/community/PartitionIntersection.hpp>
#include <networkit/components/ConnectedComponents.hpp>
#include <networkit/auxiliary/SignalHandling.hpp>

void NetworKit::PartitionFragmentation::run() {
    hasRun = false;

    Aux::SignalHandler handler;

    ConnectedComponents cc(G);
    cc.run();

    handler.assureRunning();

    Partition ccP = cc.getPartition();

    handler.assureRunning();

    Partition ints = PartitionIntersection().calculate(P, ccP);

    handler.assureRunning();

    std::vector<count> intsSizes(ints.upperBound());
    std::vector<count> PSizes(P.upperBound());

    handler.assureRunning();

    G.forNodes([&](node u) {
        ++intsSizes[ints[u]];
        ++PSizes[P[u]];
    });

    handler.assureRunning();

    values.clear();
    values.resize(P.upperBound(), std::numeric_limits< double >::max());

    handler.assureRunning();

    G.forNodes([&](node u) {
        values[P[u]] = std::min(values[P[u]], 1.0 - intsSizes[ints[u]] * 1.0 / PSizes[P[u]]);
    });

    handler.assureRunning();

    maximumValue = 0.0;
    minimumValue = std::numeric_limits<double>::max();
    unweightedAverage = 0.0;
    weightedAverage = 0.0;

    count numSubsets = 0;

    for (index i = 0; i < P.upperBound(); ++i) {
        if (values[i] < std::numeric_limits< double >::max()) {
            maximumValue = std::max(values[i], maximumValue);
            minimumValue = std::min(values[i], minimumValue);
            unweightedAverage += values[i];
            weightedAverage += values[i] * PSizes[i];

            ++numSubsets;
        }
    }

    handler.assureRunning();

    unweightedAverage /= numSubsets;
    weightedAverage /= G.numberOfNodes();

    hasRun = true;
}

