📄 bestfirst.java
字号:
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* BestFirst.java
* Copyright (C) 1999 Mark Hall
*
*/
package weka.attributeSelection;
import java.io.Serializable;
import java.util.BitSet;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import weka.core.FastVector;
import weka.core.Instances;
import weka.core.Option;
import weka.core.OptionHandler;
import weka.core.Range;
import weka.core.SelectedTag;
import weka.core.Tag;
import weka.core.Utils;
/**
* Class for performing a best first search. <p>
*
* Valid options are: <p>
*
* -P <start set> <br>
* Specify a starting set of attributes. Eg 1,4,7-9. <p>
*
* -D <-1 = backward | 0 = bidirectional | 1 = forward> <br>
* Direction of the search. (default = 1). <p>
*
* -N <num> <br>
* Number of non improving nodes to consider before terminating search.
* (default = 5). <p>
*
* -S <num> <br>
* Size of lookup cache for evaluated subsets. Expressed as a multiple
* of the number of attributes in the data set. (default = 1). <p>
*
* @author Mark Hall (mhall@cs.waikato.ac.nz)
* @version $Revision$
*/
public class BestFirst extends ASSearch
implements OptionHandler, StartSetHandler
{
// Inner classes
/**
* Class for a node in a linked list. Used in best first search.
* @author Mark Hall (mhall@cs.waikato.ac.nz)
**/
public class Link2 implements Serializable {
/* BitSet group; */
Object [] m_data;
double m_merit;
// Constructor
public Link2 (Object [] data, double mer) {
// group = (BitSet)gr.clone();
m_data = data;
m_merit = mer;
}
/** Get a group */
public Object [] getData () {
return m_data;
}
public String toString () {
return ("Node: " + m_data.toString() + " " + m_merit);
}
}
/**
* Class for handling a linked list. Used in best first search.
* Extends the Vector class.
* @author Mark Hall (mhall@cs.waikato.ac.nz)
**/
public class LinkedList2
extends FastVector
{
// Max number of elements in the list
int m_MaxSize;
// ================
// Public methods
// ================
public LinkedList2 (int sz) {
super();
m_MaxSize = sz;
}
/**
* removes an element (Link) at a specific index from the list.
* @param index the index of the element to be removed.
**/
public void removeLinkAt (int index)
throws Exception {
if ((index >= 0) && (index < size())) {
removeElementAt(index);
}
else {
throw new Exception("index out of range (removeLinkAt)");
}
}
/**
* returns the element (Link) at a specific index from the list.
* @param index the index of the element to be returned.
**/
public Link2 getLinkAt (int index)
throws Exception {
if (size() == 0) {
throw new Exception("List is empty (getLinkAt)");
}
else {if ((index >= 0) && (index < size())) {
return ((Link2)(elementAt(index)));
}
else {
throw new Exception("index out of range (getLinkAt)");
}
}
}
/**
* adds an element (Link) to the list.
* @param gr the attribute set specification
* @param mer the "merit" of this attribute set
**/
public void addToList (Object [] data, double mer)
throws Exception {
Link2 newL = new Link2(data, mer);
if (size() == 0) {
addElement(newL);
}
else {if (mer > ((Link2)(firstElement())).m_merit) {
if (size() == m_MaxSize) {
removeLinkAt(m_MaxSize - 1);
}
//----------
insertElementAt(newL, 0);
}
else {
int i = 0;
int size = size();
boolean done = false;
//------------
// don't insert if list contains max elements an this
// is worst than the last
if ((size == m_MaxSize) && (mer <= ((Link2)(lastElement())).m_merit)) {
}
//---------------
else {
while ((!done) && (i < size)) {
if (mer > ((Link2)(elementAt(i))).m_merit) {
if (size == m_MaxSize) {
removeLinkAt(m_MaxSize - 1);
}
// ---------------------
insertElementAt(newL, i);
done = true;
}
else {if (i == size - 1) {
addElement(newL);
done = true;
}
else {
i++;
}
}
}
}
}
}
}
}
// member variables
/** maximum number of stale nodes before terminating search */
protected int m_maxStale;
/** 0 == backward search, 1 == forward search, 2 == bidirectional */
protected int m_searchDirection;
/** search directions */
protected static final int SELECTION_BACKWARD = 0;
protected static final int SELECTION_FORWARD = 1;
protected static final int SELECTION_BIDIRECTIONAL = 2;
public static final Tag [] TAGS_SELECTION = {
new Tag(SELECTION_BACKWARD, "Backward"),
new Tag(SELECTION_FORWARD, "Forward"),
new Tag(SELECTION_BIDIRECTIONAL, "Bi-directional"),
};
/** holds an array of starting attributes */
protected int[] m_starting;
/** holds the start set for the search as a Range */
protected Range m_startRange;
/** does the data have a class */
protected boolean m_hasClass;
/** holds the class index */
protected int m_classIndex;
/** number of attributes in the data */
protected int m_numAttribs;
/** total number of subsets evaluated during a search */
protected int m_totalEvals;
/** for debugging */
protected boolean m_debug;
/** holds the merit of the best subset found */
protected double m_bestMerit;
/** holds the maximum size of the lookup cache for evaluated subsets */
protected int m_cacheSize;
/**
* Returns a string describing this search method
* @return a description of the search method suitable for
* displaying in the explorer/experimenter gui
*/
public String globalInfo() {
return "BestFirst:\n\n"
+"Searches the space of attribute subsets by greedy hillclimbing "
+"augmented with a backtracking facility. Setting the number of "
+"consecutive non-improving nodes allowed controls the level of "
+"backtracking done. Best first may start with the empty set of "
+"attributes and search forward, or start with the full set of "
+"attributes and search backward, or start at any point and search "
+"in both directions (by considering all possible single attribute "
+"additions and deletions at a given point).\n";
}
/**
*Constructor
*/
public BestFirst () {
resetOptions();
}
/**
* Returns an enumeration describing the available options.
* @return an enumeration of all the available options.
*
**/
public Enumeration listOptions () {
Vector newVector = new Vector(4);
newVector.addElement(new Option("\tSpecify a starting set of attributes."
+ "\n\tEg. 1,3,5-7."
,"P",1
, "-P <start set>"));
newVector.addElement(new Option("\tDirection of search. (default = 1)."
, "D", 1
, "-D <0 = backward | 1 = forward "
+ "| 2 = bi-directional>"));
newVector.addElement(new Option("\tNumber of non-improving nodes to"
+ "\n\tconsider before terminating search."
, "N", 1, "-N <num>"));
newVector.addElement(new Option("\tSize of lookup cache for evaluated subsets."
+"\n\tExpressed as a multiple of the number of"
+"\n\tattributes in the data set. (default = 1)",
"S", 1, "-S <num>"));
return newVector.elements();
}
/**
* Parses a given list of options.
*
* Valid options are: <p>
*
* -P <start set> <br>
* Specify a starting set of attributes. Eg 1,4,7-9. <p>
*
* -D <-1 = backward | 0 = bidirectional | 1 = forward> <br>
* Direction of the search. (default = 1). <p>
*
* -N <num> <br>
* Number of non improving nodes to consider before terminating search.
* (default = 5). <p>
*
* -S <num> <br>
* Size of lookup cache for evaluated subsets. Expressed as a multiple
* of the number of attributes in the data set. (default = 1). <p>
*
* @param options the list of options as an array of strings
* @exception Exception if an option is not supported
*
**/
public void setOptions (String[] options)
throws Exception {
String optionString;
resetOptions();
optionString = Utils.getOption('P', options);
if (optionString.length() != 0) {
setStartSet(optionString);
}
optionString = Utils.getOption('D', options);
if (optionString.length() != 0) {
setDirection(new SelectedTag(Integer.parseInt(optionString),
TAGS_SELECTION));
} else {
setDirection(new SelectedTag(SELECTION_FORWARD, TAGS_SELECTION));
}
optionString = Utils.getOption('N', options);
if (optionString.length() != 0) {
setSearchTermination(Integer.parseInt(optionString));
}
optionString = Utils.getOption('S', options);
if (optionString.length() != 0) {
setLookupCacheSize(Integer.parseInt(optionString));
}
m_debug = Utils.getFlag('Z', options);
}
/**
* Set the maximum size of the evaluated subset cache (hashtable). This is
* expressed as a multiplier for the number of attributes in the data set.
* (default = 1).
*
* @param size the maximum size of the hashtable
*/
public void setLookupCacheSize(int size) {
if (size >= 0) {
m_cacheSize = size;
}
}
/**
* Return the maximum size of the evaluated subset cache (expressed as a multiplier
* for the number of attributes in a data set.
*
* @return the maximum size of the hashtable.
*/
public int getLookupCacheSize() {
return m_cacheSize;
}
/**
* Returns the tip text for this property
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String lookupCacheSizeTipText() {
return "Set the maximum size of the lookup cache of evaluated subsets. This is "
+"expressed as a multiplier of the number of attributes in the data set. "
+"(default = 1).";
}
/**
* Returns the tip text for this property
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String startSetTipText() {
return "Set the start point for the search. This is specified as a comma "
+"seperated list off attribute indexes starting at 1. It can include "
+"ranges. Eg. 1,2,5-9,17.";
}
/**
* Sets a starting set of attributes for the search. It is the
* search method's responsibility to report this start set (if any)
* in its toString() method.
* @param startSet a string containing a list of attributes (and or ranges),
* eg. 1,2,6,10-15.
* @exception Exception if start set can't be set.
*/
public void setStartSet (String startSet) throws Exception {
m_startRange.setRanges(startSet);
}
/**
* Returns a list of attributes (and or attribute ranges) as a String
* @return a list of attributes (and or attribute ranges)
*/
public String getStartSet () {
return m_startRange.getRanges();
}
/**
* Returns the tip text for this property
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String searchTerminationTipText() {
return "Set the amount of backtracking. Specify the number of ";
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -