/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Arithmetic.java * Copyright (C) 2008-2012 University of Waikato, Hamilton, New Zealand * */ package weka.core.pmml; import java.util.ArrayList; import weka.core.Attribute; import weka.core.Utils; /** * Built-in function for min, max, sum, avg, log10, * ln, sqrt, abs, exp, pow, threshold, floor, ceil and round. * * @author Mark Hall (mhall{[at]}pentaho{[dot]}com) * @version $Revision 1.0 $ */ public class BuiltInMath extends Function { /** * For serialization */ private static final long serialVersionUID = -8092338695602573652L; /** * Enum for the math functions. */ enum MathFunc { MIN ("min") { double eval(double[] args) { return args[Utils.minIndex(args)]; } boolean legalNumParams(int num) { return (num > 0); } String[] getParameterNames() { return null; // unbounded number of parameters } }, MAX ("max") { double eval(double[] args) { return args[Utils.maxIndex(args)]; } boolean legalNumParams(int num) { return (num > 0); } String[] getParameterNames() { return null; // unbounded number of parameters } }, SUM ("sum") { double eval(double[] args) { return Utils.sum(args); } boolean legalNumParams(int num) { return (num > 0); } String[] getParameterNames() { return null; // unbounded number of parameters } }, AVG ("avg") { double eval(double[] args) { return Utils.mean(args); } boolean legalNumParams(int num) { return (num > 0); } String[] getParameterNames() { return null; // unbounded number of parameters } }, LOG10 ("log10") { double eval(double[] args) { return Math.log10(args[0]); } boolean legalNumParams(int num) { return (num == 1); } String[] getParameterNames() { return new String[] {"A"}; } }, LN ("ln") { double eval(double[] args) { return Math.log(args[0]); } boolean legalNumParams(int num) { return (num == 1); } String[] getParameterNames() { return new String[] {"A"}; } }, SQRT ("sqrt") { double eval(double[] args) { return Math.sqrt(args[0]); } boolean legalNumParams(int num) { return (num == 1); } String[] getParameterNames() { return new String[] {"A"}; } }, ABS ("abs") { double eval(double[] args) { return Math.abs(args[0]); } boolean legalNumParams(int num) { return (num == 1); } String[] getParameterNames() { return new String[] {"A"}; } }, EXP ("exp") { double eval(double[] args) { return Math.exp(args[0]); } boolean legalNumParams(int num) { return (num == 1); } String[] getParameterNames() { return new String[] {"A"}; } }, POW ("pow") { double eval(double[] args) { return Math.pow(args[0], args[1]); } boolean legalNumParams(int num) { return (num == 2); } String[] getParameterNames() { return new String[] {"A", "B"}; } }, THRESHOLD ("threshold") { double eval(double[] args) { if (args[0] > args[1]) { return 1.0; } else { return 0.0; } } boolean legalNumParams(int num) { return (num == 2); } String[] getParameterNames() { return new String[] {"A", "B"}; } }, FLOOR ("floor") { double eval(double[] args) { return Math.floor(args[0]); } boolean legalNumParams(int num) { return (num == 1); } String[] getParameterNames() { return new String[] {"A"}; } }, CEIL ("ceil") { double eval(double[] args) { return Math.ceil(args[0]); } boolean legalNumParams(int num) { return (num == 1); } String[] getParameterNames() { return new String[] {"A"}; } }, ROUND ("round") { double eval(double[] args) { return Math.round(args[0]); } boolean legalNumParams(int num) { return (num == 1); } String[] getParameterNames() { return new String[] {"A"}; } }; abstract double eval(double[] args); abstract boolean legalNumParams(int num); abstract String[] getParameterNames(); private final String m_stringVal; MathFunc(String funcName) { m_stringVal = funcName; } public String toString() { return m_stringVal; } } /** The function to apply */ protected MathFunc m_func = MathFunc.ABS; /** * Construct a new built-in pmml Math function. * @param func the math function to use */ public BuiltInMath(MathFunc func) { m_func = func; m_functionName = m_func.toString(); } /** * Set the structure of the parameters that are expected as input by * this function. This must be called before getOutputDef() is called. * * @param paramDefs the structure of the input parameters * @throws Exception if the number or types of parameters are not acceptable by * this function */ public void setParameterDefs(ArrayList<Attribute> paramDefs) throws Exception { m_parameterDefs = paramDefs; if (!m_func.legalNumParams(m_parameterDefs.size())) { throw new Exception("[BuiltInMath] illegal number of parameters for function: " + m_functionName); } } /** * Get the structure of the result produced by this function. * Subclasses must implement. * * @return the structure of the result produced by this function. */ public Attribute getOutputDef() { return new Attribute("BuiltInMathResult:" + m_func.toString()); } /** * Returns an array of the names of the parameters expected * as input by this function. May return null if the function * can accept an unbounded number of arguments. * * @return an array of the parameter names (or null if the function * can accept any number of arguments). */ public String[] getParameterNames() { return m_func.getParameterNames(); } /** * Get the result of applying this function. * * @param incoming the arguments to this function (supplied in order to match that * of the parameter definitions * @return the result of applying this function. When the optype is * categorical or ordinal, an index into the values of the output definition * is returned. * @throws Exception if there is a problem computing the result of this function */ public double getResult(double[] incoming) throws Exception { if (m_parameterDefs == null) { throw new Exception("[BuiltInMath] incoming parameter structure has not been set"); } if (!m_func.legalNumParams(incoming.length)) { throw new Exception("[BuiltInMath] wrong number of parameters!"); } double result = m_func.eval(incoming); return result; } public String toString() { String result = m_func.toString() + "("; for (int i = 0; i < m_parameterDefs.size(); i++) { result += m_parameterDefs.get(i).name(); if (i != m_parameterDefs.size() - 1) { result += ", "; } else { result += ")"; } } return result; } }