Solver.java

  1. package org.opentrafficsim.core.math;

  2. import org.djunits.value.ValueException;

  3. /**
  4.  * Solvers for simple equations.
  5.  * <p>
  6.  * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  7.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
  8.  * <p>
  9.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version Dec 10, 2015 <br>
  10.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  11.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  12.  */
  13. public final class Solver
  14. {
  15.     /**
  16.      *
  17.      */
  18.     private Solver()
  19.     {
  20.         // cannot be instantiated.
  21.     }

  22.     /**
  23.      * Solve quadratic equation <cite>ax<sup>2</sup>+bx+c=0</cite> for <cite>x</cite>. Degenerate case <cite>a == 0</cite> is
  24.      * allowed.
  25.      * @param a double; the coefficient of <cite>x<sup>2</sup></cite>
  26.      * @param b double; the coefficient of <cite>x</cite>
  27.      * @param c double;
  28.      * @return double[]; array with zero, one, or two elements (depending on the number of solutions of the equation)
  29.      */
  30.     public static double[] solve(final double a, final double b, final double c)
  31.     {
  32.         if (Math.abs(a) < 1E-8) // rounding errors will yield incorrect solutions if we allow very small a
  33.         {
  34.             // Degenerate; linear equation
  35.             return solve(b, c);
  36.         }
  37.         // Quadratic equation
  38.         double discriminant = b * b - 4 * a * c;
  39.         if (discriminant < 0)
  40.         {
  41.             return new double[0];
  42.         }
  43.         if (0 == discriminant)
  44.         {
  45.             return new double[]{-b / 2 / a};
  46.         }
  47.         discriminant = Math.sqrt(discriminant);
  48.         return new double[]{(-b + discriminant) / 2 / a, (-b - discriminant) / 2 / a};
  49.     }

  50.     /**
  51.      * Solve a quadratic or linear equation and return the solution that is closest (but not less than) a boundary.
  52.      * @param lowerBound double; minimum value of good solution
  53.      * @param a double; quadratic coefficient
  54.      * @param b double; linear coefficient
  55.      * @param c double; value of the quadratic function for x==0
  56.      * @return double; the solution that is closest (but not less than) a boundary
  57.      * @throws ValueException if there is no acceptable solution
  58.      */
  59.     public static double firstSolutionAfter(final double lowerBound, final double a, final double b, final double c)
  60.         throws ValueException
  61.     {
  62.         double[] solutions = solve(a, b, c);
  63.         if (0 == solutions.length)
  64.         {
  65.             throw new ValueException("No solutions");
  66.         }
  67.         else if (1 == solutions.length)
  68.         {
  69.             if (solutions[0] >= lowerBound)
  70.             {
  71.                 return solutions[0];
  72.             }
  73.             throw new ValueException("Only one solution and it is before lowerBound");
  74.         }
  75.         // Two solutions
  76.         if (solutions[0] < lowerBound && solutions[1] < lowerBound)
  77.         {
  78.             throw new ValueException("Both solutions are before lowerBound");
  79.         }
  80.         if (solutions[0] < lowerBound)
  81.         {
  82.             return solutions[1];
  83.         }
  84.         if (solutions[1] < lowerBound)
  85.         {
  86.             return solutions[0];
  87.         }
  88.         return Math.min(solutions[0], solutions[1]);
  89.     }

  90.     /**
  91.      * Solve linear equation <cite>ax+b=0</cite> for <cite>x</cite>.
  92.      * @param a double; the coefficient of <cite>x</cite>
  93.      * @param b double;
  94.      * @return double[]; array with one or zero elements (depending on the number of solutions of the equation). The case where
  95.      *         both <cite>a</cite> and <cite>b</cite> are zero returns an array of length 0.
  96.      */
  97.     public static double[] solve(final double a, final double b)
  98.     {
  99.         if (0 == a)
  100.         {
  101.             // Degenerate; no solution (or infinitely many solutions)
  102.             return new double[0];
  103.         }
  104.         return new double[]{-b / a};
  105.     }

  106. }