[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Axiom-developer] [Q] How to classify # integrate(log(%i+z^2), z)

From: William Sit
Subject: Re: [Axiom-developer] [Q] How to classify # integrate(log(%i+z^2), z) -> 2 ?
Date: Tue, 15 Feb 2005 09:22:11 -0500

Hi Bill and Vladimir:

It turns out, as usual, there is no such thing as a simple explanation. 

================ Equality of Functions =======================

[WS] I'm not sure, because you can use

 (4) -> complexIntegrate(log(%i+z^2),z)
 to obtain one form.

> That is true, but it is a different problem and it doesn't make
> the first result correct (returning two equivalent expressions).
> To me, this is still a bug - although admittedly not a very serious
> bug since Axiom only claims to "return all possible values" - not
> that these answers would necessarily all be unique.

> -> #integrate(log(%i+z^2), z)
> 2
> mean that in fact the user would have 2 identical answers,
> and if we ask AXIOM to calculate
> [snipped]
> Even more, if these 2 answers returned by AXIOM for
> integrate(log(%i+z^2), z) are NOT identical, it is
> obviously a math bug. The must be the same (but maybe
> of different form).

As functions, the two results returned are NOT identical in the sense that the
domains (if division by 0 is not allowed) are different. If division by 0 is
allowed (by evaluating via some limit process), then they would be identical
(but Axiom or any other system cannot be expected to automatically perform this
type of verification without further user instruction or code, and this should
be on a "wish list", not a "bug list"). Even assuming that these two results are
identical as mathematical functions, this brings us to the question of what does
"identical" or "equality" mean in symbolic computation. Do we have an algorithm,
given two expressions in EXPR INT or EXPR COMPLEX INT (or even more generally
EXPR whatever), to say that they are mathematically equivalent as functions?
(isn't this undecidable?)

================== Scope of "integrate" ======================

 Using integrate when the integrand involves complex values and
 ask for real forms does not sound correct.

> I don't understand your objection. The expression `log(%i+z^2)'
> does not contain any parameters. It makes perfectly good sense
> to me to integrate this complex-valued function over the real
> line z. I don't think that using `integrate' is "asking for real
> forms". What are "real forms"? The expressions returned by Axiom
> for both `integrate' and `complexIntegrate' can involve complex
> quantities and both (implicitly) assume that the variable of
> integration is real-valued.

My mistake ("real form"). Sorry. I believe the operation integrate is for
anti-derivative only, not to do what you want (which as you recognized
encroaches on contour integration).

========= Differences between "integrate" and "complexIntegrate" ====

> The Axiom Book has the following to say about integration (page
> 110):
> "When real parameters are present, the form of the integral can
> depend on the signs of some expressions. Rather than query the user
> or make sign assumptions, Axiom returns all possible answers.

I wish the sign assumptions are given and associated with the possible answers.
However, I also have some idea why this is not done (see below). 

> The integrate operation generally assumes that all parameters are
> real. The only exception is when the integrand has complex valued
> quantities.
> If the parameter is complex instead of real, then the notion of
> sign is undefined and there is a unique answer. You can request
> this answer by "prepending" the word "complex" to the command name
> ..."
> So the issue has to do only with assumptions about parameters.

No, two different algorithms may be involved here. For example, using
"integrate(log((a+%i)*(a-%i)+z^2,z)" Axiom is "smart enough" to return only one
branch, realizing that a^2+1 is always positive when a is assumed real. However,
as if to emphasize the difference between "integrate" (over EXPR COMPLEX INT)
and "complexIntegrate", the "integrate" routine "simplifies" sqrt(-1) to %i, but
the "complexIntegrate" routine does not! In other words, the answer in
"integrate" looks more "complex", and the answer in "complexIntegrate", more
"real". The two answers are also different in structure besides this but are
obviously mathematically the same (certainly for real parameter a, and even for
complex parameter a). I am not sure if the difference is due to lack of
sophistication in simplification or not (simplification is NOT a simple problem,
requiring the notion of canonical form).

(19) -> integrate(log((a+%i)*(a-%i)+z^2),z)

      +------+          | 2         2    2
      | 2         2%i z\|a  + 1  + z  - a  - 1           2    2
   %i\|a  + 1 log(----------------------------) + z log(z  + a  + 1) - 2z
                            2    2
                           z  + a  + 1
                                  Type: Union(Expression Complex Integer,...)
(20) -> complexIntegrate(log((a+%i)*(a-%i)+z^2),z)

                        +---------+                            +---------+
        +---------+     |    2               +---------+       |    2
        |    2         \|- 4a  - 4  + 2z     |    2         - \|- 4a  - 4  + 2z
       \|- 4a  - 4 log(-----------------) - \|- 4a  - 4 log(-------------------)

                               2                                     2
               2    2
       2z log(z  + a  + 1) - 4z
                                             Type: Expression Complex Integer

=========== Should "integrate" over EXPR COMPLEX INT be allowed ======== 
> Page 370:
> "The package FunctionSpaceIntegration provides the top-level
> integration operation, integrate, for integrating **real-valued
> elementary functions**."
> Since `log(%i+z^2)' is of type 'Expression Complex Integer' it
> might be considered a bug that there is an `integrate' function
> with the signature
> [snipped]
> [1]  signature:   (EXPR COMPLEX INT,SYMBOL) -> Union(
>                        EXPR COMPLEX INT,
>                        LIST EXPR COMPLEX INT)

Maybe. But the above example shows that there are situations where one may want
to allow that, because it is not always easy to know (especially in a chain of
computation) that an intermediate result fed to "integrate" is a "real-valued
elementary function" or not.

========= Differences between "integrate" and "complexIntegrate" ====

> ---------
> In contrast
> (12) -> complexIntegrate(%% 10,z)
>  Function Selection for complexIntegrate
>       Arguments: (EXPR COMPLEX INT,VARIABLE z)
>       implemented: slot (Expression (Complex (Integer)))
>         (Expression (Complex (Integer)))(Symbol) from
> -----------
> It is not clear to me what exactly is the intended difference
> between the domains FSINT(COMPLEX INT,EXPR COMPLEX INT) and

I think the reason for two different integration routines is to provide more
information when the integrand involves a real parameter.

========== Documentation ================

> Further on page 372 the Book says:
> "If the parameters and the variables of integration can be
> complex numbers rather than real, then the notion of sign is
> not defined. In this case all the possible answers can be
> expressed as one complex function. To get that function, rather
> than a list of real functions, use complexIntegrate, ..."
> I think the reference to "variables of integration" must be
> incorrect here, otherwise we would be talking about contour
> integrals, residuals, etc. and that seems like a very different
> subject - one that unfortunately Axiom doesn't seem to address :(

In these packages, I believe the only meaning for "integrate" is
anti-differentiation, so it makes perfectly good sense to say the dummy variable
is real or complex.

===== Should %i be treated as a parameter (symbol) in "integrate" ==============

The interpreter selection, in the integration discussed, over EXPR COMPLEX INT,
must be from the signature [7] you gave, resulting in [1] above:

> )di op integrate
> [7] (D2,Symbol) -> Union(D2,List D2) from FunctionSpaceIntegration(
>          D4,D2)
>          if D4 has Join(EuclideanDomain,OrderedSet,
>          CharacteristicZero,RetractableTo Integer,
>          LinearlyExplicitRingOver Integer) and D2 has Join(
>          TranscendentalFunctionCategory,PrimitiveFunctionCategory,
>          AlgebraicallyClosedFunctionSpace D4)

