/*
* RapidMiner
*
* Copyright (C) 2001-2011 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.preprocessing.filter;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.rapidminer.example.Attribute;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.operator.OperatorDescription;
import com.rapidminer.operator.annotation.ResourceConsumptionEstimator;
import com.rapidminer.operator.ports.metadata.AttributeMetaData;
import com.rapidminer.operator.ports.metadata.ExampleSetMetaData;
import com.rapidminer.parameter.ParameterType;
import com.rapidminer.parameter.ParameterTypeCategory;
import com.rapidminer.parameter.ParameterTypeDouble;
import com.rapidminer.parameter.UndefinedParameterError;
import com.rapidminer.parameter.conditions.EqualTypeCondition;
import com.rapidminer.tools.Ontology;
import com.rapidminer.tools.OperatorResourceConsumptionHandler;
/**
* Replaces positive and negative infinite values in examples by one of the
* functions "none", "zero", "max_byte",
* "max_int", "max_double", and "missing".
* "none" means, that the value is not replaced. The max_xxx functions
* replace plus infinity by the upper bound and minus infinity by the lower
* bound of the range of the Java type xxx. "missing" means, that the
* value is replaced by nan (not a number), which is internally used to
* represent missing values. A {@link MissingValueReplenishment} operator can be
* used to replace missing values by average (or the mode for nominal
* attributes), maximum, minimum etc. afterwards.<br/> For each attribute, the
* function can be selected using the parameter list <code>columns</code>. If
* an attribute's name appears in this list as a key, the value is used as the
* function name. If the attribute's name is not in the list, the function
* specified by the <code>default</code> parameter is used.
*
* @author Simon Fischer, Ingo Mierswa
*/
public class InfiniteValueReplenishment extends ValueReplenishment {
public static final String PARAMETER_REPLENISHMENT_VALUE = "replenishment_value";
public static final String PARAMETER_REPLENISHMENT_WHAT = "replenish_what";
private static final int NONE = 0;
private static final int ZERO = 1;
private static final int MAX_BYTE = 2;
private static final int MAX_INT = 3;
private static final int MAX_DOUBLE = 4;
private static final int MISSING = 5;
private static final int VALUE = 6;
private static final String[] REP_NAMES = { "none", "zero", "max_byte", "max_int", "max_double", "missing", "value" };
private static final String[] WHAT_NAMES = { "positive_infinity", "negative_infinity"};
public InfiniteValueReplenishment(OperatorDescription description) {
super(description);
}
@Override
protected Collection<AttributeMetaData> modifyAttributeMetaData(ExampleSetMetaData emd, AttributeMetaData amd) throws UndefinedParameterError {
return Collections.singletonList(amd);
}
@Override
public double getReplacedValue() {
try {
int chosen = getParameterAsInt(PARAMETER_REPLENISHMENT_WHAT);
if (chosen == 0)
return Double.POSITIVE_INFINITY;
} catch (Exception e) {}
return Double.NEGATIVE_INFINITY;
}
@Override
protected int[] getFilterValueTypes() {
return new int[] {Ontology.NUMERICAL};
}
@Override
public String[] getFunctionNames() {
return REP_NAMES;
}
@Override
public int getDefaultFunction() {
return MAX_DOUBLE;
}
@Override
public int getDefaultColumnFunction() {
return ZERO;
}
/** Replaces the values
* @throws UndefinedParameterError */
@Override
public double getReplenishmentValue(int functionIndex, ExampleSet exampleSet, Attribute attribute) throws UndefinedParameterError {
int chosen = getParameterAsInt(PARAMETER_REPLENISHMENT_WHAT);
switch (functionIndex) {
case NONE:
return Double.POSITIVE_INFINITY;
case ZERO:
return 0.0;
case MAX_BYTE:
return (chosen == 0) ? Byte.MAX_VALUE : Byte.MIN_VALUE;
case MAX_INT:
return (chosen == 0) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
case MAX_DOUBLE:
return (chosen == 0) ? Double.MAX_VALUE : -Double.MAX_VALUE;
case MISSING:
return Double.NaN;
case VALUE:
return getParameterAsDouble(PARAMETER_REPLENISHMENT_VALUE);
default:
throw new RuntimeException("Illegal value functionIndex: " + functionIndex);
}
}
@Override
public List<ParameterType> getParameterTypes() {
List<ParameterType> types = super.getParameterTypes();
ParameterType type = new ParameterTypeCategory(PARAMETER_REPLENISHMENT_WHAT, "Decides if positive or negative infite values will be replaced.", WHAT_NAMES, 0, false);
types.add(type);
type = new ParameterTypeDouble(PARAMETER_REPLENISHMENT_VALUE, "This value will be inserted instead of infinity.", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, true);
type.registerDependencyCondition(new EqualTypeCondition(this, PARAMETER_DEFAULT, getFunctionNames(), true, VALUE));
types.add(type);
return types;
}
@Override
public ResourceConsumptionEstimator getResourceConsumptionEstimator() {
return OperatorResourceConsumptionHandler.getResourceConsumptionEstimator(getInputPort(), InfiniteValueReplenishment.class, attributeSelector);
}
}