Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Hello, @ortollj! After studying your code, I believe the problem comes from the fact that intY0 is a function of two variables---x and z, in this case, as you can see from the output your code generates. The thing is that definite_integral can integrate only one-variable functions. That is why you get the message

ValueError: The function to be integrated depends on 2 variables (x, z), and so cannot be integrated in one dimension. Please fix additional variables with the 'params' argument

What does this mean? That Sage has noticed that there are more than one variable, and you should give the remaining variables some numerical value in order to perform the numerical integral. Basically, Sage is asking you to do something like this:

intYX00 = numerical_integral(intY0,eqLimitL[2].rhs(),eqLimitL[3].rhs(), params=[0])

That specifies that this integral is to be performed on the first variable ($x$), after replacing $z=0$. In short, if you have a $n$-variable function, you need to specify $n-1$ numerical values for the $n-1$ last variables, so that numerical_integral can perform the integral using the first variable of the function. To better understand this, consider the following example:

f(x,y,z) = x^2 * y * z
numerical_integral(f, 0, 1, params=[2,3])

This is effectively equivalent to the integral $$\int_0^16x^2\;dx$$ since the variables $y$ and $z$ have been given the values $2$ and $3$, respectively.

This brings me to the following matter: why did I use params=[0] and no other value? In this particular case, the value I choose is irrelevant, since your intY0 is defined to be a function on $(x,z)$, but in reality its value only depends on $x$. This example will clarify this words:

f(x,y) = x^2
numerical_integral(f, 0, 1, params=[0])

Since I defined $f$ to be a function of $(x,y)$, I need to use the params argument to fix the value of $y$. However, since the value of $f$ does NOT depend on $y$, I can use anything that I please, even params=[y] itself. It won't make any difference. Of course, if this function were $f(x,y)=x^2y^3$, then there would be a different result for every (numerical) value I choose for $y$ (e.g., params=[2] to integrate $8x^2$). Notice that in this particular case, I can NOT use params=[y], because that would keep $f$ as a two variable function.

Now, when you make

fsgn(x) = -1
intY00 = intY0.substitute_function(sgn,fsgn)

apparently substitute_function converts intY0 into a simple expression (not a function that maps $(x,z)$, just a formula.) You can check this if you add print(intY00). You will notice the part (x,z) |--> is now missing. In particular, now intY00 is a formula whose value depends only on $x$, but not on $z$. So, when you pass it to numerical_integral, Sage assumes it is a one-variable function, and that way it is able to integrate.

I believe that answers your question. However, there are a few additional observations that could help you:

  1. I can see that you used assume(0<x<1); I also did that. I was quite surprised to see that this had no effect on the sgn function. Indeed, here is an example that should return 1, but does not:

    var('x', domain='real')
    assume(0<x<1)
    sgn(x)
    

    However, that should not be a problem, since the integration algorithm will anyway evaluate the sgn function and return an adequate value.

  2. I recommend in this case to remove the variable $z$ from the definition of your functions, since their values do not depend on that variable. That should eliminate the necessity of using the params argument to eliminate $z$, when it is not needed in the first place.

  3. Unfortunately, in this particular case, you will still need to manually replace the value for sgn, since intY0 has this expression in it:

    sgn(4*x^2*e^(2/9*I*pi) + e^(4/9*I*pi) - 2*e^(2/9*I*pi) + 1)
    

    Sage seems unable to deal with this expression. Indeed, I get the message

    TypeError: unable to coerce to a real number
    

    However, replacing only that part with fsgn(x) or '(-1)' (leaving the other sgn) in intY0, returns the correct result without any problem. BUT BE CAREFULL: For complex numbers $z$, the signum function is defined by

    $$\operatorname{sgn}(z) = \frac{z}{|z|}.$$

    Unfortunately, the last bad news is that numerical_integral cannot deal with complex functions. Hopefully, there is a solution to this problem, but I can think of it right now...

I hope this answers your questions!