Since the algorithm is categorical, the algorithm for integration will NOT (AND
SHOULD NOT) be aware of special properties of %i (or ANY particular element
other than 0 and 1 in the ground domain). ONLY the COMPLEX INT domain knows,
which will simplify %i^2 to -1, and the effect on the integration algorithm
depends on WHEN this simplification is done, not just limited to pre-processing
and post-processing. For example, 

(24) -> integrate(log((a^2+1)+z^2),z)

             +------+      | 2
             | 2          \|a  + 1            2    2
   (24)  - 2\|a  + 1 atan(---------) + z log(z  + a  + 1) - 2z
                                          Type: Union(Expression Integer,...)

gave yet a third form of the same integral (compare to (19), (20) above). This
third form suggests that the simplification of (a+%i)(a-%i) to a^2+1 is not done
at preprocessing time but within the integration routine.

When you perform an integration of a complex-valued function in a real variable,
it is reasonable to regard the complex constants as parameters during the
integration process unless such integration is outlawed to begin with (but see
above for one reason not to outlaw it). One would treat complex constants the
same way when differentiating with respect to a real variable. 

At what point the underlying domain simplifies a computation and how it does it
may affect the form of the answer. This is nothing new, especially for
elementary functions and special functions, which are involved in many

On the other hand, complexIntegrate SHOULD be aware of the property of %i, and
it does. The package that implements complexIntegrate is 
FunctionSpaceComplexIntegration (FSCINT) as given in [1] above.

