weka.core.pmml.DefineFunction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weka-dev Show documentation
Show all versions of weka-dev Show documentation
The Waikato Environment for Knowledge Analysis (WEKA), a machine
learning workbench. This version represents the developer version, the
"bleeding edge" of development, you could say. New functionality gets added
to this version.
/*
* 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 .
*/
/*
* DefineFunction.java
* Copyright (C) 2008-2012 University of Waikato, Hamilton, New Zealand
*
*/
package weka.core.pmml;
import java.util.ArrayList;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import weka.core.Attribute;
/**
* Class encapsulating DefineFunction (used in TransformationDictionary).
*
* @author Mark Hall (mhall{[at]}pentaho{[dot]}com
* @version $Revision 1.0 $
*/
public class DefineFunction extends Function {
/**
* For serialization
*/
private static final long serialVersionUID = -1976646917527243888L;
/**
* Inner class for handling Parameters
*/
protected class ParameterField extends FieldMetaInfo {
/**
* For serialization
*/
private static final long serialVersionUID = 3918895902507585558L;
protected ParameterField(Element field) {
super(field);
}
public Attribute getFieldAsAttribute() {
if (m_optype == Optype.CONTINUOUS) {
return new Attribute(m_fieldName);
}
// return a string attribute for categorical/ordinal optypes
return new Attribute(m_fieldName, (ArrayList)null);
}
}
/**
* The list of parameters expected by this function. We can use this to do
* some error/type checking when users call setParameterDefs() on us
*/
protected ArrayList m_parameters = new ArrayList();
/** The optype for this function */
FieldMetaInfo.Optype m_optype = FieldMetaInfo.Optype.NONE;
/** The Expression for this function to use */
protected Expression m_expression = null;
public DefineFunction(Element container, TransformationDictionary transDict) throws Exception {
m_functionName = container.getAttribute("name");
// get the optype for this function
String opType = container.getAttribute("optype");
if (opType != null && opType.length() > 0) {
for (FieldMetaInfo.Optype o : FieldMetaInfo.Optype.values()) {
if (o.toString().equals(opType)) {
m_optype = o;
break;
}
}
} else {
throw new Exception("[DefineFunction] no optype specified!!");
}
m_parameterDefs = new ArrayList();
// get all the parameters
NodeList paramL = container.getElementsByTagName("ParameterField");
for (int i = 0; i < paramL.getLength(); i++) {
Node paramN = paramL.item(i);
if (paramN.getNodeType() == Node.ELEMENT_NODE) {
ParameterField newP = new ParameterField((Element)paramN);
m_parameters.add(newP);
// set up default parameter definitions - these will probably get replaced
// by more informative ones (i.e. possibly nominal attributes instead of
// string attributes) later
m_parameterDefs.add(newP.getFieldAsAttribute());
}
}
m_expression = Expression.getExpression(container, m_optype, m_parameterDefs, transDict);
// check that the optype of the Expression is compatible with ours
if (m_optype == FieldMetaInfo.Optype.CONTINUOUS &&
m_expression.getOptype() != m_optype) {
throw new Exception("[DefineFunction] optype is continuous but our Expression's optype "
+ "is not.");
}
if ((m_optype == FieldMetaInfo.Optype.CATEGORICAL || m_optype == FieldMetaInfo.Optype.ORDINAL) !=
(m_expression.getOptype() == FieldMetaInfo.Optype.CATEGORICAL ||
m_expression.getOptype() == FieldMetaInfo.Optype.ORDINAL)) {
throw new Exception("[DefineFunction] optype is categorical/ordinal but our Expression's optype "
+ "is not.");
}
}
public void pushParameterDefs() throws Exception {
if (m_parameterDefs == null) {
throw new Exception("[DefineFunction] parameter definitions are null! Can't "
+ "push them to encapsulated expression.");
}
m_expression.setFieldDefs(m_parameterDefs);
}
/**
* Get the structure of the result produced by this function.
*
* @return the structure of the result produced by this function.
*/
public Attribute getOutputDef() {
return m_expression.getOutputDef();
}
/**
* Returns an array of the names of the parameters expected
* as input by this function. May return null if this function
* can take an unbounded number of parameters (i.e. min, max, etc.).
*
* @return an array of the parameter names or null if there are an
* unbounded number of parameters.
*/
public String[] getParameterNames() {
String[] result = new String[m_parameters.size()];
for (int i = 0; i < m_parameters.size(); i++) {
result[i] = m_parameters.get(i).getFieldName();
}
return result;
}
/**
* 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 (incoming.length != m_parameters.size()) {
throw new IllegalArgumentException("[DefineFunction] wrong number of arguments: expected "
+ m_parameters.size() + ", recieved " + incoming.length);
}
return m_expression.getResult(incoming);
}
/**
* 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 paramDefs) throws Exception {
if (paramDefs.size() != m_parameters.size()) {
throw new Exception("[DefineFunction] number of parameter definitions does not match "
+ "number of parameters!");
}
// check these defs against the optypes of the parameters
for (int i = 0; i < m_parameters.size(); i++) {
if (m_parameters.get(i).getOptype() == FieldMetaInfo.Optype.CONTINUOUS) {
if (!paramDefs.get(i).isNumeric()) {
throw new Exception("[DefineFunction] parameter "
+ m_parameters.get(i).getFieldName() + " is continuous, but corresponding "
+ "supplied parameter def " + paramDefs.get(i).name() + " is not!");
}
} else {
if (!paramDefs.get(i).isNominal() && !paramDefs.get(i).isString()) {
throw new Exception("[DefineFunction] parameter "
+ m_parameters.get(i).getFieldName() + " is categorical/ordinal, but corresponding "
+ "supplied parameter def " + paramDefs.get(i).name() + " is not!");
}
}
}
// now we need to rename these argument definitions to match the names of
// the actual parameters
ArrayList newParamDefs = new ArrayList();
for (int i = 0; i < paramDefs.size(); i++) {
Attribute a = paramDefs.get(i);
newParamDefs.add(a.copy(m_parameters.get(i).getFieldName()));
}
m_parameterDefs = newParamDefs;
// update the Expression
m_expression.setFieldDefs(m_parameterDefs);
}
public String toString() {
return toString("");
}
public String toString(String pad) {
StringBuffer buff = new StringBuffer();
buff.append(pad + "DefineFunction (" + m_functionName + "):\n"
+ pad + "nparameters:\n");
for (ParameterField p : m_parameters) {
buff.append(pad + p.getFieldAsAttribute() + "\n");
}
buff.append(pad + "expression:\n" + m_expression.toString(pad + " "));
return buff.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy