package rank;

import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
import it.unimi.dsi.webgraph.labelling.ArcLabelledNodeIterator.LabelledArcIterator;

public class Cluster {
		
	private IntRBTreeSet set;

	private double volume;
	private double cutSize;

	private WeightedImmutableGraph g;
	private double alpha;

	/* Fitness score:
	 * 
	 *   f(G) = K_in(G) / (K_in(G) + K_out(G))^alpha
	 * 
	 * The parameter 'alpha' tunes the resolution of the method.
	 */
	public Cluster(WeightedImmutableGraph g, double alpha) {
		this.g = g;
		this.alpha = alpha;
		set = new IntRBTreeSet();
		volume = cutSize = 0.0;
	}

	public void add(int u) {
		LabelledArcIterator iter = g.successors(u);
		int v = iter.nextInt();
		
		while (v >= 0) {
			double w = Float.intBitsToFloat(iter.label().getInt());
			
			volume += w;
			
			if (set.contains(v))
				cutSize -= w;
			else
				cutSize += w;
			
			v = iter.nextInt();
		}

		set.add(u);
	}
	
	public double getScore() {
		return (Math.min(volume, g.numArcs() - volume) - cutSize) / Math.pow(Math.min(volume, g.numArcs() - volume), alpha);
	}

	public double getVolume() {
		return volume;
	}
	
	public double getCutSize() {
		return cutSize;
	}
	
	public IntRBTreeSet getElements() {
		return set;
	}
}
