pearu / sympycore

Automatically exported from code.google.com/p/sympycore
Other
11 stars 1 forks source link

Review ExtendedNumber #49

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago

Currently ExtendedNumber takes 2 arguments, is_infinity and direction.
It should be sufficient to use only the direction argument.

Also, let's use the definition of oo(theta) from

  http://sympycore.googlecode.com/svn/trunk/doc/html/evaluation_rules.html

that defines well all possible extended numbers and operations
between them. It means that
  undefined = ExtendedNumber(ExtendedNumber(1))

Though, I am not sure whether the direction argument should be
replaced with theta. May be not as 
  ExtendedNumber(1+I)
  ExtendedNumber(exp(2/3*pi*I))
represent examples of the most general ways to specify
directions.

Original issue reported on code.google.com by pe...@cens.ioc.ee on 21 Feb 2008 at 9:54

GoogleCodeExporter commented 9 years ago
I meant
  +oo = ExtendedNumber(1)
  zoo = ExtendedNumber(+oo)
  undefined = ExtendedNumber(0)

Original comment by pe...@cens.ioc.ee on 22 Feb 2008 at 7:52

GoogleCodeExporter commented 9 years ago
I must still sleeping..

  zoo = ExtendedNumber(exp(+oo*I))

as oo(theta) in the evaluation_rules.html would read

  oo(theta) = ExtendedNumber(exp(theta*I))

Original comment by pe...@cens.ioc.ee on 22 Feb 2008 at 7:57

GoogleCodeExporter commented 9 years ago
1.

The choice of parametrization is entirely arbitrary. Whichever makes the code 
simpler
should be used.

2.

Let's not place Calculus data inside numbers; I think there is an important
conceptual distinction to be made. Numbers should be closed with respect to
arithmetic operations, and unambiguously comparable (this can be achieved for
extended numbers by allowing the direction to be an arbitrary complex rational, 
maybe
with some form of magnitude normalization).

99% uses of infinities don't require this generalization. In the cases where 
actually
needed, the most general way to represent an infinity with a complex angle in
Calculus could be as TERMS : {exp(I*theta) : oo}. Then theta can even be 
nonconstant.

When multiplying expr * oo, Calculus could check if the direction of expr is a
rational complex number (note that this includes any whole degree angle or 
rational
multiple of pi -- moving coverage up to 99.99% of cases), and then absorb it 
into the
oo, and otherwise just leave expr*oo as it stands.

3.

With extended numbers defined as oo*something, there is again the possibility of
defining oo as a Calculus singleton and making 'something' a coefficient. This 
works
out poorly if there are separate oo / moo / zoo / nan objects, but with just 
one, it
can be looked for in a sum by doing "if oo in terms.data" which is entirely 
possibly
faster than what we're doing now to handle extended numbers.

The downside is that this would require allowing the term coefficient to be a
Calculus instance (possibly even containing symbols). This means e.g. any code 
that
looks for symbolic parts need to be aware that there can be one in a TERMS
coefficient, but if this only happens when "if oo in terms.data" is True, it 
perhaps
does not add much complexity.

The distributive behavior would be changed to always move the infinity out, 
e.g. oo +
x*oo --> (1+x)*oo; this may be surprising considering how other numbers and 
symbols work.

4.

I've looked a little more closely at how Mathematica handles special cases 
involving
infinities. Interesting examples include:

Infinity - Infinity -> Indeterminate

a Infinity - a Infinity -> a Infinity - a Infinity
Simplify[%] -> Indeterminate

Infinity^a -> Indeterminate
a^Infinity -> Indeterminate

a^(b Infinity) -> a^(b Infinity)
a^(b Infinity) - a^(b Infinity) -> 0

a = x (y + z Infinity)
a - a -> 0

u = (a + b (c + d Infinity))^g -> (a + b (c + d Infinity))^g
u - u -> 0

So it seems that Mathematica does not bother to search deeply into expressions 
for
the presence of infinities when cancelling terms; it only checks whether they 
appear
as linear terms. Having direct powers involving symbolics/infinity evaluate to
Indeterminate avoids erroneous cancellations in simple cases, e.g. by making
Infinity^a - Infinity^a -> Indeterminate.

So Mathematica is not enforcing any kind of rigorous consistency; presumably its
developers have simply found that the current scheme gives a good 
speed/correctness
tradeoff in practical calculations.

Original comment by fredrik....@gmail.com on 22 Feb 2008 at 11:54

GoogleCodeExporter commented 9 years ago
Note that expression

  oo * x

really means

  oo * sign(x)

(if x is complex then replace sign with csign).

So, expressions

  oo * x + oo * y

and

  oo * (x + y)

are different in general and should also treated so:

  oo * x + oo * y -> oo * (sign(x)+sign(y))/2
  oo * (x + y) -> oo * sign(x+y)

Also,
  oo * x + oo * y + oo * z -> oo*(sign((sign(x)+sign(y))/2) + sign(z))/2

It means that any expression that comes in touch with oo in multiplication,
should be replaced with sign(expression).

Expression

  oo*sign(x) + y

is oo*sign(x) when y is finite. But in special cases y could also have infinite
value, say, oo*sign(z). Therefore the above should not be evaluated.
Since the result of

  oo*sign(x)+y

is always a multiple of oo, then it can be rewritten in a canonical form:

  oo*(sign(x)+sign(y)*is_unbounded(y))

where is_unbounded is a symbolic function that returns 1 if it's argument
is in the form oo*sign(z), 0 if y is bounded, and unevaluated if y is symbolic.

The above formalism allows to treat oo as a constant symbol and always write
ring expressions with oo symbol in the form:

  oo*sign(..)

Original comment by pearu.peterson on 22 Feb 2008 at 10:19

GoogleCodeExporter commented 9 years ago
To be formally correct,

  oo*(sign(x)+sign(y)*is_unbounded(y))

should read

  oo*(2*sign(x) + (sign(y)-sign(x))*is_unbounded(y)))/2

Original comment by pearu.peterson on 22 Feb 2008 at 10:25

GoogleCodeExporter commented 9 years ago
To support replacing x with 0 in oo*x+oo*y then

  oo * x + oo * y -> oo * sign(sign(x)*abs(sign(y)) + sign(y)*abs(sign(x)))

Original comment by pearu.peterson on 22 Feb 2008 at 10:34

GoogleCodeExporter commented 9 years ago
To support directional infinities on complex plain, all apparences
of sign should be replaced with U1. U1 is a function that scales
any complex number to a unit circle.

Original comment by pearu.peterson on 23 Feb 2008 at 12:08

GoogleCodeExporter commented 9 years ago
It would perhaps be logical to have complex infinity = oo*U1(undefined).

Original comment by fredrik....@gmail.com on 23 Feb 2008 at 12:51

GoogleCodeExporter commented 9 years ago
Current behaviour:
>>> print oo*x + oo*y
oo*(x) + (oo*(y))
>>> oo*x + oo*y
CalculusInfinity(Calculus('x*EqualArg(x, y)'))

Original comment by pearu.peterson on 29 Feb 2008 at 1:24