========== Is this a bug? How to fix it? Alternatives? ==========

 Axiom may (I am not sure) have interpreted %i as a parameter
 with no special property.
> If that is true, then surely that is a bug. Right?
> If it is the case, this is certainly a bug as %i has a special,
> a unique meaning in AXIOM, isn't is so?

Not necessarily, as discussed above under "Should %i be ...".

If you consider this a bug, how would you fix it? 

To really understand how the branching occurs in "integrate", one will have to
study the integration algorithm (a very complicated procedure). I don't have the
time (nor competence) to do this, so let us consider a plausible and simplified
scenario for the sake of argument. If as the documentation says, "the notion of
sign is not defined" for COMPLEX INT, one may wish the algorithm to have failed 
when it does something like "if f > 0".  However, "failed" would be equivalent
to "outlawing" it, so let's see if we can "fix" it.

Scenario: Assume that f has been simplified. The "integrate" routine performs a
query to see if there is a function > (or related functions like sign) for the
domain containing the expression f and if yes, it performs branching based on
the result of the sign of f. Otherwise, make a declarative (proviso) that f > 0,
and continue based on that assumption and a similar one for f < 0, resulting in
two branches, say.

This would explain why we have two branches over COMPLEX INT (when %i is
involved) or POLY INT (when there is a real-valued parameter), and only one over
INT (when neither %i nor a parameter is involved).  Under this scenario, the
two-branch result would be unavoidable in "integrate(log(%i+z^2),z)" over
COMPLEX INT. If, as I wish, the returned list had provided info on the
declarative assumptions, we would have known the assumptions, even if it would
not make sense, like %i > 0 (this may be the reason for not giving the
assumptions; the generality may give meaningless conditions, while the answers
still make sense). The true scenario is probably not that simple. 

But in any case, to fix this, you will need to examine every instance in the
code for "integrate" where branching based on parts of the integrand may occur
and then handle the special cases (%i is only one, any complex constant may
appear in the integrand). 

So why not simply use complexIntegrate?

I think this is NOT a bug. 

As a possible alternative, you may want to write a simple package to convert
integrate to complexIntegrate WHENEVER the integrand is COMPLEX INT---but
beware.  Axiom has no reason to prevent the instantiation of 


To write the conversion, you have to intercept that. Moreover, there may be
situations when you DON'T want to do that, when the branches are really
different, for example, in integrate(log(%i+a+z),z) where a is real. 

So in the end, it is better that the user be aware (and as you pointed out, this
is documented) of the difference between integrate and complexIntegrate and use
each appropriately.

====== The Consequence of the Categorical Nature of Algorithms =======

The fact that algorithms are categorical in Axiom is the reason for some other
"strange" behaviors. I have written on this problem (about Axiom being inclusive
and not exclusive) in

[#87 solve(x + 1.1, 0.001) fails] reply and experimenting with
         new format

Often, what is needed is OTHER algorithms to handle the situation (here
complexIntegrate, and contour integration perhaps, and in the case of
solve(x+1.1,0.001), a numerical solver). 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]