All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.constraints.impl.Real Maven / Gradle / Ivy

Go to download

JCP Standard JSR331 “Java Constraint Programming API”. It is used for Modeling and Solving Constraint Satisfaction and Optimization Problems using Java and off-the-shelf Constraint/Linear Solvers

The newest version!
package javax.constraints.impl;

import javax.constraints.Problem;
import javax.constraints.VarReal;

//  IEEE 754 NAN and inf RULES
//  - result of any operation with the operand NAN = NAN
//  - (-inf)+(+inf) = NAN
//  - (+inf)-(+inf) = NAN
//  - (-inf)-(-inf) = NAN
//  - inf*0 = NAN
//  - inf/inf = NAN
//  - 0/0 = NAN ((!0)/0 = (+/-)inf)
//
// We have to try the rules:
//   - values can be finite doubles, +inf, -inf but not NaN

/**
 * A helper for the floating-point arithmetic.
 */
public final class Real {
	/**
	 * A Not-a-Number (NaN) value of type double.
	 * 
	 * @see Double#NaN
	 */
//	static public final double NaN = Double.NaN;

	/**
	 * The positive infinity of type double.
	 * 
	 * @see Double#POSITIVE_INFINITY
	 */
//	static public final double pInf = Double.POSITIVE_INFINITY;

	/**
	 * The negative infinity of type double.
	 * 
	 * @see Double#NEGATIVE_INFINITY
	 */
//	static public final double nInf = Double.NEGATIVE_INFINITY;

	/**
	 * Returns true if the specified numbers are equal with the precision
	 */
	public static boolean eq(Problem p, double d1, double d2) {
		return Math.abs(d1 - d2) < p.getRealPrecision();
	}

	/**
	 * Returns true if the first number more than the second number with the
	 * precision
	 */
	public static boolean gt(Problem p, double d1, double d2) {
		return (d1 - d2) > p.getRealPrecision();
	}

	/**
	 * Returns true if the first number is more or equal to the second number
	 * with the precision
	 */
	public static boolean ge(Problem p, double d1, double d2) {
		return d1 - d2 > -p.getRealPrecision();
	}

	/**
	 * Returns true if the specified number is the special Not-a-Number (NaN)
	 * value.
	 * 
	 * @see Double#isNaN
	 */
	public static boolean isNan(double v) {
		return Double.isNaN(v);
	}

	/**
	 * Returns true if the specified number is infinitely large in magnitude.
	 * 
	 * @see Double#isInfinite
	 */
	public static boolean isInf(double v) {
		return Double.isInfinite(v);
	}

	/**
	 * Returns the expression: min(1 / [min..max]). Result may be
	 * finite number or -inf.
	 */
	public static double inverseMin(double min, double max) {
		assertMinMax(min, max);
		double _min;
		// strictly positive or strictly negative
		if (min > 0 || max < 0) {
			_min = 1 / max;
		}
		// [0..>0]
		else if (min == 0 && max > 0) {
			_min = 1 / max;
		}
		// [<0..0]
		else if (max == 0 && min < 0) {
			_min = Double.NEGATIVE_INFINITY;
		}
		// [<0..>0] or [0..0]
		else {
			_min = Double.NEGATIVE_INFINITY;
		}
		return _min;
	}

	/**
	 * Returns the expression: max(1 / [min..max]). Result may be
	 * finite number or +inf.
	 */
	public static double inverseMax(double min, double max) {
		assertMinMax(min, max);
		double _max;
		// strictly positive or strictly negative
		if (min > 0 || max < 0) {
			_max = 1 / min;
		}
		// [0..>0]
		else if (min == 0 && max > 0) {
			_max = Double.POSITIVE_INFINITY;
		}
		// [<0..0]
		else if (max == 0 && min < 0) {
			_max = 1 / min;
		}
		// [<0..>0] or [0..0]
		else {
			_max = Double.POSITIVE_INFINITY;
		}
		return _max;
	}

	/**
	 * Returns the expression: min(1 / [v..v]). Result may be
	 * finite number or -inf.
	 */
	public static double inverseMin(double v) {
		return v != 0 ? 1 / v : Double.NEGATIVE_INFINITY;
	}

