/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package tr.gov.ulakbim.jDenetX.clusterers; import tr.gov.ulakbim.jDenetX.cluster.Clustering; import tr.gov.ulakbim.jDenetX.cluster.SphereCluster; import tr.gov.ulakbim.jDenetX.core.Measurement; import tr.gov.ulakbim.jDenetX.gui.visualization.DataPoint; import tr.gov.ulakbim.jDenetX.options.FloatOption; import tr.gov.ulakbim.jDenetX.options.IntOption; import weka.core.Instance; import java.util.ArrayList; import java.util.Arrays; import java.util.Random; /** * @author jansen */ public class ClusterGenerator extends AbstractClusterer { public IntOption timeWindowOption = new IntOption("timeWindow", 't', "Rang of the window.", 1000); public FloatOption radiusDecreaseOption = new FloatOption("radiusDecrease", 'r', "The average radii of the centroids in the model.", 0, 0, 1); public FloatOption radiusIncreaseOption = new FloatOption("radiusIncrease", 'R', "The average radii of the centroids in the model.", 0, 0, 1); public FloatOption positionOffsetOption = new FloatOption("positionOffset", 'p', "The average radii of the centroids in the model.", 0, 0, 1); // public FloatOption microclusterOverlapOption = new FloatOption("microclusterOverlap", 'o', // "Allowed overlap of microclusters", 0.5, 0.0001, 1); private static double err_intervall_width = 0.0; private ArrayList<DataPoint> points; private int instanceCounter; private int windowCounter; private Random random; private double overlapThreshold; private int microInitMinPoints = 5; private Clustering sourceClustering = null; @Override public void resetLearningImpl() { points = new ArrayList<DataPoint>(); instanceCounter = 0; windowCounter = 0; random = new Random(227); // overlapThreshold = microclusterOverlapOption.getValue(); //evaluateMicroClusteringOption.set(); } @Override public void trainOnInstanceImpl(Instance inst) { if (windowCounter >= timeWindowOption.getValue()) { points.clear(); windowCounter = 0; } windowCounter++; instanceCounter++; points.add(new DataPoint(inst, instanceCounter)); } @Override public boolean implementsMicroClusterer() { return true; } public void setSourceClustering(Clustering source) { sourceClustering = source; } @Override public Clustering getMicroClusteringResult() { //System.out.println("Numcluster:"+clustering.size()+" / "+num); //Clustering source_clustering = new Clustering(points, overlapThreshold, microInitMinPoints); if (sourceClustering == null) { System.out.println("You need to set a source clustering for the ClusterGenerator to work"); return null; } return alterClustering(sourceClustering); } public Clustering getClusteringResult() { sourceClustering = new Clustering(points); // if(sourceClustering == null){ // System.out.println("You need to set a source clustering for the ClusterGenerator to work"); // return null; // } return alterClustering(sourceClustering); } private Clustering alterClustering(Clustering scclustering) { //percentage of the radius that will be cut off //0: no changes to radius //1: radius of 0 double errLevelRadiusDecrease = radiusDecreaseOption.getValue(); //0: no changes to radius //1: radius 100% bigger double errLevelRadiusIncrease = radiusIncreaseOption.getValue(); //0: no changes //1: distance between centers is 2 * original radius double errLevelPosition = positionOffsetOption.getValue(); int numCluster = scclustering.size(); double[] err_seeds = new double[numCluster]; double err_seed_sum = 0.0; double tmp_seed; for (int i = 0; i < numCluster; i++) { tmp_seed = random.nextDouble(); err_seeds[i] = err_seed_sum + tmp_seed; err_seed_sum += tmp_seed; } double sumWeight = 0; for (int i = 0; i < numCluster; i++) { sumWeight += scclustering.get(i).getWeight(); } Clustering clustering = new Clustering(); for (int i = 0; i < numCluster; i++) { if (!(scclustering.get(i) instanceof SphereCluster)) { System.out.println("Not a Sphere Cluster"); continue; } SphereCluster sourceCluster = (SphereCluster) scclustering.get(i); double[] center = Arrays.copyOf(sourceCluster.getCenter(), sourceCluster.getCenter().length); double weight = sourceCluster.getWeight(); double radius = sourceCluster.getRadius(); //move cluster center if (errLevelPosition > 0) { double errOffset = random.nextDouble() * err_intervall_width / 2.0; double errOffsetDirection = ((random.nextBoolean()) ? 1 : -1); double level = errLevelPosition + errOffsetDirection * errOffset; double[] vector = new double[center.length]; double vectorLength = 0; for (int d = 0; d < center.length; d++) { vector[d] = (random.nextBoolean() ? 1 : -1) * random.nextDouble(); vectorLength += Math.pow(vector[d], 2); } vectorLength = Math.sqrt(vectorLength); //max is when clusters are next to each other double length = 2 * radius * level; for (int d = 0; d < center.length; d++) { //normalize length and then strecht to reach error position vector[d] = vector[d] / vectorLength * length; } // System.out.println("Center "+Arrays.toString(center)); // System.out.println("Vector "+Arrays.toString(vector)); //check if error position is within bounds double[] newCenter = new double[center.length]; for (int d = 0; d < center.length; d++) { //check bounds, otherwise flip vector if (center[d] + vector[d] >= 0 && center[d] + vector[d] <= 1) { newCenter[d] = center[d] + vector[d]; } else { newCenter[d] = center[d] + (-1) * vector[d]; } } center = newCenter; for (int d = 0; d < center.length; d++) { if (newCenter[d] >= 0 && newCenter[d] <= 1) { } else { System.out.println("This shouldnt have happend, Cluster center out of bounds:" + Arrays.toString(newCenter)); } } //System.out.println("new Center "+Arrays.toString(newCenter)); } //alter radius if (errLevelRadiusDecrease > 0 || errLevelRadiusIncrease > 0) { double errOffset = random.nextDouble() * err_intervall_width / 2.0; int errOffsetDirection = ((random.nextBoolean()) ? 1 : -1); if (errLevelRadiusDecrease > 0 && (errLevelRadiusIncrease == 0 || random.nextBoolean())) { double level = (errLevelRadiusDecrease + errOffsetDirection * errOffset);//*sourceCluster.getWeight()/sumWeight; level = (level < 0) ? 0 : level; level = (level > 1) ? 1 : level; radius *= (1 - level); } else { double level = errLevelRadiusIncrease + errOffsetDirection * errOffset; level = (level < 0) ? 0 : level; level = (level > 1) ? 1 : level; radius += radius * level; } } SphereCluster newCluster = new SphereCluster(center, radius, weight); newCluster.setMeasureValue("Source Cluster", "C" + sourceCluster.getId()); clustering.add(newCluster); } return clustering; } @Override protected Measurement[] getModelMeasurementsImpl() { throw new UnsupportedOperationException("Not supported yet."); } @Override public void getModelDescription(StringBuilder out, int indent) { throw new UnsupportedOperationException("Not supported yet."); } public boolean isRandomizable() { return false; } public double[] getVotesForInstance(Instance inst) { throw new UnsupportedOperationException("Not supported yet."); } }