package net.tuis.ubench.scale;
import java.util.Arrays;
import java.util.function.DoubleUnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
/**
* A function that describes one of the standard scaling equations
*
* @author Simon Forsberg
*/
public class MathEquation {
private final DoubleUnaryOperator equation;
private final double[] parameters;
private final String format;
private final double rSquared;
private final MathModel model;
/**
* A function that describes one of the standard scaling equations
*
* @param model
* the model this function is based on
* @param equation
* the x-to-y equation for this instance
* @param parameters
* the parameters describing the required coefficients in the
* equation
* @param format
* the string format for the equation
* @param rSquared
* the measure of the accuracy of this equation against the
* actual results.
*/
public MathEquation(MathModel model, DoubleUnaryOperator equation, double[] parameters, String format,
double rSquared) {
this.model = model;
this.equation = equation;
this.parameters = parameters;
this.format = format;
this.rSquared = rSquared;
}
/**
* Get a text-based description of this equation
*
* @return the string version of this equation
*/
public String getDescription() {
Object[] params = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
params[i] = parameters[i];
}
return String.format(format, params);
}
/**
* Get the parameters representing the various coefficients in this equation
*
* @return a copy of the equation coefficients
*/
public double[] getParameters() {
return Arrays.copyOf(parameters, parameters.length);
}
/**
* Get a function representing the x-to-y transform for this eqation
*
* @return an equation transforming an x position to a y offset.
*/
public DoubleUnaryOperator getEquation() {
return equation;
}
/**
* A String.format template for presenting the equation with its parameters
*
* @return A String format specification suitable for the parameters.
*/
public String getFormat() {
return format;
}
/**
* Get the accuracy measure for this equation against the actual results. A
* value of 1.0 is a compelte match against the actual results, a value
* close to zero is a fail-to-match
*
* @return the r-squared value representing this equation's accuracy
*/
public double getRSquared() {
return rSquared;
}
/**
* Get the mathematical model this equation is based on.
*
* @return the underlying model.
*/
public MathModel getModel() {
return model;
}
@Override
public String toString() {
return getDescription() + " with precision " + rSquared;
}
/**
* Convert this equation in to a JSON string representing the vital
* statistics of the equation.
*
* @return a JSON interpretation of this equation.
*/
public String toJSONString() {
String parms = DoubleStream.of(parameters)
.mapToObj(d -> String.format("%f", d))
.collect(Collectors.joining(", ", "[", "]"));
String desc = String.format(format, DoubleStream.of(parameters).mapToObj(Double::valueOf).toArray());
return String.format(
"{name: \"%s\", valid: %s, format: \"%s\", description: \"%s\", parameters: %s, rsquare: %f}",
model.getName(), isValid() ? "true" : "false", format, desc, parms, rSquared);
}
/**
* Indicate whether this equation is a suitable match against the actual
* data.
*
* @return true if this equation is useful when representing the actual
* data's scalability
*/
public boolean isValid() {
return Math.abs(parameters[0]) >= 0.001 && rSquared != Double.NEGATIVE_INFINITY && !Double.isNaN(rSquared);
}
}