commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Luc Maisonobe <...@spaceroots.org>
Subject Re: [MATH] What is the derivative of 0^x
Date Tue, 27 Aug 2013 11:35:16 GMT
Le 26/08/2013 22:37, Ajo Fod a écrit :
> On a side note. Given a derivative structure ds. Wouldn't it be nice to
> generate a constant derivative structure with something like:
> 
> ds.getConstant(dobule value);
> Currently I"m doing something like:
> new DerivativeStructure(length, order, value);  ... seesm more verbose than
> necessary when I have order and length information in existing ds all
> around.

Good idea. I have committed it as r1517789, simply renaming the function
createConstant instead of getConstant.

Thanks for the suggestion.
Luc

> 
> Cheers,
> Ajo.
> 
> 
> On Mon, Aug 26, 2013 at 8:23 AM, Ajo Fod <ajo.fod@gmail.com> wrote:
> 
>> With regards to what is happening in DsCompiler.pow():
>> IMHO, when a==0 and x>=0 the function is well behaved because log|a| ->
>> Inf slower than a^x -> 0. I got to this by simulation.
>> One could probably get to something more conclusive using L'Hopital rule :
>> http://en.wikipedia.org/wiki/L%27H%C3%B4pital%27s_rule.
>> There is one about xlog(x) behavior as x->0+.
>>
>> So, I propose this:
>>
>>         if (a == 0) {
>>             if (operand[operandOffset] >= 0) {
>>
>>                 for (int i = 0; i < function.length; ++i) {
>>                     function[i] = 0;
>>                 }
>>             }else{
>>
>>                 for (int i = 0; i < function.length; ++i) {
>>                     function[i] = Double.NaN;
>>                 }
>>             }
>>         } else {
>>
>>
>> in place of :
>>
>>         if (a == 0) {
>>             if (operand[operandOffset] == 0) {
>>                 function[0] = 1;
>>                 double infinity = Double.POSITIVE_INFINITY;
>>
>>                 for (int i = 1; i < function.length; ++i) {
>>                     infinity = -infinity;
>>                     function[i] = infinity;
>>                 }
>>             }
>>         } else {
>>
>>
>> PS: I think you made a change to DSCompiler.pow too. If so, what happens
>> when a=0 & x!=0  in that function?
>>
>>
>> On Mon, Aug 26, 2013 at 12:38 AM, Luc Maisonobe <luc@spaceroots.org>wrote:
>>
>>>
>>>
>>>
>>> Ajo Fod <ajo.fod@gmail.com> a écrit :
>>>> Are you saying patched the code? Can you provide the link?
>>>
>>> I committed it in the development version. You just have to update your
>>> checked out copy from either the official
>>>  Apache subversion repository or the git mirror we talked about in a
>>> previous thread.
>>>
>>> The new method is a static one called pow and taking a and x as arguments
>>> and returning a^x. Not to
>>> Be confused with the non-static methods that take only the power as
>>> argument (either int, double or
>>> DerivativeStructure) and use the instance as the base to apply power on.
>>>
>>> Best regards,
>>> Luc
>>>
>>>>
>>>> -Ajo
>>>>
>>>>
>>>> On Sun, Aug 25, 2013 at 1:20 PM, Luc Maisonobe <luc@spaceroots.org>
>>>> wrote:
>>>>
>>>>> Le 24/08/2013 11:24, Luc Maisonobe a écrit :
>>>>>> Le 23/08/2013 19:20, Ajo Fod a écrit :
>>>>>>> Hello,
>>>>>>
>>>>>> Hi Ajo,
>>>>>>
>>>>>>>
>>>>>>> This shows one way of interpreting the derivative for strictly
+ve
>>>>> numbers.
>>>>>>>
>>>>>>>     public static void main(final String[] args) {
>>>>>>>         final double x = 1d;
>>>>>>>         DerivativeStructure dsA = new DerivativeStructure(1,
1, 0,
>>>> x);
>>>>>>>         System.out.println("Derivative of |a|^x wrt x");
>>>>>>>         for (int p = 10; p < 21; p++) {
>>>>>>>             double a;
>>>>>>>             if (p < 20) {
>>>>>>>                 a = 1d / Math.pow(2d, p);
>>>>>>>             } else {
>>>>>>>                 a = 0d;
>>>>>>>             }
>>>>>>>             final DerivativeStructure a_ds = new
>>>> DerivativeStructure(1,
>>>>> 1,
>>>>>>> a);
>>>>>>>             final DerivativeStructure out = a_ds.pow(dsA);
>>>>>>>             final double calc = (Math.pow(a, x + EPS) -
>>>> Math.pow(a, x))
>>>>> /
>>>>>>> EPS;
>>>>>>>             System.out.format("Derivative@%f=%f  %f\n", a, calc,
>>>>>>> out.getPartialDerivative(new int[]{1}));
>>>>>>>         }
>>>>>>>     }
>>>>>>>
>>>>>>> At this point I"m explicitly substituting the rule that
>>>>> derivative(|a|^x) =
>>>>>>> 0 for |a|=0.
>>>>>>
>>>>>> Yes, but this fails for x = 0, as the limit of the finite
>>>> difference is
>>>>>> -infinity and not 0.
>>>>>>
>>>>>> You can build your own function which explicitly assumes a is
>>>> constant
>>>>>> and takes care of special values as follows:
>>>>>>
>>>>>>  public static DerivativeStructure aToX(final double a,
>>>>>>                                         final DerivativeStructure
>>>> x) {
>>>>>>      final double lnA = (a == 0 && x.getValue() == 0) ?
>>>>>>                   Double.NEGATIVE_INFINITY :
>>>>>>                   FastMath.log(a);
>>>>>>      final double[] function = new double[1 + x.getOrder()];
>>>>>>      function[0] = FastMath.pow(a, x.getValue());
>>>>>>      for (int i = 1; i < function.length; ++i) {
>>>>>>          function[i] = lnA * function[i - 1];
>>>>>>      }
>>>>>>      return x.compose(function);
>>>>>>  }
>>>>>>
>>>>>> This will work and provides derivatives to any order for almost any
>>>>>> values of a and x, including a=0, x=1 as in your exemple, but also
>>>>>> slightly better for a=0, x=0. However, it still has an important
>>>>>> drawback: it won't compute the n-th order derivative correctly for
>>>> a=0,
>>>>>> x=0 and n > 1. It will provide NaN for these higher order
>>>> derivatives
>>>>>> instead of +/-infinity according to parity of n.
>>>>>
>>>>> I have added a similar function to the DerivativeStructure class
>>>> (with
>>>>> some errors above corrected). The main interesting property of this
>>>>> function is that it is more accurate that converting a to a
>>>>> DerivativeStructure and using the general x^y function. It does its
>>>> best
>>>>> to handle the special case, but as written above, this does NOT work
>>>> for
>>>>> general combination (i.e. more than one variable or more than one
>>>>> order). As soon as there is a combination, the derivative will
>>>> involve
>>>>> something like df/dx * dg/dy and as infinities and zeros are
>>>> everywheren
>>>>> NaN appears immediately for these partial derivatives. This cannot be
>>>>> avoided.
>>>>>
>>>>> If you stay away from the singularity, the function behaves
>>>> correctly.
>>>>>
>>>>> best regards,
>>>>> Luc
>>>>>
>>>>>>
>>>>>> This is a known problem that we already encountered when dealing
>>>> with
>>>>>> rootN. Here is an extract of a comment in the test case
>>>>>> testRootNSingularity, where similar NaN appears instead of +/-
>>>> infinity.
>>>>>> The dsZero instance in the comment is simple the x parameter of the
>>>>>> function, as a derivativeStructure with value 0.0 and depending on
>>>>>> itself (dsZero = new DerivativeStructure(1, maxOrder, 0, 0.0)):
>>>>>>
>>>>>>
>>>>>> // the following checks shows a LIMITATION of the current
>>>> implementation
>>>>>> // we have no way to tell dsZero is a pure linear variable x = 0
>>>>>> // we only say: "dsZero is a structure with value = 0.0,
>>>>>> // first derivative = 1.0, second and higher derivatives = 0.0".
>>>>>> // Function composition rule for second derivatives is:
>>>>>> // d2[f(g(x))]/dx2 = f''(g(x)) * [g'(x)]^2 + f'(g(x)) * g''(x)
>>>>>> // when function f is the nth root and x = 0 we have:
>>>>>> // f(0) = 0, f'(0) = +infinity, f''(0) = -infinity (and higher
>>>>>> // derivatives keep switching between +infinity and -infinity)
>>>>>> // so given that in our case dsZero represents g, we have g(x) =
0,
>>>>>> // g'(x) = 1 and g''(x) = 0
>>>>>> // applying the composition rules gives:
>>>>>> // d2[f(g(x))]/dx2 = f''(g(x)) * [g'(x)]^2 + f'(g(x)) * g''(x)
>>>>>> //                 = -infinity * 1^2 + +infinity * 0
>>>>>> //                 = -infinity + NaN
>>>>>> //                 = NaN
>>>>>> // if we knew dsZero is really the x variable and not the identity
>>>>>> // function applied to x, we would not have computed f'(g(x)) *
>>>> g''(x)
>>>>>> // and we would have found that the result was -infinity and not
>>>> NaN
>>>>>>
>>>>>> Hope this helps
>>>>>> Luc
>>>>>>
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Ajo.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Fri, Aug 23, 2013 at 9:39 AM, Luc Maisonobe
>>>> <Luc.Maisonobe@free.fr
>>>>>> wrote:
>>>>>>>
>>>>>>>> Hi Ajo,
>>>>>>>>
>>>>>>>> Le 23/08/2013 17:48, Ajo Fod a écrit :
>>>>>>>>> Try this and I'm happy to explain if necessary:
>>>>>>>>>
>>>>>>>>> public class Derivative {
>>>>>>>>>
>>>>>>>>>     public static void main(final String[] args) {
>>>>>>>>>         DerivativeStructure dsA = new DerivativeStructure(1,
1,
>>>> 0,
>>>>> 1d);
>>>>>>>>>         System.out.println("Derivative of constant^x
wrt x");
>>>>>>>>>         for (int a = -3; a < 3; a++) {
>>>>>>>>
>>>>>>>> We have chosen the classical definition which implies c^x
is not
>>>>> defined
>>>>>>>> for real r and negative c.
>>>>>>>>
>>>>>>>> Our implementation is based on the decomposition c^r = exp(r
*
>>>> ln(c)),
>>>>>>>> so the NaN comes from the logarithm when c <= 0.
>>>>>>>>
>>>>>>>> Noe also that as explained in the documentation here:
>>>>>>>> <
>>>>>>>>
>>>>>
>>>>
>>> http://commons.apache.org/proper/commons-math/userguide/analysis.html#a4.7_Differentiation
>>>>>>>>> ,
>>>>>>>> there are no concepts of "constants" and "variables" in this
>>>> framework,
>>>>>>>> so we cannot draw a line between c^r as seen as a univariate
>>>> function
>>>>> of
>>>>>>>> r, or as a univariate function of c, or as a bivariate function
>>>> of c
>>>>> and
>>>>>>>> r, or even as a pentavariate function of p1, p2, p3, p4,
p5 with
>>>> both c
>>>>>>>> and r being computed elsewhere from p1...p5. So we don't
make
>>>> special
>>>>>>>> cases for the case c = 0 for example.
>>>>>>>>
>>>>>>>> Does this explanation make sense to you?
>>>>>>>>
>>>>>>>> best regards,
>>>>>>>> Luc
>>>>>>>>
>>>>>>>>
>>>>>>>>>             final DerivativeStructure a_ds = new
>>>>> DerivativeStructure(1,
>>>>>>>> 1,
>>>>>>>>> a);
>>>>>>>>>             final DerivativeStructure out = a_ds.pow(dsA);
>>>>>>>>>             System.out.format("Derivative@%d=%f\n", a,
>>>>>>>>> out.getPartialDerivative(new int[]{1}));
>>>>>>>>>         }
>>>>>>>>>     }
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Fri, Aug 23, 2013 at 7:59 AM, Gilles
>>>> <gilles@harfang.homelinux.org
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> On Fri, 23 Aug 2013 07:17:35 -0700, Ajo Fod wrote:
>>>>>>>>>>
>>>>>>>>>>> Seems like the DerivativeCompiler returns NaN.
>>>>>>>>>>>
>>>>>>>>>>> IMHO it should return 0.
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> What should be 0?  And Why?
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>> Is this worthy of an issue?
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> As is, no.
>>>>>>>>>>
>>>>>>>>>> Gilles
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>> Thanks,
>>>>>>>>>>> -Ajo
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>
>>>>>
>>>> ------------------------------**------------------------------**---------
>>>>>>>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.**apache.org<
>>>>>>>> dev-unsubscribe@commons.apache.org>
>>>>>>>>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>>>>>>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>>>>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>>>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>>>
>>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>
>>>
>>
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message