	/**
	 * Returns the expression: max(1 / [v..v]). Result may be
	 * finite number or +inf.
	 */
	public static double inverseMax(double v) {
		return v != 0 ? 1 / v : Double.POSITIVE_INFINITY;
	}

	/**
	 * Returns the expression: log(x,base).
	 */
	public static double log(double x, double base) {
		// log(x,e)=log(x,base)*log(base,e)
		return Math.log(x) / Math.log(base);
	}

	/**
	 * Returns x satisfying the equation: y = pow(x,v).
	 */
	public static double pow(double y, double v) {
		// y=pow(x,v) -> pow(y,1/v)=pow(pow(x,v),1/v)=x
		double x = Math.pow(y, 1 / v);
		// System.out.println(y+"=pow("+x+","+v+")["+Math.pow(x,v)+"]"); //
		// check
		return x;
	}

	/**
	 * Returns the expression: min([min1..max1]*[min2..max2]) where
	 * [min1..max1] is more or equal 0.
	 */
	public static double productMinP(double min1, double max1, double min2) {
		if (min2 >= 0)
			return min1 * min2;
		else
			return max1 * min2;
	}

	/**
	 * Returns the expression: max([min1..max1]*[min2..max2]) where
	 * [min1..max1] is more or equal to 0.
	 */
	public static double productMaxP(double min1, double max1, double max2) {
		if (max2 >= 0)
			return max1 * max2;
		else
			return min1 * max2;
	}

	/**
	 * Returns the expression: min([min1..max1]*[min2..max2]) where
	 * [min1..max1] is less or equal to 0.
	 */
	public static double productMinN(double min1, double max1, double max2) {
		if (max2 >= 0)
			return min1 * max2;
		else
			return max1 * max2;
	}

	/**
	 * Returns the expression: max([min1..max1]*[min2..max2]) where
	 * [min1..max1] is less or equal to 0.
	 */
	public static double productMaxN(double min1, double max1, double min2) {
		if (min2 >= 0)
			return max1 * min2;
		else
			return min1 * min2;
	}

	/**
	 * Returns the expression: min([min1..max1]*[min2..max2]).
	 */
	public static double productMin(double min1, double max1, double min2,
			double max2) {
		// exp1 >= 0
		if (min1 >= 0)
			return productMinP(min1, max1, min2);
		// exp1 <= 0
		else if (max1 <= 0)
			return productMinN(min1, max1, max2);
		// exp1 changes sign
		else {
			// exp2 >= 0
			if (min2 >= 0)
				return min1 * max2;
			// exp2 <= 0
			else if (max2 <= 0)
				return max1 * min2;
			// exp2 changes sign
			else {
				return Math.min(max1 * min2, min1 * max2);
			}
		}
	}

