/* * RapidMiner * * Copyright (C) 2001-2008 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.operator.features.construction; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import com.rapidminer.example.Attribute; import com.rapidminer.example.Tools; import com.rapidminer.example.set.AttributeWeightedExampleSet; import com.rapidminer.generator.FeatureGenerator; import com.rapidminer.generator.GenerationException; import com.rapidminer.operator.features.Individual; import com.rapidminer.operator.features.IndividualOperator; import com.rapidminer.tools.RandomGenerator; /** * The mutation operator for YAGGA. This operator adds single attributes from * the original set, creates new ones and deselect single attributes. * * @see YAGGA * @author Ingo Mierswa, Simon Fischer * @version $Id: GeneratingMutation.java,v 1.1 2006/04/14 07:47:17 ingomierswa * Exp $ */ public class GeneratingMutation extends IndividualOperator { private List<FeatureGenerator> generators; private List<Attribute> originalAttributes; private double prob; private int maxNumberOfAttributes; private RandomGenerator random; private int maxDepth = -1; private String[] unusedFunctions = new String[0]; public GeneratingMutation(List<Attribute> originalAttributes, double prob, int maxNumberOfAttributes, List<FeatureGenerator> generators, RandomGenerator random) { this.originalAttributes = originalAttributes; this.prob = prob; this.maxNumberOfAttributes = maxNumberOfAttributes; this.generators = generators; this.random = random; } public void setMaxConstructionDepth(int maxDepth) { this.maxDepth = maxDepth; } public void setUnusedFunctions(String[] functions) { this.unusedFunctions = functions; } /** * Performs one of the following three mutations: * <ul> * <li>add a newly generated attribute</li> * <li>add an original attribute</li> * <li>remove an attribute</li> * </ul> */ public List<Individual> operate(Individual individual) throws Exception { List<Individual> l = new LinkedList<Individual>(); AttributeWeightedExampleSet clone = (AttributeWeightedExampleSet) individual.getExampleSet().clone(); double p = prob < 0 ? 1.0d / clone.getAttributes().size() : prob; p /= 4.0d; try { if ((maxNumberOfAttributes < 0) || (clone.getAttributes().size() < maxNumberOfAttributes)) { addOriginalAttribute(clone, p); } boolean generationPossible = false; if ((maxNumberOfAttributes < 0) || (clone.getAttributes().size() <= maxNumberOfAttributes)) { generationPossible = addGeneratedAttribute(clone, p); } deselect(clone, generationPossible ? 2 : 1, p); } catch (GenerationException e) { individual.getExampleSet().getLog().logWarning("GeneratingMutation: Exception occured during generation of attributes, using only original example set instead."); } if (clone.getNumberOfUsedAttributes() > 0) { l.add(new Individual(clone)); } l.add(individual); return l; } /** Adds a new attribute. Returns true, if generation was possible. */ private boolean addGeneratedAttribute(AttributeWeightedExampleSet exampleSet, double p) throws Exception { if (random.nextDouble() < p) { FeatureGenerator generator = FeatureGenerator.selectGenerator(exampleSet, generators, maxDepth, unusedFunctions, random); if (generator != null) { generator = generator.newInstance(); Attribute[] args = Tools.getRandomCompatibleAttributes(exampleSet, generator, maxDepth, unusedFunctions, random); generator.setArguments(args); List<FeatureGenerator> generatorList = new LinkedList<FeatureGenerator>(); generatorList.add(generator); List<Attribute> newAttributes = FeatureGenerator.generateAll(exampleSet.getExampleTable(), generatorList); for (Attribute newAttribute : newAttributes) exampleSet.getAttributes().addRegular(newAttribute); return true; } else return false; } else return false; } private void addOriginalAttribute(AttributeWeightedExampleSet exampleSet, double p) { if (random.nextDouble() < p) { int i = random.nextInt(originalAttributes.size()); Attribute originalAttribute = originalAttributes.get(i); if (exampleSet.getAttributes().get(originalAttribute.getName()) == null) exampleSet.getAttributes().addRegular(originalAttribute); } } private void deselect(AttributeWeightedExampleSet exampleSet, int m, double p) { Iterator<Attribute> i = exampleSet.getAttributes().iterator(); while (i.hasNext()) { i.next(); if (random.nextDouble() < m * p / originalAttributes.size()) { i.remove(); } } } }