📄 geneticsearch.java
字号:
}
/**
* 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 seedTipText() {
return "Set the random seed.";
}
/**
* set the seed for random number generation
* @param s seed value
*/
public void setSeed(int s) {
m_seed = s;
}
/**
* get the value of the random number generator's seed
* @return the seed for random number generation
*/
public int getSeed() {
return m_seed;
}
/**
* Returns the tip text for this property
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String reportFrequencyTipText() {
return "Set how frequently reports are generated. Default is equal to "
+"the number of generations meaning that a report will be printed for "
+"initial and final generations. Setting the value to 5 will result in "
+"a report being printed every 5 generations.";
}
/**
* set how often reports are generated
* @param f generate reports every f generations
*/
public void setReportFrequency(int f) {
m_reportFrequency = f;
}
/**
* get how often repports are generated
* @return how often reports are generated
*/
public int getReportFrequency() {
return m_reportFrequency;
}
/**
* Returns the tip text for this property
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String mutationProbTipText() {
return "Set the probability of mutation occuring.";
}
/**
* set the probability of mutation
* @param m the probability for mutation occuring
*/
public void setMutationProb(double m) {
m_pMutation = m;
}
/**
* get the probability of mutation
* @return the probability of mutation occuring
*/
public double getMutationProb() {
return m_pMutation;
}
/**
* Returns the tip text for this property
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String crossoverProbTipText() {
return "Set the probability of crossover. This is the probability that "
+"two population members will exchange genetic material.";
}
/**
* set the probability of crossover
* @param c the probability that two population members will exchange
* genetic material
*/
public void setCrossoverProb(double c) {
m_pCrossover = c;
}
/**
* get the probability of crossover
* @return the probability of crossover
*/
public double getCrossoverProb() {
return m_pCrossover;
}
/**
* Returns the tip text for this property
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String maxGenerationsTipText() {
return "Set the number of generations to evaluate.";
}
/**
* set the number of generations to evaluate
* @param m the number of generations
*/
public void setMaxGenerations(int m) {
m_maxGenerations = m;
}
/**
* get the number of generations
* @return the maximum number of generations
*/
public int getMaxGenerations() {
return m_maxGenerations;
}
/**
* Returns the tip text for this property
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String populationSizeTipText() {
return "Set the population size. This is the number of individuals "
+"(attribute sets) in the population.";
}
/**
* set the population size
* @param p the size of the population
*/
public void setPopulationSize(int p) {
m_popSize = p;
}
/**
* get the size of the population
* @return the population size
*/
public int getPopulationSize() {
return m_popSize;
}
/**
* Returns a string describing this search method
* @return a description of the search suitable for
* displaying in the explorer/experimenter gui
*/
public String globalInfo() {
return "GeneticSearch :\n\nPerforms a search using the simple genetic "
+"algorithm described in Goldberg (1989).\n";
}
/**
* Constructor. Make a new GeneticSearch object
*/
public GeneticSearch() {
resetOptions();
}
/**
* converts the array of starting attributes to a string. This is
* used by getOptions to return the actual attributes specified
* as the starting set. This is better than using m_startRanges.getRanges()
* as the same start set can be specified in different ways from the
* command line---eg 1,2,3 == 1-3. This is to ensure that stuff that
* is stored in a database is comparable.
* @return a comma seperated list of individual attribute numbers as a String
*/
private String startSetToString() {
StringBuffer FString = new StringBuffer();
boolean didPrint;
if (m_starting == null) {
return getStartSet();
}
for (int i = 0; i < m_starting.length; i++) {
didPrint = false;
if ((m_hasClass == false) ||
(m_hasClass == true && i != m_classIndex)) {
FString.append((m_starting[i] + 1));
didPrint = true;
}
if (i == (m_starting.length - 1)) {
FString.append("");
}
else {
if (didPrint) {
FString.append(",");
}
}
}
return FString.toString();
}
/**
* returns a description of the search
* @return a description of the search as a String
*/
public String toString() {
StringBuffer GAString = new StringBuffer();
GAString.append("\tGenetic search.\n\tStart set: ");
if (m_starting == null) {
GAString.append("no attributes\n");
}
else {
GAString.append(startSetToString()+"\n");
}
GAString.append("\tPopulation size: "+m_popSize);
GAString.append("\n\tNumber of generations: "+m_maxGenerations);
GAString.append("\n\tProbability of crossover: "
+Utils.doubleToString(m_pCrossover,6,3));
GAString.append("\n\tProbability of mutation: "
+Utils.doubleToString(m_pMutation,6,3));
GAString.append("\n\tReport frequency: "+m_reportFrequency);
GAString.append("\n\tRandom number seed: "+m_seed+"\n");
GAString.append(m_generationReports.toString());
return GAString.toString();
}
/**
* Searches the attribute subset space using a genetic algorithm.
*
* @param ASEvaluator the attribute evaluator to guide the search
* @param data the training instances.
* @return an array (not necessarily ordered) of selected attribute indexes
* @exception Exception if the search can't be completed
*/
public int[] search (ASEvaluation ASEval, Instances data)
throws Exception {
m_best = null;
m_generationReports = new StringBuffer();
if (!(ASEval instanceof SubsetEvaluator)) {
throw new Exception(ASEval.getClass().getName()
+ " is not a "
+ "Subset evaluator!");
}
if (ASEval instanceof UnsupervisedSubsetEvaluator) {
m_hasClass = false;
}
else {
m_hasClass = true;
m_classIndex = data.classIndex();
}
SubsetEvaluator ASEvaluator = (SubsetEvaluator)ASEval;
m_numAttribs = data.numAttributes();
m_startRange.setUpper(m_numAttribs-1);
if (!(getStartSet().equals(""))) {
m_starting = m_startRange.getSelection();
}
// initial random population
m_lookupTable = new Hashtable(m_lookupTableSize);
m_random = new Random(m_seed);
m_population = new GABitSet [m_popSize];
// set up random initial population
initPopulation();
evaluatePopulation(ASEvaluator);
populationStatistics();
scalePopulation();
checkBest();
m_generationReports.append(populationReport(0));
boolean converged;
for (int i=1;i<=m_maxGenerations;i++) {
generation();
evaluatePopulation(ASEvaluator);
populationStatistics();
scalePopulation();
// find the best pop member and check for convergence
converged = checkBest();
if ((i == m_maxGenerations) ||
((i % m_reportFrequency) == 0) ||
(converged == true)) {
m_generationReports.append(populationReport(i));
if (converged == true) {
break;
}
}
}
return attributeList(m_best.getChromosome());
}
/**
* converts a BitSet into a list of attribute indexes
* @param group the BitSet to convert
* @return an array of attribute indexes
**/
private int[] attributeList (BitSet group) {
int count = 0;
// count how many were selected
for (int i = 0; i < m_numAttribs; i++) {
if (group.get(i)) {
count++;
}
}
int[] list = new int[count];
count = 0;
for (int i = 0; i < m_numAttribs; i++) {
if (group.get(i)) {
list[count++] = i;
}
}
return list;
}
/**
* checks to see if any population members in the current
* population are better than the best found so far. Also checks
* to see if the search has converged---that is there is no difference
* in fitness between the best and worse population member
* @return true is the search has converged
* @exception Exception if something goes wrong
*/
private boolean checkBest() throws Exception {
int i,j,count,lowestCount = m_numAttribs;
double b = -Double.MAX_VALUE;
GABitSet localbest = null;
BitSet temp;
boolean converged = false;
int oldcount = Integer.MAX_VALUE;
if (m_maxFitness - m_minFitness > 0) {
// find the best in this population
for (i=0;i<m_popSize;i++) {
if (m_population[i].getObjective() > b) {
b = m_population[i].getObjective();
localbest = m_population[i];
oldcount = countFeatures(localbest.getChromosome());
} else if (Utils.eq(m_population[i].getObjective(), b)) {
// see if it contains fewer features
count = countFeatures(m_population[i].getChromosome());
if (count < oldcount) {
b = m_population[i].getObjective();
localbest = m_population[i];
oldcount = count;
}
}
}
} else {
// look for the smallest subset
for (i=0;i<m_popSize;i++) {
temp = m_population[i].getChromosome();
count = countFeatures(temp);;
if (count < lowestCount) {
lowestCount = count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -