/* * 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 java.util.Random; import com.rapidminer.example.Attribute; import com.rapidminer.example.set.AttributeWeightedExampleSet; import com.rapidminer.operator.features.selection.SelectionCrossover; /** * This <tt>PopulationOperator</tt> applies a crossover on two example sets. * Crossover type can be ONE_POINT, UNIFORM, or SHUFFLE. In difference to * SelectionCrossover the attribute vectors can have different lengths. <br> * This crossover type should only be used for SINGLE_VALUEs, i.e. attributes * without a block number (blocknumber can and should be assigned to value * series attributes)! * * @author Ingo Mierswa * @version $Id: UnbalancedCrossover.java,v 1.1 2006/04/14 07:47:17 ingomierswa * Exp $ */ public class UnbalancedCrossover extends SelectionCrossover { private static class AttributeWeightContainer { private Attribute attribute; private double weight; public AttributeWeightContainer(Attribute attribute, double weight) { this.attribute = attribute; this.weight = weight; } public Attribute getAttribute() { return attribute; } public double getWeight() { return weight; } public String toString() { return attribute.getName() + "(" + weight + ")"; } } private Random random; /** * Creates a new generating crossover with the given type which will be * applied with the given probability. */ public UnbalancedCrossover(int type, double prob, Random random) { super(type, prob, random, 1, Integer.MAX_VALUE, -1); this.random = random; } /** Applies the crossover. Works directly on the given example sets. */ public void crossover(AttributeWeightedExampleSet es1, AttributeWeightedExampleSet es2) { LinkedList<AttributeWeightContainer> dummyList1 = new LinkedList<AttributeWeightContainer>(); LinkedList<AttributeWeightContainer> dummyList2 = new LinkedList<AttributeWeightContainer>(); int maxSize = Math.max(es1.getAttributes().size(), es2.getAttributes().size()); if (maxSize < 2) return; switch (getType()) { case SelectionCrossover.ONE_POINT: int splitPoint = 1 + random.nextInt(maxSize - 2); Iterator<Attribute> it = es1.getAttributes().iterator(); int counter = 0; while (it.hasNext()) { Attribute attribute = it.next(); if (counter > splitPoint) { double weight = es1.getWeight(attribute); it.remove(); dummyList1.add(new AttributeWeightContainer(attribute, weight)); } counter++; } it = es2.getAttributes().iterator(); counter = 0; while (it.hasNext()) { Attribute attribute = it.next(); if (counter > splitPoint) { double weight = es2.getWeight(attribute); it.remove(); dummyList2.add(new AttributeWeightContainer(attribute, weight)); } counter++; } break; case SelectionCrossover.UNIFORM: it = es1.getAttributes().iterator(); while (it.hasNext()) { Attribute attribute = it.next(); if (random.nextBoolean()) { double weight = es1.getWeight(attribute); dummyList1.add(new AttributeWeightContainer(attribute, weight)); it.remove(); } } it = es2.getAttributes().iterator(); while (it.hasNext()) { Attribute attribute = it.next(); if (random.nextBoolean()) { double weight = es2.getWeight(attribute); dummyList2.add(new AttributeWeightContainer(attribute, weight)); it.remove(); } } break; case SelectionCrossover.SHUFFLE: double prob1 = (double) (random.nextInt(es1.getAttributes().size() - 1) + 1) / (double) es1.getAttributes().size(); it = es1.getAttributes().iterator(); while (it.hasNext()) { Attribute attribute = it.next(); if (random.nextDouble() < prob1) { double weight = es1.getWeight(attribute); dummyList1.add(new AttributeWeightContainer(attribute, weight)); it.remove(); } } double prob2 = (double) (random.nextInt(es2.getAttributes().size() - 1) + 1) / (double) es2.getAttributes().size(); it = es2.getAttributes().iterator(); while (it.hasNext()) { Attribute attribute = it.next(); if (random.nextDouble() < prob2) { double weight = es2.getWeight(attribute); dummyList2.add(new AttributeWeightContainer(attribute, weight)); it.remove(); } } break; default: break; } mergeAttributes(es1, dummyList2); mergeAttributes(es2, dummyList1); } private void mergeAttributes(AttributeWeightedExampleSet exampleSet, List<AttributeWeightContainer> attributeWeights) { Iterator<AttributeWeightContainer> i = attributeWeights.iterator(); while (i.hasNext()) { AttributeWeightContainer attributeWeight = i.next(); Attribute attribute = attributeWeight.getAttribute(); if (exampleSet.getAttributes().get(attribute.getName()) == null) { exampleSet.getAttributes().addRegular(attribute); } exampleSet.setWeight(attribute, attributeWeight.getWeight()); } } }