org.jpmml.evaluator.DiscretizationUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.jpmml.evaluator.DiscretizationUtil.java

Source

/*
 * Copyright (c) 2013 Villu Ruusmann
 *
 * This file is part of JPMML-Evaluator
 *
 * JPMML-Evaluator 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.
 *
 * JPMML-Evaluator 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 JPMML-Evaluator.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jpmml.evaluator;

import java.util.List;
import java.util.Map;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableRangeMap;
import com.google.common.collect.Range;
import com.google.common.collect.RangeMap;
import com.google.common.collect.Table;
import com.google.common.collect.TreeRangeMap;
import org.dmg.pmml.DataType;
import org.dmg.pmml.Discretize;
import org.dmg.pmml.DiscretizeBin;
import org.dmg.pmml.InlineTable;
import org.dmg.pmml.Interval;
import org.dmg.pmml.MapValues;
import org.dmg.pmml.TableLocator;
import org.jpmml.manager.InvalidFeatureException;
import org.jpmml.manager.UnsupportedFeatureException;

public class DiscretizationUtil {

    private DiscretizationUtil() {
    }

    static public FieldValue discretize(Discretize discretize, FieldValue value) {
        String result = discretize(discretize, (value.asNumber()).doubleValue());

        return FieldValueUtil.create(discretize.getDataType(), null, result);
    }

    static public String discretize(Discretize discretize, double value) {
        RangeMap<Double, String> binRanges = CacheUtil.getValue(discretize, DiscretizationUtil.binRangeCache);

        Map.Entry<Range<Double>, String> entry = binRanges.getEntry(value);
        if (entry != null) {
            return entry.getValue();
        }

        return discretize.getDefaultValue();
    }

    static public FieldValue mapValue(MapValues mapValues, Map<String, FieldValue> values) {
        DataType dataType = mapValues.getDataType();

        TableLocator tableLocator = mapValues.getTableLocator();
        if (tableLocator != null) {
            throw new UnsupportedFeatureException(tableLocator);
        }

        InlineTable inlineTable = mapValues.getInlineTable();
        if (inlineTable != null) {
            Table<Integer, String, String> table = InlineTableUtil.getContent(inlineTable);

            Map<String, String> row = InlineTableUtil.match(table, values);
            if (row != null) {
                String result = row.get(mapValues.getOutputColumn());
                if (result == null) {
                    throw new EvaluationException(mapValues);
                }

                return FieldValueUtil.create(dataType, null, result);
            }
        }

        return FieldValueUtil.create(dataType, null, mapValues.getDefaultValue());
    }

    static public Range<Double> toRange(Interval interval) {
        Double leftMargin = interval.getLeftMargin();
        Double rightMargin = interval.getRightMargin();

        // "The attributes leftMargin and rightMargin are optional but at least one value must be defined"
        if (leftMargin == null && rightMargin == null) {
            throw new InvalidFeatureException(interval);
        } // End if

        if (leftMargin != null && rightMargin != null && (leftMargin).compareTo(rightMargin) > 0) {
            throw new InvalidFeatureException(interval);
        }

        Interval.Closure closure = interval.getClosure();
        switch (closure) {
        case OPEN_OPEN: {
            if (leftMargin == null) {
                return Range.lessThan(rightMargin);
            } else

            if (rightMargin == null) {
                return Range.greaterThan(leftMargin);
            }

            return Range.open(leftMargin, rightMargin);
        }
        case OPEN_CLOSED: {
            if (leftMargin == null) {
                return Range.atMost(rightMargin);
            } else

            if (rightMargin == null) {
                return Range.greaterThan(leftMargin);
            }

            return Range.openClosed(leftMargin, rightMargin);
        }
        case CLOSED_OPEN: {
            if (leftMargin == null) {
                return Range.lessThan(rightMargin);
            } else

            if (rightMargin == null) {
                return Range.atLeast(leftMargin);
            }

            return Range.closedOpen(leftMargin, rightMargin);
        }
        case CLOSED_CLOSED: {
            if (leftMargin == null) {
                return Range.atMost(rightMargin);
            } else

            if (rightMargin == null) {
                return Range.atLeast(leftMargin);
            }

            return Range.closed(leftMargin, rightMargin);
        }
        default:
            throw new UnsupportedFeatureException(interval, closure);
        }
    }

    static private RangeMap<Double, String> parseBinRanges(Discretize discretize) {
        RangeMap<Double, String> result = TreeRangeMap.create();

        List<DiscretizeBin> discretizeBins = discretize.getDiscretizeBins();
        for (DiscretizeBin discretizeBin : discretizeBins) {
            Interval interval = discretizeBin.getInterval();
            String binValue = discretizeBin.getBinValue();

            if (interval == null || binValue == null) {
                throw new InvalidFeatureException(discretizeBin);
            }

            Range<Double> range = toRange(interval);

            result.put(range, binValue);
        }

        return result;
    }

    private static final LoadingCache<Discretize, RangeMap<Double, String>> binRangeCache = CacheBuilder
            .newBuilder().weakKeys().build(new CacheLoader<Discretize, RangeMap<Double, String>>() {

                @Override
                public RangeMap<Double, String> load(Discretize discretize) {
                    return ImmutableRangeMap.copyOf(parseBinRanges(discretize));
                }
            });
}