	/**
	 * Returns the expression: max([min1..max1]*[min2..max2]).
	 */
	public static double productMax(double min1, double max1, double min2,
			double max2) {
		// exp1 >= 0
		if (min1 >= 0)
			return productMaxP(min1, max1, max2);
		// exp1 <= 0
		else if (max1 <= 0)
			return productMaxN(min1, max1, min2);
		// exp1 changes sign
		else {
			// exp2 >= 0
			if (min2 >= 0)
				return max1 * max2;
			// exp2 <= 0
			else if (max2 <= 0)
				return min1 * min2;
			// exp2 changes sign
			else {
				return Math.max(min1 * min2, max1 * max2);
			}
		}
	}

//	/**
//	 * Adjust the expression exp2 so that:
//	 * min([min1..max1]*[min2..max2]) >= min where
//	 * [min1..max1] >= 0.
//	 */
//	static public void productSetMinP(double min, double min1, double max1,
//			VarReal var) throws RuntimeException {
//		if (min == 0) {
//			if (min1 > 0)
//				var.setMin(0);
//		} else {
//			double v = min > 0 ? max1 : min1;
//			if (v != 0) {
//				double min2 = min / v;
//				var.setMin(min2);
//			}
//		}
//	}
//
//	/**
//	 * Adjust the expression exp2 so that:
//	 * min([min1..max1]*[min2..max2]) <= max where
//	 * [min1..max1] >= 0.
//	 */
//	static public void productSetMaxP(double max, double min1, double max1,
//			FloatExp exp2) throws Failure {
//		if (max == 0) {
//			if (min1 > 0)
//				exp2.setMax(0);
//		} else {
//			double v = max > 0 ? min1 : max1;
//			if (v != 0) {
//				double max2 = max / v;
//				exp2.setMax(max2);
//			}
//		}
//	}
//
//	/**
//	 * Adjust the expression exp2 so that:
//	 * min([min1..max1]*[min2..max2]) >= min where
//	 * [min1..max1] <= 0.
//	 */
//	static public void productSetMinN(double min, double min1, double max1,
//			FloatExp exp2) throws Failure {
//		if (min == 0) {
//			if (max1 < 0)
//				exp2.setMax(0);
//		} else {
//			double v = min > 0 ? min1 : max1;
//			if (v != 0) {
//				double max2 = min / v;
//				exp2.setMax(max2);
//			}
//		}
//	}
//
//	/**
//	 * Adjust the expression exp2 so that:
//	 * min([min1..max1]*[min2..max2]) <= max where
//	 * [min1..max1] <= 0.
//	 */
//	static public void productSetMaxN(double max, double min1, double max1,
//			FloatExp exp2) throws Failure {
//		if (max == 0) {
//			if (max1 < 0)
//				exp2.setMin(0);
//		} else {
//			double v = max > 0 ? max1 : min1;
//			if (v != 0) {
//				double min2 = max / v;
//				exp2.setMin(min2);
//			}
//		}
//	}
//
//	/**
//	 * Adjust the expression exp2 so that:
//	 * min([min1..max1]*[min2..max2]) >= min.
//	 */
//	static public void productSetMin(double min, FloatExp exp1, FloatExp exp2)
//			throws Failure {
//		double min1, max1;
//		// exp1 >= 0
//		if ((min1 = exp1.min()) >= 0) {
//			productSetMinP(min, min1, exp1.max(), exp2);
//		}
//		// exp1 <= 0
//		else if ((max1 = exp1.max()) <= 0) {
//			productSetMinN(min, min1, max1, exp2);
//		} else // exp1 changes sign
//		{
//			if (min > 0) {
//				double m = min1 / min;
//				double M = max1 / min;
//				exp2.removeRange(m, M);
//			}
//		}
//	}
//
//	/**
//	 * Adjust the expression exp2 so that:
//	 * max([min1..max1]*[min2..max2]) <= max.
//	 */
//	static public void productSetMax(double max, FloatExp exp1, FloatExp exp2)
//			throws Failure {
//		double min1, max1;
//		// exp1 >= 0
//		if ((min1 = exp1.min()) >= 0) {
//			productSetMaxP(max, min1, exp1.max(), exp2);
//		}
//		// exp1 <= 0
//		else if ((max1 = exp1.max()) <= 0) {
//			productSetMaxN(max, min1, max1, exp2);
//		} else // exp1 changes sign
//		{
//			if (max < 0) {
//				double m = max1 / max;
//				double M = min1 / max;
//				exp2.removeRange(m, M);
//			}
//		}
//	}

	/**
	 * Returns the expression: max(sqr(min),sqr(max)).
	 */
	public static double sqrMax(double min, double max) {
		return Math.max(min * min, max * max);
	}

	/**
	 * Returns the expression: min(sqr(min),sqr(max)).
	 */
	public static double sqrMin(double min, double max) {
		// min >= 0 && max >= 0
		if (min >= 0)
			return min * min;

		// min < 0 && max >= 0
		if (max >= 0)
			return 0;

		// min < 0 && max < 0
		return max * max;
	}

	public static void doAssert(boolean v, String s) {
		if (v)
			return;
		System.out.println("Assertion failed: " + s);
	}

	public static void assertMinMax(double min, double max) {
		doAssert(!isNan(min), "min not NaN");
		doAssert(!isNan(max), "max not NaN");
		doAssert(min <= max, "min <= max");
	}

} // ~ Real




© 2015 - 2024 Weber Informatics LLC | Privacy Policy