Menu

Float precision, significant digit option

Help
Luzius
2015-08-26
2015-08-26
  • Luzius

    Luzius - 2015-08-26

    I'm trying to solve an equation system with about 150 variables. Precision is not important, so I set precision to 0.0001. Jacop still took hours to find a solutions. Digging into this a little deeper, I found out that Jacop spent most of its time playing with insignificant digits, i.e. narrowing down ranges like [9999.99 .... 10000.01]. In case of large numbers, I do not care about those digits. I suggest to introduce an option to specify the precision relative to the size of the number. In a quick hack, I already did so by changing FloatDomain as follows:

    static double precision = 1e-11;
    static double multiplier = 1e16 * precision;
    
    public static double precision() {
        return precision;
    }
    
    public static void setPrecision(double p) {
        precision = p;
        multiplier = 1e16 * precision;
    }
    
    public static double epsilon(double f) {
        return Math.max(precision, java.lang.Math.ulp(f) * multiplier);
    }
    

    Furthermore, I replaced a number of calls to precision() by calls to epsilon(f), for example in the satisfied() method of PeqQ:

    public boolean satisfied() {
        return p.singleton() && q.singleton() && 
        java.lang.Math.abs(p.min() - q.max()) <= FloatDomain.epsilon(p.min()) && 
        java.lang.Math.abs(p.max() - q.min()) <= FloatDomain.epsilon(q.min());
    }
    

    As a result, Jacop now solves within seconds what used to take many hours.

    Maybe that should become an official feature?

    Note that my changes are a quick hack, I just guessed what values to pick for the epsilon(f) parameter f.
    If interested, I might also be able to provide a patch.

    PS: I suggest to move away from sourceforge, maybe to github? See http://danluu.com/slashdot-sourceforge/

     
  • kris

    kris - 2015-08-26

    Hi!

    Thanks for your comments and suggestions. In fact, in the satisifed method we shoud probably use epsilon method and not precision since the precision of number representation in floating-points changes depending what number you have (small or very big, for example). Your suggestions introduce basically additional scaling in addition to ulp (unit at last position) taht already is different for different numbers. I need to think about it and possible way to introduce it in a coherent and general way.

    BTW, what constraints do you use that the method satisfied is called? Normally only consistency method is called. Do you use reified constraints? Did you replaced precision by epsilon in other methods as well?

    Best,
    /Kris

     
  • kris

    kris - 2015-08-26

    Hi!

    I have checked the code a little bit more and there is one important place that we use epsilon. In method org.jacop.floats.FloatInterval.singleton() we compare value (max-min) with the epsilon and decide whether the number is supposed to be treated as single value (this will stop further search on this variable). Currently we use the value of epsilon based on difference between max and min (in your case it is 10000.01-9999.99=0.02) and ulp for 0.02 is 3.469e-18) when we will change to take ulp of max, for example than it will be 1.819e-12. It is 6 orders of magnited larger but will probably not help significantly in your case since the specified precision is much higher :(

    This however might be a better solution, in general.

    Best,
    /Kris

     

Log in to post a comment.