// Copyright 2015 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.cpdp.training; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import weka.core.Instance; import de.ugoe.cs.cpdp.training.WekaLocalFQTraining.QuadTreePayload; /** *
* QuadTree implementation. *
** QuadTree gets a list of instances and then recursively split them into 4 children For this it * uses the median of the 2 values x,y. *
* * @author Alexander Trautsch */ public class QuadTree { /** * 1 parent or null */ private QuadTree parent = null; /** * north-west quadrant */ private QuadTree child_nw; /** * north-east quadrant */ private QuadTree child_ne; /** * south-east quadrant */ private QuadTree child_se; /** * south-west quadrant */ private QuadTree child_sw; /** * helper list for child quadrant generation */ private ArrayList* Constructor. Creates a new QuadTree. *
* * @param parent * parent of this tree * @param payload * data within the quadrant */ public QuadTree(QuadTree parent, ArrayList* Returns the payload, used for clustering in the clustering list we only have children with * payload *
* * @return payload the payload */ public ArrayList* Calculate the density of this quadrant as *
* sets the size coordinates of the quadrant *
* * @param x * x-dimension * @param y * y-dimension */ public void setSize(double[] x, double[] y) { this.x = x; this.y = y; } /** ** returns the size of the quadrant *
* * @return size of the current quadrant */ public double[][] getSize() { return new double[][] { this.x, this.y }; } /** ** returns the size of the quadrant *
* * @return size of the current quadrant */ public Double[][] getSizeDouble() { Double[] tmpX = new Double[2]; Double[] tmpY = new Double[2]; tmpX[0] = this.x[0]; tmpX[1] = this.x[1]; tmpY[0] = this.y[0]; tmpY[1] = this.y[1]; return new Double[][] { tmpX, tmpY }; } /** ** calculates the median for the x axis *
* * @return median for x */ private double getMedianForX() { double med_x = 0; Collections.sort(this.payload, new Comparator* calculates the median for the y axis *
* * @return median for y */ private double getMedianForY() { double med_y = 0; Collections.sort(this.payload, new Comparator* Returns the number of instances in the payload *
* * @return number of instances */ public int getNumbers() { int number = 0; if (this.payload != null) { number = this.payload.size(); } return number; } /** ** Calculate median values of payload for x, y and split into 4 sectors *
* * @return Array of QuadTree nodes (4 childs) * @throws Exception * if we would run into an recursive loop */ public QuadTree[] split() throws Exception { double medx = this.getMedianForX(); double medy = this.getMedianForY(); // Payload lists for each child ArrayList* creates the children of a QuadTree and recursively splits them as well *
* * @param q * tree that is split */ public static void recursiveSplit(QuadTree q) { if (QuadTree.verbose) { System.out.println("splitting: " + q); } if (q.getNumbers() < QuadTree.alpha) { return; } else { // exception is thrown if we would run into an endless loop (see comments in split()) try { QuadTree[] childs = q.split(); recursiveSplit(childs[0]); recursiveSplit(childs[1]); recursiveSplit(childs[2]); recursiveSplit(childs[3]); } catch (Exception e) { return; } } } /** ** returns an list of children sorted by density *
* * @param q * QuadTree */ private void generateList(QuadTree q) { // we only have all childs or none at all if (q.child_ne == null) { this.l.add(q); } if (q.child_ne != null) { this.generateList(q.child_ne); } if (q.child_nw != null) { this.generateList(q.child_nw); } if (q.child_se != null) { this.generateList(q.child_se); } if (q.child_sw != null) { this.generateList(q.child_sw); } } /** ** Checks if passed QuadTree is neighboring to us *
* * @param q * QuadTree * @return true if passed QuadTree is a neighbor */ public boolean isNeighbour(QuadTree q) { boolean is_neighbour = false; double[][] our_size = this.getSize(); double[][] new_size = q.getSize(); // X is i=0, Y is i=1 for (int i = 0; i < 2; i++) { // we are smaller than q // -------------- q // ------- we if (our_size[i][0] >= new_size[i][0] && our_size[i][1] <= new_size[i][1]) { is_neighbour = true; } // we overlap with q at some point // a) ---------------q // ----------- we // b) --------- q // --------- we if ((our_size[i][0] >= new_size[i][0] && our_size[i][0] <= new_size[i][1]) || (our_size[i][1] >= new_size[i][0] && our_size[i][1] <= new_size[i][1])) { is_neighbour = true; } // we are larger than q // ---- q // ---------- we if (our_size[i][1] >= new_size[i][1] && our_size[i][0] <= new_size[i][0]) { is_neighbour = true; } } if (is_neighbour && QuadTree.verbose) { System.out.println(this + " neighbour of: " + q); } return is_neighbour; } /** ** Perform pruning and clustering of the quadtree *
** Pruning according to: Tim Menzies, Andrew Butcher, David Cok, Andrian Marcus, Lucas Layman, * Forrest Shull, Burak Turhan, Thomas Zimmermann, * "Local versus Global Lessons for Defect Prediction and Effort Estimation," IEEE Transactions * on Software Engineering, vol. 39, no. 6, pp. 822-834, June, 2013 *
** debugging function that prints information about the QuadTree *
* */ public void printInfo() { System.out.println("we have " + ccluster.size() + " clusters"); for (int i = 0; i < ccluster.size(); i++) { System.out.println("cluster: " + i + " size: " + ccluster.get(i).size()); } } /** ** Helper Method to get a sorted list (by density) for all children *
* * @param q * QuadTree * @return Sorted ArrayList of quadtrees */ public ArrayList