private Clustering alterClustering()

in samoa-api/src/main/java/org/apache/samoa/moa/clusterers/ClusterGenerator.java [119:273]


  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 numRemoveCluster = (int) (clusterRemoveOption.getValue() * scclustering.size());

    int numAddCluster = (int) (clusterAddOption.getValue() * scclustering.size());

    for (int c = 0; c < numRemoveCluster; c++) {
      int delId = random.nextInt(scclustering.size());
      scclustering.remove(delId);
    }

    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
      double err_interval_width = 0.0;
      if (errLevelPosition > 0) {
        double errOffset = random.nextDouble() * err_interval_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) {
            System.out.println("This shouldnt have happend, Cluster center out of bounds:" + Arrays.toString(newCenter));
          }
        }
      }

      // alter radius
      if (errLevelRadiusDecrease > 0 || errLevelRadiusIncrease > 0) {
        double errOffset = random.nextDouble() * err_interval_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);
    }

    if (joinClustersOption.getValue() > 0) {
      clustering = joinClusters(clustering);
    }

    // add new clusters by copying clusters and set a random center
    for (int c = 0; c < numAddCluster; c++) {
      int copyId = random.nextInt(clustering.size());
      SphereCluster scorg = (SphereCluster) clustering.get(copyId);
      int dim = scorg.getCenter().length;
      double[] center = new double[dim];
      double radius = scorg.getRadius();

      boolean outofbounds = true;
      int tryCounter = 0;
      while (outofbounds && tryCounter < 20) {
        tryCounter++;
        outofbounds = false;
        for (int j = 0; j < center.length; j++) {
          center[j] = random.nextDouble();
          if (center[j] - radius < 0 || center[j] + radius > 1) {
            outofbounds = true;
            break;
          }
        }
      }
      if (outofbounds) {
        System.out.println("Coludn't place additional cluster");
      }
      else {
        SphereCluster scnew = new SphereCluster(center, radius, scorg.getWeight() / 2);
        scorg.setWeight(scorg.getWeight() - scnew.getWeight());
        clustering.add(scnew);
      }
    }

    return clustering;

  }