Java tutorial
/** * Copyright (c) 2010 Darmstadt University of Technology. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Marcel Bruch - initial API and implementation. * Sebastian Proksch - stripped down to a simple calculation helper */ package cc.recommenders.mining.calls; import static cc.recommenders.assertions.Checks.ensureEquals; import static cc.recommenders.assertions.Checks.ensureIsGreaterOrEqualTo; import static cc.recommenders.assertions.Checks.ensureIsNotNull; import static cc.recommenders.assertions.Throws.throwIllegalArgumentException; import static cc.recommenders.assertions.Throws.throwIllegalStateException; import static java.lang.Math.abs; import java.math.BigDecimal; import java.util.Arrays; import org.apache.commons.math.stat.StatUtils; import org.apache.commons.math.util.MathUtils; import org.eclipse.recommenders.commons.bayesnet.Node; public class NetworkMathUtils { // TODO check why this is so huge! public static final double MAX_PROBABILTY_DELTA = 0.1; public static final int P_ROUNDING_PRECISION = 6; public static final double P_ROUNDING_FACTOR = 1000000; public static final double P_MIN = 0.000001; public static final double P_MAX = 0.999999; /** * Computes the sum of all values, determines the delta to "1.0" and * corrects this by adding or removing the delta to the any of the fields * (starting from the <b>last</b> index). * * @throws RuntimeException * if delta passes a max threshold */ public static void scaleMaximalValue(final double[] values) { for (int i = 0; i < values.length; i++) { values[i] += P_MIN; } // ensureAllProbabilitiesInValidRange(values); // final double sum = StatUtils.sum(values); // final double delta = 1.0 - sum; // // if (isDeltaEqualToZero(delta)) { // return; // } // if (isDeltaTooHigh(delta)) { // throwIllegalArgumentException("sum of values is too far away from '1.0': %6.6f", // sum); // } // for (int i = values.length; i-- > 0;) { // double d = values[i]; // d += delta; // d = round(d, P_ROUNDING_PRECISION); // if (isInMinMaxRange(d)) { // values[i] = d; // // sanity check: did we actually fix the problem? // ensureSumIsOne(values); // return; // } // } // // // TODO re-enable exception, but include further handling here! // Logger.err("Scaling Error: failed to scale double array. Delta '%.6f' couldn't " // + // "be added to any other value AND keeping min/max constraints intact.\n", // delta); // throwIllegalArgumentException( // "failed to scale double array. Delta '%.6f' couldn't be added to any other value in '%s' AND keeping min/max constraints intact.", // delta, Arrays.toString(values)); } public static void ensureAllProbabilitiesInValidRange(final double[] values) { ensureIsNotNull(values); ensureIsGreaterOrEqualTo(values.length, 1, "zero length arrays not allowed."); for (int i = values.length; i-- > 0;) { if (!isInMinMaxRange(values[i])) { throwIllegalArgumentException("index '%d' has invalid value of '%1.6f'.", i, values[i]); } } } public static boolean isInMinMaxRange(final double value) { if (value < P_MIN) { return false; } if (value > P_MAX) { return false; } return true; } private static boolean isDeltaEqualToZero(final double delta) { return delta == 0d; } private static boolean isDeltaTooHigh(final double delta) { final boolean res = abs(delta) > MAX_PROBABILTY_DELTA; return res; } @Deprecated public static double round(final double value, final int precision) { return MathUtils.round(value, precision, BigDecimal.ROUND_HALF_EVEN); } public static double roundToDefaultPrecision(final double value) { return (long) (P_ROUNDING_FACTOR * value + 0.5) / P_ROUNDING_FACTOR; } private static void ensureSumIsOne(final double[] values) { final double sum = StatUtils.sum(values); final double delta = abs(1 - sum); if (delta > 0.0001) { throwIllegalStateException("failed to round double array properly"); } } // // private static IMethodName findConstructorCall(final Set<IMethodName> // invokedMethods) { // for (final IMethodName m : invokedMethods) { // if (m.isInit()) { // return m; // } // } // return null; // } public static void ensureCorrectNumberOfProbabilities(final Node node) { int numberOfProbabilities = node.getStates().length; for (final Node parent : node.getParents()) { numberOfProbabilities *= parent.getStates().length; } ensureEquals(numberOfProbabilities, node.getProbabilities().length, "incomplete probability definition"); } public static void ensureMinimumTwoStates(final Node node) { ensureMinimumTwoStates(node.getStates()); } public static void ensureMinimumTwoStates(final String[] states) { ensureIsGreaterOrEqualTo(states.length, 2, "less than 2 states: %s", Arrays.toString(states)); } public static double[] createPriorProbabilitiesForContextNodeAssumingDummyStateAtFirstIndex(final int length) { final double[] res = new double[length]; Arrays.fill(res, 1, res.length, P_MIN); final double sum = StatUtils.sum(res); res[0] = 1 - sum; return res; } /** * Returns a/b. Returns P_MIN if b==0; */ public static double safeDivMaxMin(final int a, final int b) { // TODO does this make sense? Wouldn't P_MAX be "more" correct? if (b == 0) { return P_MIN; } final double res = a / (double) b; if (res > P_MAX) { return P_MAX; } if (res < P_MIN) { return P_MIN; } return res; } public static double getProbabilityInMinMaxRange(double probability) { if (probability > P_MAX) { return P_MAX; } if (probability < P_MIN) { return P_MIN; } return probability; } }