-3

If I want to solve the variable (p) from the following equation, where everything else is known :

enter image description here

Is there a method out there in Java that would let me do this?

I can do it with my calculator, and I am sure there is something out there for Python - so I know it's doable. Thank you.

Here is quick reference graph:

enter image description here

The x-value with the circle would be the (p) that satisfies both sides of the equation. But calculating all values, then checking for zero would not be the most efficient way of doing this.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
Edv Beq
  • 910
  • 3
  • 18
  • 43

2 Answers2

1

You would have to implement the function giving the difference of both sides of the equation and then some kind of univariate solver. Due to the convexity of this equation on the positive axis, all the classical methods, esp. the secant method, should work flawlessly.

class myfunc {
    public myfunc(int nn, int cc, double aalpha) {...}

    public double eval(double p) {
        double sum = 1;
        double term = 1;
        for(int i = 1; i<=c; i++) {
             term *= (n*p)/i;
             sum += term;
         }
         return sum*Math.exp(-n*p) - alpha;
     }
}

..............

public double secant(myfunc f, double a, double b) {
    double fa = f.eval(a);
    double fb = f.eval(b);
    while(Math.abs(b-a)>1e-10) {
        double c = (a*fb-b*fa)/(fb-fa);
        a=b; fa = fb;
        b=c; fb = f.eval(b);
    }
    return b;
}

and you would call this with something like

p = secant(new myfunc(n,c,alpha), 0, 0.1);

It turns out that the secant method is unstable, use modified regula falsi

import java.lang.*;

interface RealFunc {
    public double eval(double x);
}

class myfunc implements RealFunc {

  int c,n;  
  double alpha;

  public myfunc(int nn, int cc, double aalpha) {
    c=cc; n=nn; alpha = aalpha;
  }

  public double eval(double p) {
    double sum = 1;
    double term = 1;
    for(int i = 1; i<=c; i++) {
        term *= (n*p)/i;
        sum += term;
     }
     return sum*Math.exp(-n*p) - alpha;
   }
}


public class SecantSolverSO34980366 {

  static public double illinois(RealFunc f, double a, double b) {
        double fa = f.eval(a);
        double fb = f.eval(b);
        while(Math.abs(b-a) > 1e-10) {
        //System.out.printf("a:f(%16.12f) = %16.12f | b: f(%16.12f) = %16.12f \n ",a,fa,b,fb);
          double c = (a*fb-b*fa)/(fb-fa);
          double fc = f.eval(c);
          if( fa*fc < 0 ) {
            fa *= 0.5;
          } else {
            a = b; fa = fb;
          }
          b = c; fb = fc;
      }
      return b;
  }


  public static void main(String[] args) {
    int n = 1;

    for(double alpha = 0.2; alpha <=1.0001; alpha += 0.1) {
        System.out.printf("alpha=%4.2f: ", alpha);
        for(int c = 2; c < 15; c+=2) {

            double p = illinois(new myfunc(n,c,alpha), 0.,(c+13.0)/n);
            System.out.printf("(c=%2d):%12.9f  ",c,p);
        }
        System.out.printf("\n");
    }

  }
}
Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51
  • Can you please provide a few more details how to implement. For example: What p-values are you passing in the "eval" function? What is the order of operation? Thanks again. – Edv Beq Jan 25 '16 at 14:09
  • since these are cumulative probabilities for a Poisson process, one has alpha in (0,1) and would expect that p is rather small. Thus values a=0 and b=0.1 should be universally sensible, even if the actual result is much larger. – Lutz Lehmann Jan 25 '16 at 14:58
  • @LultzL Last favor: Could you please write the function- maybe it will sense then. I am on track with the cumulative probability distribution being 1. I was also thinking since n is fixed I could just write np = lambda - then divide after i find its value. Thanks a lot once again. – Edv Beq Jan 25 '16 at 18:37
1

There are several numerical methods in Apache Commons Math for finding roots of functions. See the documentation for numerical methods. There are probably many other existing libraries for numerical methods in Java.

As for solving such equations symbolically, I don't know the best way to go about it in Java. You could compile a computer algebra system, let's say Maxima, using a JVM-based Lisp (I know of ABCL but there may be others).

Solving equations symbolically is difficult and Maxima's symbolic solver isn't too powerful. But with some coaxing, I get the following, which you'll want to verify before using it:

(1 - alpha) c! = gamma_greek(c + 1, n*p)

where gamma_greek is the lower incomplete gamma function. So you could solve this without invoking a root-finding algorithm if you have an implementation of the inverse of the lower incomplete gamma function. It appears that Apache Commons Math does not, although other libraries might. See also this question on SO. Good luck and have fun.

Community
  • 1
  • 1
Robert Dodier
  • 16,905
  • 2
  • 31
  • 48
  • Thank you for the post. I am not trying to solve it symbolically. All the constants would be given a value - and (p) basically has to satisfy both sides. I'll take a look at the stuff. – Edv Beq Jan 25 '16 at 04:33