source: tags/MetisMQIDemo/src/main/java/weka/core/neighboursearch/kdtrees/MidPointOfWidestDimension.java

Last change on this file was 29, checked in by gnappo, 15 years ago

Taggata versione per la demo e aggiunto branch.

File size: 7.0 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * MidPointOfWidestDimension.java
19 * Copyright (C) 2007 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.core.neighboursearch.kdtrees;
23
24import weka.core.RevisionUtils;
25import weka.core.TechnicalInformation;
26import weka.core.TechnicalInformationHandler;
27import weka.core.TechnicalInformation.Field;
28import weka.core.TechnicalInformation.Type;
29
30/**
31 <!-- globalinfo-start -->
32 * The class that splits a KDTree node based on the midpoint value of a dimension in which the node's points have the widest spread.<br/>
33 * <br/>
34 * For more information see also:<br/>
35 * <br/>
36 * Andrew Moore (1991). A tutorial on kd-trees.
37 * <p/>
38 <!-- globalinfo-end -->
39 *
40 <!-- technical-bibtex-start -->
41 * BibTeX:
42 * <pre>
43 * &#64;techreport{Moore1991,
44 *    author = {Andrew Moore},
45 *    booktitle = {University of Cambridge Computer Laboratory Technical Report No. 209},
46 *    howpublished = {Extract from PhD Thesis},
47 *    title = {A tutorial on kd-trees},
48 *    year = {1991},
49 *    HTTP = {http://www.autonlab.org/autonweb/14665.html}
50 * }
51 * </pre>
52 * <p/>
53 <!-- technical-bibtex-end -->
54 *
55 <!-- options-start -->
56 <!-- options-end -->
57 *
58 * @author Ashraf M. Kibriya (amk14[at-the-rate]cs[dot]waikato[dot]ac[dot]nz)
59 * @version $Revision: 5953 $
60 */
61public class MidPointOfWidestDimension
62  extends KDTreeNodeSplitter
63  implements TechnicalInformationHandler {
64
65  /** for serialization. */
66  private static final long serialVersionUID = -7617277960046591906L;
67
68  /**
69   * Returns a string describing this nearest neighbour search algorithm.
70   *
71   * @return            a description of the algorithm for displaying in the
72   *                    explorer/experimenter gui
73   */
74  public String globalInfo() {
75    return 
76        "The class that splits a KDTree node based on the midpoint value of "
77      + "a dimension in which the node's points have the widest spread.\n\n"
78      + "For more information see also:\n\n"
79      + getTechnicalInformation().toString();
80  }
81
82  /**
83   * Returns an instance of a TechnicalInformation object, containing detailed
84   * information about the technical background of this class, e.g., paper
85   * reference or book this class is based on.
86   *
87   * @return            the technical information about this class
88   */
89  public TechnicalInformation getTechnicalInformation() {
90    TechnicalInformation result;
91
92    result = new TechnicalInformation(Type.TECHREPORT);
93    result.setValue(Field.AUTHOR, "Andrew Moore");
94    result.setValue(Field.YEAR, "1991");
95    result.setValue(Field.TITLE, "A tutorial on kd-trees");
96    result.setValue(Field.HOWPUBLISHED, "Extract from PhD Thesis");
97    result.setValue(Field.BOOKTITLE, "University of Cambridge Computer Laboratory Technical Report No. 209");
98    result.setValue(Field.HTTP, "http://www.autonlab.org/autonweb/14665.html");
99
100    return result;
101  }
102 
103  /**
104   * Splits a node into two based on the midpoint value of the dimension
105   * in which the points have the widest spread. After splitting two
106   * new nodes are created and correctly initialised. And, node.left
107   * and node.right are set appropriately. 
108   * @param node The node to split.
109   * @param numNodesCreated The number of nodes that so far have been
110   * created for the tree, so that the newly created nodes are
111   * assigned correct/meaningful node numbers/ids.
112   * @param nodeRanges The attributes' range for the points inside
113   * the node that is to be split.
114   * @param universe The attributes' range for the whole
115   * point-space.
116   * @throws Exception If there is some problem in splitting the
117   * given node.
118   */
119  public void splitNode(KDTreeNode node, int numNodesCreated, 
120                        double[][] nodeRanges, double[][] universe) throws Exception {
121   
122    correctlyInitialized();
123
124    int splitDim = widestDim(nodeRanges, universe);
125
126    double splitVal = m_EuclideanDistance.getMiddle(nodeRanges[splitDim]);
127
128    int rightStart = rearrangePoints(m_InstList, node.m_Start, node.m_End,
129        splitDim, splitVal);
130
131    if (rightStart == node.m_Start || rightStart > node.m_End) {
132      if (rightStart == node.m_Start)
133        throw new Exception("Left child is empty in node " 
134                            + node.m_NodeNumber + 
135                            ". Not possible with " + 
136                            "MidPointofWidestDim splitting method. Please " + 
137                            "check code.");
138      else
139        throw new Exception("Right child is empty in node " + node.m_NodeNumber + 
140                            ". Not possible with " + 
141                            "MidPointofWidestDim splitting method. Please " + 
142                            "check code.");
143    }
144   
145    node.m_SplitDim = splitDim;
146    node.m_SplitValue = splitVal;
147    node.m_Left = new KDTreeNode(numNodesCreated + 1, node.m_Start,
148        rightStart - 1, m_EuclideanDistance.initializeRanges(m_InstList,
149            node.m_Start, rightStart - 1));
150    node.m_Right = new KDTreeNode(numNodesCreated + 2, rightStart, node.m_End,
151        m_EuclideanDistance
152            .initializeRanges(m_InstList, rightStart, node.m_End));     
153  }
154 
155  /**
156   * Re-arranges the indices array such that the points <= to the splitVal
157   * are on the left of the array and those > the splitVal are on the right.
158   *
159   * @param indices The master index array.
160   * @param startidx The begining index of portion of indices that needs
161   * re-arranging.
162   * @param endidx The end index of portion of indices that needs
163   * re-arranging.
164   * @param splitDim The split dimension/attribute.
165   * @param splitVal The split value.
166   * @return The startIdx of the points > the splitVal (the points
167   * belonging to the right child of the node).
168   */
169  protected int rearrangePoints(int[] indices, final int startidx, final int endidx,
170                              final int splitDim, final double splitVal) {
171   
172    int tmp, left = startidx - 1;
173    for (int i = startidx; i <= endidx; i++) {
174      if (m_EuclideanDistance.valueIsSmallerEqual(m_Instances
175          .instance(indices[i]), splitDim, splitVal)) {
176        left++;
177        tmp = indices[left];
178        indices[left] = indices[i];
179        indices[i] = tmp;
180      }//end if valueIsSmallerEqual
181    }//end for
182    return left + 1;
183  }
184 
185  /**
186   * Returns the revision string.
187   *
188   * @return            the revision
189   */
190  public String getRevision() {
191    return RevisionUtils.extract("$Revision: 5953 $");
192  }
193}
Note: See TracBrowser for help on using the repository browser.