source: src/main/java/weka/classifiers/trees/adtree/TwoWayNominalSplit.java @ 7

Last change on this file since 7 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 6.5 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 *    TwoWayNominalSplit.java
19 *    Copyright (C) 2001 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.classifiers.trees.adtree;
24
25import weka.core.Attribute;
26import weka.core.Instance;
27import weka.core.Instances;
28import weka.core.RevisionUtils;
29
30import java.util.Enumeration;
31
32/**
33 * Class representing a two-way split on a nominal attribute, of the form:
34 * either 'is some_value' or 'is not some_value'.
35 *
36 * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
37 * @version $Revision: 1.6 $
38 */
39public class TwoWayNominalSplit
40  extends Splitter {
41
42  /** for serialization */
43  private static final long serialVersionUID = -4598366190152721355L;
44
45  /** The index of the attribute the split depends on */
46  private int attIndex;
47
48  /** The attribute value that is compared against */
49  private int trueSplitValue;
50
51  /** The children of this split */
52  private PredictionNode[] children;
53
54  /**
55   * Creates a new two-way nominal splitter.
56   *
57   * @param _attIndex the index of the attribute this split depeneds on
58   * @param _trueSplitValue the attribute value that the splitter splits on
59   */
60  public TwoWayNominalSplit(int _attIndex, int _trueSplitValue) {
61
62    attIndex = _attIndex; trueSplitValue = _trueSplitValue;
63    children = new PredictionNode[2];
64  }
65
66  /**
67   * Gets the number of branches of the split.
68   *
69   * @return the number of branches (always = 2)
70   */
71  public int getNumOfBranches() { 
72 
73    return 2;
74  }
75
76  /**
77   * Gets the index of the branch that an instance applies to. Returns -1 if no branches
78   * apply.
79   *
80   * @param inst the instance
81   * @return the branch index
82   */
83  public int branchInstanceGoesDown(Instance inst) {
84   
85    if (inst.isMissing(attIndex)) return -1;
86    else if (inst.value(attIndex) == trueSplitValue) return 0;
87    else return 1;
88  }
89
90  /**
91   * Gets the subset of instances that apply to a particluar branch of the split. If the
92   * branch index is -1, the subset will consist of those instances that don't apply to
93   * any branch.
94   *
95   * @param branch the index of the branch
96   * @param instances the instances from which to find the subset
97   * @return the set of instances that apply
98   */
99  public ReferenceInstances instancesDownBranch(int branch, Instances instances) {
100   
101    ReferenceInstances filteredInstances = new ReferenceInstances(instances, 1);
102    if (branch == -1) {
103      for (Enumeration e = instances.enumerateInstances(); e.hasMoreElements(); ) {
104        Instance inst = (Instance) e.nextElement();
105        if (inst.isMissing(attIndex)) filteredInstances.addReference(inst);
106      }
107    } else if (branch == 0) {
108      for (Enumeration e = instances.enumerateInstances(); e.hasMoreElements(); ) {
109        Instance inst = (Instance) e.nextElement();
110        if (!inst.isMissing(attIndex) && inst.value(attIndex) == trueSplitValue)
111          filteredInstances.addReference(inst);
112      }
113    } else {
114      for (Enumeration e = instances.enumerateInstances(); e.hasMoreElements(); ) {
115        Instance inst = (Instance) e.nextElement();
116        if (!inst.isMissing(attIndex) && inst.value(attIndex) != trueSplitValue)
117          filteredInstances.addReference(inst);
118      }
119    }
120    return filteredInstances;
121  }
122
123  /**
124   * Gets the string describing the attributes the split depends on.
125   * i.e. the left hand side of the description of the split.
126   *
127   * @param dataset the dataset that the split is based on
128   * @return a string describing the attributes
129   */ 
130  public String attributeString(Instances dataset) {
131   
132    return dataset.attribute(attIndex).name();
133  }
134
135  /**
136   * Gets the string describing the comparision the split depends on for a particular
137   * branch. i.e. the right hand side of the description of the split.
138   *
139   * @param branchNum the branch of the split
140   * @param dataset the dataset that the split is based on
141   * @return a string describing the comparison
142   */
143  public String comparisonString(int branchNum, Instances dataset) {
144
145    Attribute att = dataset.attribute(attIndex);
146    if (att.numValues() != 2) 
147      return ((branchNum == 0 ? "= " : "!= ") + att.value(trueSplitValue));
148    else return ("= " + (branchNum == 0 ?
149                         att.value(trueSplitValue) :
150                         att.value(trueSplitValue == 0 ? 1 : 0)));
151  }
152
153  /**
154   * Tests whether two splitters are equivalent.
155   *
156   * @param compare the splitter to compare with
157   * @return whether or not they match
158   */
159  public boolean equalTo(Splitter compare) {
160
161    if (compare instanceof TwoWayNominalSplit) { // test object type
162      TwoWayNominalSplit compareSame = (TwoWayNominalSplit) compare;
163      return (attIndex == compareSame.attIndex &&
164              trueSplitValue == compareSame.trueSplitValue);
165    } else return false;
166  }
167
168  /**
169   * Sets the child for a branch of the split.
170   *
171   * @param branchNum the branch to set the child for
172   * @param childPredictor the new child
173   */
174  public void setChildForBranch(int branchNum, PredictionNode childPredictor) {
175
176    children[branchNum] = childPredictor;
177  }
178
179  /**
180   * Gets the child for a branch of the split.
181   *
182   * @param branchNum the branch to get the child for
183   * @return the child
184   */
185  public PredictionNode getChildForBranch(int branchNum) {
186
187    return children[branchNum];
188  }
189
190  /**
191   * Clones this node. Performs a deep copy, recursing through the tree.
192   *
193   * @return a clone
194   */
195  public Object clone() {
196
197    TwoWayNominalSplit clone = new TwoWayNominalSplit(attIndex, trueSplitValue);
198    clone.orderAdded = orderAdded;
199    if (children[0] != null)
200      clone.setChildForBranch(0, (PredictionNode) children[0].clone());
201    if (children[1] != null)
202      clone.setChildForBranch(1, (PredictionNode) children[1].clone());
203    return clone;
204  }
205 
206  /**
207   * Returns the revision string.
208   *
209   * @return            the revision
210   */
211  public String getRevision() {
212    return RevisionUtils.extract("$Revision: 1.6 $");
213  }
214}
Note: See TracBrowser for help on using the repository browser.